Path: blob/master/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java
41171 views
/*1* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package com.sun.beans.decoder;2526import com.sun.beans.finder.ConstructorFinder;2728import java.lang.reflect.Array;29import java.lang.reflect.Constructor;3031import java.util.ArrayList;32import java.util.List;3334/**35* This class is intended to handle <new> element.36* It describes instantiation of the object.37* The {@code class} attribute denotes38* the name of the class to instantiate.39* The inner elements specifies the arguments of the constructor.40* For example:<pre>41* <new class="java.lang.Long">42* <string>10</string>43* </new></pre>44* is equivalent to {@code Long.valueOf("10")} in Java code.45* <p>The following attributes are supported:46* <dl>47* <dt>class48* <dd>the type of object for instantiation49* <dt>id50* <dd>the identifier of the variable that is intended to store the result51* </dl>52*53* @since 1.754*55* @author Sergey A. Malenkov56*/57class NewElementHandler extends ElementHandler {58private List<Object> arguments = new ArrayList<Object>();59private ValueObject value = ValueObjectImpl.VOID;6061private Class<?> type;6263/**64* Parses attributes of the element.65* The following attributes are supported:66* <dl>67* <dt>class68* <dd>the type of object for instantiation69* <dt>id70* <dd>the identifier of the variable that is intended to store the result71* </dl>72*73* @param name the attribute name74* @param value the attribute value75*/76@Override77public void addAttribute(String name, String value) {78if (name.equals("class")) { // NON-NLS: the attribute name79this.type = getOwner().findClass(value);80} else {81super.addAttribute(name, value);82}83}8485/**86* Adds the argument to the list of arguments87* that is used to calculate the value of this element.88*89* @param argument the value of the element that contained in this one90*/91@Override92protected final void addArgument(Object argument) {93if (this.arguments == null) {94throw new IllegalStateException("Could not add argument to evaluated element");95}96this.arguments.add(argument);97}9899/**100* Returns the context of the method.101* The context of the static method is the class object.102* The context of the non-static method is the value of the parent element.103*104* @return the context of the method105*/106@Override107protected final Object getContextBean() {108return (this.type != null)109? this.type110: super.getContextBean();111}112113/**114* Returns the value of this element.115*116* @return the value of this element117*/118@Override119protected final ValueObject getValueObject() {120if (this.arguments != null) {121try {122this.value = getValueObject(this.type, this.arguments.toArray());123}124catch (Exception exception) {125getOwner().handleException(exception);126}127finally {128this.arguments = null;129}130}131return this.value;132}133134/**135* Calculates the value of this element136* using the base class and the array of arguments.137* By default, it creates an instance of the base class.138* This method should be overridden in those handlers139* that extend behavior of this element.140*141* @param type the base class142* @param args the array of arguments143* @return the value of this element144* @throws Exception if calculation is failed145*/146ValueObject getValueObject(Class<?> type, Object[] args) throws Exception {147if (type == null) {148throw new IllegalArgumentException("Class name is not set");149}150Class<?>[] types = getArgumentTypes(args);151Constructor<?> constructor = ConstructorFinder.findConstructor(type, types);152if (constructor.isVarArgs()) {153args = getArguments(args, constructor.getParameterTypes());154}155return ValueObjectImpl.create(constructor.newInstance(args));156}157158/**159* Converts the array of arguments to the array of corresponding classes.160* If argument is {@code null} the class is {@code null} too.161*162* @param arguments the array of arguments163* @return the array of corresponding classes164*/165static Class<?>[] getArgumentTypes(Object[] arguments) {166Class<?>[] types = new Class<?>[arguments.length];167for (int i = 0; i < arguments.length; i++) {168if (arguments[i] != null) {169types[i] = arguments[i].getClass();170}171}172return types;173}174175/**176* Resolves variable arguments.177*178* @param arguments the array of arguments179* @param types the array of parameter types180* @return the resolved array of arguments181*/182static Object[] getArguments(Object[] arguments, Class<?>[] types) {183int index = types.length - 1;184if (types.length == arguments.length) {185Object argument = arguments[index];186if (argument == null) {187return arguments;188}189Class<?> type = types[index];190if (type.isAssignableFrom(argument.getClass())) {191return arguments;192}193}194int length = arguments.length - index;195Class<?> type = types[index].getComponentType();196Object array = Array.newInstance(type, length);197System.arraycopy(arguments, index, array, 0, length);198199Object[] args = new Object[types.length];200System.arraycopy(arguments, 0, args, 0, index);201args[index] = array;202return args;203}204}205206207