Path: blob/master/src/java.desktop/share/classes/java/beans/MetaData.java
41152 views
/*1* Copyright (c) 2000, 2021, 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 java.beans;2526import com.sun.beans.finder.PrimitiveWrapperMap;2728import java.awt.AWTKeyStroke;29import java.awt.BorderLayout;30import java.awt.Dimension;31import java.awt.Color;32import java.awt.Font;33import java.awt.GridBagConstraints;34import java.awt.Insets;35import java.awt.Point;36import java.awt.Rectangle;37import java.awt.event.KeyEvent;38import java.awt.font.TextAttribute;3940import java.lang.reflect.Array;41import java.lang.reflect.Constructor;42import java.lang.reflect.Field;43import java.lang.reflect.Method;44import java.lang.reflect.Modifier;45import java.lang.reflect.InvocationTargetException;4647import java.security.AccessController;48import java.security.PrivilegedAction;4950import java.util.*;5152import javax.swing.Box;53import javax.swing.JLayeredPane;54import javax.swing.border.MatteBorder;55import javax.swing.plaf.ColorUIResource;5657import sun.swing.PrintColorUIResource;5859import static sun.reflect.misc.ReflectUtil.isPackageAccessible;6061/*62* Like the {@code Intropector}, the {@code MetaData} class63* contains <em>meta</em> objects that describe the way64* classes should express their state in terms of their65* own public APIs.66*67* @see java.beans.Intropector68*69* @author Philip Milne70* @author Steve Langley71*/72class MetaData {7374static final class NullPersistenceDelegate extends PersistenceDelegate {75// Note this will be called by all classes when they reach the76// top of their superclass chain.77protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {78}79protected Expression instantiate(Object oldInstance, Encoder out) { return null; }8081public void writeObject(Object oldInstance, Encoder out) {82// System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);83}84}8586/**87* The persistence delegate for {@code enum} classes.88*89* @author Sergey A. Malenkov90*/91static final class EnumPersistenceDelegate extends PersistenceDelegate {92protected boolean mutatesTo(Object oldInstance, Object newInstance) {93return oldInstance == newInstance;94}9596protected Expression instantiate(Object oldInstance, Encoder out) {97Enum<?> e = (Enum<?>) oldInstance;98return new Expression(e, Enum.class, "valueOf", new Object[]{e.getDeclaringClass(), e.name()});99}100}101102static final class PrimitivePersistenceDelegate extends PersistenceDelegate {103protected boolean mutatesTo(Object oldInstance, Object newInstance) {104return oldInstance.equals(newInstance);105}106107protected Expression instantiate(Object oldInstance, Encoder out) {108return new Expression(oldInstance, oldInstance.getClass(),109"new", new Object[]{oldInstance.toString()});110}111}112113static final class ArrayPersistenceDelegate extends PersistenceDelegate {114protected boolean mutatesTo(Object oldInstance, Object newInstance) {115return (newInstance != null &&116oldInstance.getClass() == newInstance.getClass() && // Also ensures the subtype is correct.117Array.getLength(oldInstance) == Array.getLength(newInstance));118}119120protected Expression instantiate(Object oldInstance, Encoder out) {121// System.out.println("instantiate: " + type + " " + oldInstance);122Class<?> oldClass = oldInstance.getClass();123return new Expression(oldInstance, Array.class, "newInstance",124new Object[]{oldClass.getComponentType(),125Array.getLength(oldInstance)});126}127128protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {129int n = Array.getLength(oldInstance);130for (int i = 0; i < n; i++) {131Object index = i;132// Expression oldGetExp = new Expression(Array.class, "get", new Object[]{oldInstance, index});133// Expression newGetExp = new Expression(Array.class, "get", new Object[]{newInstance, index});134Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});135Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});136try {137Object oldValue = oldGetExp.getValue();138Object newValue = newGetExp.getValue();139out.writeExpression(oldGetExp);140if (!Objects.equals(newValue, out.get(oldValue))) {141// System.out.println("Not equal: " + newGetExp + " != " + actualGetExp);142// invokeStatement(Array.class, "set", new Object[]{oldInstance, index, oldValue}, out);143DefaultPersistenceDelegate.invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);144}145}146catch (Exception e) {147// System.err.println("Warning:: failed to write: " + oldGetExp);148out.getExceptionListener().exceptionThrown(e);149}150}151}152}153154static final class ProxyPersistenceDelegate extends PersistenceDelegate {155protected Expression instantiate(Object oldInstance, Encoder out) {156Class<?> type = oldInstance.getClass();157java.lang.reflect.Proxy p = (java.lang.reflect.Proxy)oldInstance;158// This unappealing hack is not required but makes the159// representation of EventHandlers much more concise.160java.lang.reflect.InvocationHandler ih = java.lang.reflect.Proxy.getInvocationHandler(p);161if (ih instanceof EventHandler) {162EventHandler eh = (EventHandler)ih;163Vector<Object> args = new Vector<>();164args.add(type.getInterfaces()[0]);165args.add(eh.getTarget());166args.add(eh.getAction());167if (eh.getEventPropertyName() != null) {168args.add(eh.getEventPropertyName());169}170if (eh.getListenerMethodName() != null) {171args.setSize(4);172args.add(eh.getListenerMethodName());173}174return new Expression(oldInstance,175EventHandler.class,176"create",177args.toArray());178}179return new Expression(oldInstance,180java.lang.reflect.Proxy.class,181"newProxyInstance",182new Object[]{type.getClassLoader(),183type.getInterfaces(),184ih});185}186}187188// Strings189static final class java_lang_String_PersistenceDelegate extends PersistenceDelegate {190protected Expression instantiate(Object oldInstance, Encoder out) { return null; }191192public void writeObject(Object oldInstance, Encoder out) {193// System.out.println("NullPersistenceDelegate:writeObject " + oldInstance);194}195}196197// Classes198static final class java_lang_Class_PersistenceDelegate extends PersistenceDelegate {199protected boolean mutatesTo(Object oldInstance, Object newInstance) {200return oldInstance.equals(newInstance);201}202203protected Expression instantiate(Object oldInstance, Encoder out) {204Class<?> c = (Class)oldInstance;205// As of 1.3 it is not possible to call Class.forName("int"),206// so we have to generate different code for primitive types.207// This is needed for arrays whose subtype may be primitive.208if (c.isPrimitive()) {209Field field = null;210try {211field = PrimitiveWrapperMap.getType(c.getName()).getDeclaredField("TYPE");212} catch (NoSuchFieldException ex) {213System.err.println("Unknown primitive type: " + c);214}215return new Expression(oldInstance, field, "get", new Object[]{null});216}217else if (oldInstance == String.class) {218return new Expression(oldInstance, "", "getClass", new Object[]{});219}220else if (oldInstance == Class.class) {221return new Expression(oldInstance, String.class, "getClass", new Object[]{});222}223else {224Expression newInstance = new Expression(oldInstance, Class.class, "forName", new Object[] { c.getName() });225newInstance.loader = c.getClassLoader();226return newInstance;227}228}229}230231// Fields232static final class java_lang_reflect_Field_PersistenceDelegate extends PersistenceDelegate {233protected boolean mutatesTo(Object oldInstance, Object newInstance) {234return oldInstance.equals(newInstance);235}236237protected Expression instantiate(Object oldInstance, Encoder out) {238Field f = (Field)oldInstance;239return new Expression(oldInstance,240f.getDeclaringClass(),241"getField",242new Object[]{f.getName()});243}244}245246// Methods247static final class java_lang_reflect_Method_PersistenceDelegate extends PersistenceDelegate {248protected boolean mutatesTo(Object oldInstance, Object newInstance) {249return oldInstance.equals(newInstance);250}251252protected Expression instantiate(Object oldInstance, Encoder out) {253Method m = (Method)oldInstance;254return new Expression(oldInstance,255m.getDeclaringClass(),256"getMethod",257new Object[]{m.getName(), m.getParameterTypes()});258}259}260261// Dates262263/**264* The persistence delegate for {@code java.util.Date} classes.265* Do not extend DefaultPersistenceDelegate to improve performance and266* to avoid problems with {@code java.sql.Date},267* {@code java.sql.Time} and {@code java.sql.Timestamp}.268*269* @author Sergey A. Malenkov270*/271static class java_util_Date_PersistenceDelegate extends PersistenceDelegate {272protected boolean mutatesTo(Object oldInstance, Object newInstance) {273if (!super.mutatesTo(oldInstance, newInstance)) {274return false;275}276Date oldDate = (Date)oldInstance;277Date newDate = (Date)newInstance;278279return oldDate.getTime() == newDate.getTime();280}281282protected Expression instantiate(Object oldInstance, Encoder out) {283Date date = (Date)oldInstance;284return new Expression(date, date.getClass(), "new", new Object[] {date.getTime()});285}286}287288/**289* The persistence delegate for {@code java.sql.Timestamp} classes.290* It supports nanoseconds.291*292* @author Sergey A. Malenkov293*/294static final class java_sql_Timestamp_PersistenceDelegate extends java_util_Date_PersistenceDelegate {295private static final Method getNanosMethod = getNanosMethod();296297private static Method getNanosMethod() {298try {299Class<?> c = Class.forName("java.sql.Timestamp", true, ClassLoader.getPlatformClassLoader());300return c.getMethod("getNanos");301} catch (ClassNotFoundException e) {302return null;303} catch (NoSuchMethodException e) {304throw new AssertionError(e);305}306}307308/**309* Invoke Timstamp getNanos.310*/311private static int getNanos(Object obj) {312if (getNanosMethod == null)313throw new AssertionError("Should not get here");314try {315return (Integer)getNanosMethod.invoke(obj);316} catch (InvocationTargetException e) {317Throwable cause = e.getCause();318if (cause instanceof RuntimeException)319throw (RuntimeException)cause;320if (cause instanceof Error)321throw (Error)cause;322throw new AssertionError(e);323} catch (IllegalAccessException iae) {324throw new AssertionError(iae);325}326}327328protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {329// assumes oldInstance and newInstance are Timestamps330int nanos = getNanos(oldInstance);331if (nanos != getNanos(newInstance)) {332out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos}));333}334}335}336337// Collections338339/*340The Hashtable and AbstractMap classes have no common ancestor yet may341be handled with a single persistence delegate: one which uses the methods342of the Map insterface exclusively. Attatching the persistence delegates343to the interfaces themselves is fraught however since, in the case of344the Map, both the AbstractMap and HashMap classes are declared to345implement the Map interface, leaving the obvious implementation prone346to repeating their initialization. These issues and questions around347the ordering of delegates attached to interfaces have lead us to348ignore any delegates attached to interfaces and force all persistence349delegates to be registered with concrete classes.350*/351352/**353* The base class for persistence delegates for inner classes354* that can be created using {@link Collections}.355*356* @author Sergey A. Malenkov357*/358private abstract static class java_util_Collections extends PersistenceDelegate {359protected boolean mutatesTo(Object oldInstance, Object newInstance) {360if (!super.mutatesTo(oldInstance, newInstance)) {361return false;362}363if ((oldInstance instanceof List) || (oldInstance instanceof Set) || (oldInstance instanceof Map)) {364return oldInstance.equals(newInstance);365}366Collection<?> oldC = (Collection<?>) oldInstance;367Collection<?> newC = (Collection<?>) newInstance;368return (oldC.size() == newC.size()) && oldC.containsAll(newC);369}370371protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {372// do not initialize these custom collections in default way373}374375static final class EmptyList_PersistenceDelegate extends java_util_Collections {376protected Expression instantiate(Object oldInstance, Encoder out) {377return new Expression(oldInstance, Collections.class, "emptyList", null);378}379}380381static final class EmptySet_PersistenceDelegate extends java_util_Collections {382protected Expression instantiate(Object oldInstance, Encoder out) {383return new Expression(oldInstance, Collections.class, "emptySet", null);384}385}386387static final class EmptyMap_PersistenceDelegate extends java_util_Collections {388protected Expression instantiate(Object oldInstance, Encoder out) {389return new Expression(oldInstance, Collections.class, "emptyMap", null);390}391}392393static final class SingletonList_PersistenceDelegate extends java_util_Collections {394protected Expression instantiate(Object oldInstance, Encoder out) {395List<?> list = (List<?>) oldInstance;396return new Expression(oldInstance, Collections.class, "singletonList", new Object[]{list.get(0)});397}398}399400static final class SingletonSet_PersistenceDelegate extends java_util_Collections {401protected Expression instantiate(Object oldInstance, Encoder out) {402Set<?> set = (Set<?>) oldInstance;403return new Expression(oldInstance, Collections.class, "singleton", new Object[]{set.iterator().next()});404}405}406407static final class SingletonMap_PersistenceDelegate extends java_util_Collections {408protected Expression instantiate(Object oldInstance, Encoder out) {409Map<?,?> map = (Map<?,?>) oldInstance;410Object key = map.keySet().iterator().next();411return new Expression(oldInstance, Collections.class, "singletonMap", new Object[]{key, map.get(key)});412}413}414415static final class UnmodifiableCollection_PersistenceDelegate extends java_util_Collections {416protected Expression instantiate(Object oldInstance, Encoder out) {417List<?> list = new ArrayList<>((Collection<?>) oldInstance);418return new Expression(oldInstance, Collections.class, "unmodifiableCollection", new Object[]{list});419}420}421422static final class UnmodifiableList_PersistenceDelegate extends java_util_Collections {423protected Expression instantiate(Object oldInstance, Encoder out) {424List<?> list = new LinkedList<>((Collection<?>) oldInstance);425return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});426}427}428429static final class UnmodifiableRandomAccessList_PersistenceDelegate extends java_util_Collections {430protected Expression instantiate(Object oldInstance, Encoder out) {431List<?> list = new ArrayList<>((Collection<?>) oldInstance);432return new Expression(oldInstance, Collections.class, "unmodifiableList", new Object[]{list});433}434}435436static final class UnmodifiableSet_PersistenceDelegate extends java_util_Collections {437protected Expression instantiate(Object oldInstance, Encoder out) {438Set<?> set = new HashSet<>((Set<?>) oldInstance);439return new Expression(oldInstance, Collections.class, "unmodifiableSet", new Object[]{set});440}441}442443static final class UnmodifiableSortedSet_PersistenceDelegate extends java_util_Collections {444protected Expression instantiate(Object oldInstance, Encoder out) {445SortedSet<?> set = new TreeSet<>((SortedSet<?>) oldInstance);446return new Expression(oldInstance, Collections.class, "unmodifiableSortedSet", new Object[]{set});447}448}449450static final class UnmodifiableMap_PersistenceDelegate extends java_util_Collections {451protected Expression instantiate(Object oldInstance, Encoder out) {452Map<?,?> map = new HashMap<>((Map<?,?>) oldInstance);453return new Expression(oldInstance, Collections.class, "unmodifiableMap", new Object[]{map});454}455}456457static final class UnmodifiableSortedMap_PersistenceDelegate extends java_util_Collections {458protected Expression instantiate(Object oldInstance, Encoder out) {459SortedMap<?,?> map = new TreeMap<>((SortedMap<?,?>) oldInstance);460return new Expression(oldInstance, Collections.class, "unmodifiableSortedMap", new Object[]{map});461}462}463464static final class SynchronizedCollection_PersistenceDelegate extends java_util_Collections {465protected Expression instantiate(Object oldInstance, Encoder out) {466List<?> list = new ArrayList<>((Collection<?>) oldInstance);467return new Expression(oldInstance, Collections.class, "synchronizedCollection", new Object[]{list});468}469}470471static final class SynchronizedList_PersistenceDelegate extends java_util_Collections {472protected Expression instantiate(Object oldInstance, Encoder out) {473List<?> list = new LinkedList<>((Collection<?>) oldInstance);474return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});475}476}477478static final class SynchronizedRandomAccessList_PersistenceDelegate extends java_util_Collections {479protected Expression instantiate(Object oldInstance, Encoder out) {480List<?> list = new ArrayList<>((Collection<?>) oldInstance);481return new Expression(oldInstance, Collections.class, "synchronizedList", new Object[]{list});482}483}484485static final class SynchronizedSet_PersistenceDelegate extends java_util_Collections {486protected Expression instantiate(Object oldInstance, Encoder out) {487Set<?> set = new HashSet<>((Set<?>) oldInstance);488return new Expression(oldInstance, Collections.class, "synchronizedSet", new Object[]{set});489}490}491492static final class SynchronizedSortedSet_PersistenceDelegate extends java_util_Collections {493protected Expression instantiate(Object oldInstance, Encoder out) {494SortedSet<?> set = new TreeSet<>((SortedSet<?>) oldInstance);495return new Expression(oldInstance, Collections.class, "synchronizedSortedSet", new Object[]{set});496}497}498499static final class SynchronizedMap_PersistenceDelegate extends java_util_Collections {500protected Expression instantiate(Object oldInstance, Encoder out) {501Map<?,?> map = new HashMap<>((Map<?,?>) oldInstance);502return new Expression(oldInstance, Collections.class, "synchronizedMap", new Object[]{map});503}504}505506static final class SynchronizedSortedMap_PersistenceDelegate extends java_util_Collections {507protected Expression instantiate(Object oldInstance, Encoder out) {508SortedMap<?,?> map = new TreeMap<>((SortedMap<?,?>) oldInstance);509return new Expression(oldInstance, Collections.class, "synchronizedSortedMap", new Object[]{map});510}511}512}513514// Collection515static class java_util_Collection_PersistenceDelegate extends DefaultPersistenceDelegate {516protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {517java.util.Collection<?> oldO = (java.util.Collection)oldInstance;518java.util.Collection<?> newO = (java.util.Collection)newInstance;519520if (newO.size() != 0) {521invokeStatement(oldInstance, "clear", new Object[]{}, out);522}523for (Iterator<?> i = oldO.iterator(); i.hasNext();) {524invokeStatement(oldInstance, "add", new Object[]{i.next()}, out);525}526}527}528529// List530static class java_util_List_PersistenceDelegate extends DefaultPersistenceDelegate {531protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {532java.util.List<?> oldO = (java.util.List<?>)oldInstance;533java.util.List<?> newO = (java.util.List<?>)newInstance;534int oldSize = oldO.size();535int newSize = (newO == null) ? 0 : newO.size();536if (oldSize < newSize) {537invokeStatement(oldInstance, "clear", new Object[]{}, out);538newSize = 0;539}540for (int i = 0; i < newSize; i++) {541Object index = i;542543Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{index});544Expression newGetExp = new Expression(newInstance, "get", new Object[]{index});545try {546Object oldValue = oldGetExp.getValue();547Object newValue = newGetExp.getValue();548out.writeExpression(oldGetExp);549if (!Objects.equals(newValue, out.get(oldValue))) {550invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);551}552}553catch (Exception e) {554out.getExceptionListener().exceptionThrown(e);555}556}557for (int i = newSize; i < oldSize; i++) {558invokeStatement(oldInstance, "add", new Object[]{oldO.get(i)}, out);559}560}561}562563564// Map565static class java_util_Map_PersistenceDelegate extends DefaultPersistenceDelegate {566protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {567// System.out.println("Initializing: " + newInstance);568java.util.Map<?,?> oldMap = (java.util.Map)oldInstance;569java.util.Map<?,?> newMap = (java.util.Map)newInstance;570// Remove the new elements.571// Do this first otherwise we undo the adding work.572if (newMap != null) {573for (Object newKey : newMap.keySet().toArray()) {574// PENDING: This "key" is not in the right environment.575if (!oldMap.containsKey(newKey)) {576invokeStatement(oldInstance, "remove", new Object[]{newKey}, out);577}578}579}580// Add the new elements.581for ( Object oldKey : oldMap.keySet() ) {582Expression oldGetExp = new Expression(oldInstance, "get", new Object[]{oldKey});583// Pending: should use newKey.584Expression newGetExp = new Expression(newInstance, "get", new Object[]{oldKey});585try {586Object oldValue = oldGetExp.getValue();587Object newValue = newGetExp.getValue();588out.writeExpression(oldGetExp);589if (!Objects.equals(newValue, out.get(oldValue))) {590invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);591} else if ((newValue == null) && !newMap.containsKey(oldKey)) {592// put oldValue(=null?) if oldKey is absent in newMap593invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);594}595}596catch (Exception e) {597out.getExceptionListener().exceptionThrown(e);598}599}600}601}602603static final class java_util_AbstractCollection_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}604static final class java_util_AbstractList_PersistenceDelegate extends java_util_List_PersistenceDelegate {}605static final class java_util_AbstractMap_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}606static final class java_util_Hashtable_PersistenceDelegate extends java_util_Map_PersistenceDelegate {}607608609// Beans610static final class java_beans_beancontext_BeanContextSupport_PersistenceDelegate extends java_util_Collection_PersistenceDelegate {}611612// AWT613614/**615* The persistence delegate for {@link Insets}.616* It is impossible to use {@link DefaultPersistenceDelegate}617* because this class does not have any properties.618*619* @author Sergey A. Malenkov620*/621static final class java_awt_Insets_PersistenceDelegate extends PersistenceDelegate {622protected boolean mutatesTo(Object oldInstance, Object newInstance) {623return oldInstance.equals(newInstance);624}625626protected Expression instantiate(Object oldInstance, Encoder out) {627Insets insets = (Insets) oldInstance;628Object[] args = new Object[] {629insets.top,630insets.left,631insets.bottom,632insets.right,633};634return new Expression(insets, insets.getClass(), "new", args);635}636}637638/**639* The persistence delegate for {@link Font}.640* It is impossible to use {@link DefaultPersistenceDelegate}641* because size of the font can be float value.642*643* @author Sergey A. Malenkov644*/645static final class java_awt_Font_PersistenceDelegate extends PersistenceDelegate {646protected boolean mutatesTo(Object oldInstance, Object newInstance) {647return oldInstance.equals(newInstance);648}649650protected Expression instantiate(Object oldInstance, Encoder out) {651Font font = (Font) oldInstance;652653int count = 0;654String family = null;655int style = Font.PLAIN;656int size = 12;657658Map<TextAttribute, ?> basic = font.getAttributes();659Map<TextAttribute, Object> clone = new HashMap<>(basic.size());660for (TextAttribute key : basic.keySet()) {661Object value = basic.get(key);662if (value != null) {663clone.put(key, value);664}665if (key == TextAttribute.FAMILY) {666if (value instanceof String) {667count++;668family = (String) value;669}670}671else if (key == TextAttribute.WEIGHT) {672if (TextAttribute.WEIGHT_REGULAR.equals(value)) {673count++;674} else if (TextAttribute.WEIGHT_BOLD.equals(value)) {675count++;676style |= Font.BOLD;677}678}679else if (key == TextAttribute.POSTURE) {680if (TextAttribute.POSTURE_REGULAR.equals(value)) {681count++;682} else if (TextAttribute.POSTURE_OBLIQUE.equals(value)) {683count++;684style |= Font.ITALIC;685}686} else if (key == TextAttribute.SIZE) {687if (value instanceof Number) {688Number number = (Number) value;689size = number.intValue();690if (size == number.floatValue()) {691count++;692}693}694}695}696Class<?> type = font.getClass();697if (count == clone.size()) {698return new Expression(font, type, "new", new Object[]{family, style, size});699}700if (type == Font.class) {701return new Expression(font, type, "getFont", new Object[]{clone});702}703return new Expression(font, type, "new", new Object[]{Font.getFont(clone)});704}705}706707/**708* The persistence delegate for {@link AWTKeyStroke}.709* It is impossible to use {@link DefaultPersistenceDelegate}710* because this class have no public constructor.711*712* @author Sergey A. Malenkov713*/714static final class java_awt_AWTKeyStroke_PersistenceDelegate extends PersistenceDelegate {715protected boolean mutatesTo(Object oldInstance, Object newInstance) {716return oldInstance.equals(newInstance);717}718719protected Expression instantiate(Object oldInstance, Encoder out) {720AWTKeyStroke key = (AWTKeyStroke) oldInstance;721722char ch = key.getKeyChar();723int code = key.getKeyCode();724int mask = key.getModifiers();725boolean onKeyRelease = key.isOnKeyRelease();726727Object[] args = null;728if (ch == KeyEvent.CHAR_UNDEFINED) {729args = !onKeyRelease730? new Object[]{code, mask}731: new Object[]{code, mask, onKeyRelease};732} else if (code == KeyEvent.VK_UNDEFINED) {733if (!onKeyRelease) {734args = (mask == 0)735? new Object[]{ch}736: new Object[]{ch, mask};737} else if (mask == 0) {738args = new Object[]{ch, onKeyRelease};739}740}741if (args == null) {742throw new IllegalStateException("Unsupported KeyStroke: " + key);743}744Class<?> type = key.getClass();745String name = type.getName();746// get short name of the class747int index = name.lastIndexOf('.') + 1;748if (index > 0) {749name = name.substring(index);750}751return new Expression( key, type, "get" + name, args );752}753}754755static class StaticFieldsPersistenceDelegate extends PersistenceDelegate {756protected void installFields(Encoder out, Class<?> cls) {757if (Modifier.isPublic(cls.getModifiers()) && isPackageAccessible(cls)) {758Field[] fields = cls.getFields();759for(int i = 0; i < fields.length; i++) {760Field field = fields[i];761// Don't install primitives, their identity will not be preserved762// by wrapping.763if (Object.class.isAssignableFrom(field.getType())) {764out.writeExpression(new Expression(field, "get", new Object[]{null}));765}766}767}768}769770protected Expression instantiate(Object oldInstance, Encoder out) {771throw new RuntimeException("Unrecognized instance: " + oldInstance);772}773774public void writeObject(Object oldInstance, Encoder out) {775if (out.getAttribute(this) == null) {776out.setAttribute(this, Boolean.TRUE);777installFields(out, oldInstance.getClass());778}779super.writeObject(oldInstance, out);780}781}782783// SystemColor784static final class java_awt_SystemColor_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}785786// TextAttribute787static final class java_awt_font_TextAttribute_PersistenceDelegate extends StaticFieldsPersistenceDelegate {}788789// MenuShortcut790static final class java_awt_MenuShortcut_PersistenceDelegate extends PersistenceDelegate {791protected boolean mutatesTo(Object oldInstance, Object newInstance) {792return oldInstance.equals(newInstance);793}794795protected Expression instantiate(Object oldInstance, Encoder out) {796java.awt.MenuShortcut m = (java.awt.MenuShortcut)oldInstance;797return new Expression(oldInstance, m.getClass(), "new",798new Object[]{m.getKey(), Boolean.valueOf(m.usesShiftModifier())});799}800}801802// Component803static final class java_awt_Component_PersistenceDelegate extends DefaultPersistenceDelegate {804protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {805super.initialize(type, oldInstance, newInstance, out);806java.awt.Component c = (java.awt.Component)oldInstance;807java.awt.Component c2 = (java.awt.Component)newInstance;808// The "background", "foreground" and "font" properties.809// The foreground and font properties of Windows change from810// null to defined values after the Windows are made visible -811// special case them for now.812if (!(oldInstance instanceof java.awt.Window)) {813Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;814Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;815if (!Objects.equals(oldBackground, newBackground)) {816invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);817}818Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;819Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;820if (!Objects.equals(oldForeground, newForeground)) {821invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);822}823Object oldFont = c.isFontSet() ? c.getFont() : null;824Object newFont = c2.isFontSet() ? c2.getFont() : null;825if (!Objects.equals(oldFont, newFont)) {826invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);827}828}829830// Bounds831java.awt.Container p = c.getParent();832if (p == null || p.getLayout() == null) {833// Use the most concise construct.834boolean locationCorrect = c.getLocation().equals(c2.getLocation());835boolean sizeCorrect = c.getSize().equals(c2.getSize());836if (!locationCorrect && !sizeCorrect) {837invokeStatement(oldInstance, "setBounds", new Object[]{c.getBounds()}, out);838}839else if (!locationCorrect) {840invokeStatement(oldInstance, "setLocation", new Object[]{c.getLocation()}, out);841}842else if (!sizeCorrect) {843invokeStatement(oldInstance, "setSize", new Object[]{c.getSize()}, out);844}845}846}847}848849// Container850static final class java_awt_Container_PersistenceDelegate extends DefaultPersistenceDelegate {851protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {852super.initialize(type, oldInstance, newInstance, out);853// Ignore the children of a JScrollPane.854// Pending(milne) find a better way to do this.855if (oldInstance instanceof javax.swing.JScrollPane) {856return;857}858java.awt.Container oldC = (java.awt.Container)oldInstance;859java.awt.Component[] oldChildren = oldC.getComponents();860java.awt.Container newC = (java.awt.Container)newInstance;861java.awt.Component[] newChildren = (newC == null) ? new java.awt.Component[0] : newC.getComponents();862863BorderLayout layout = ( oldC.getLayout() instanceof BorderLayout )864? ( BorderLayout )oldC.getLayout()865: null;866867JLayeredPane oldLayeredPane = (oldInstance instanceof JLayeredPane)868? (JLayeredPane) oldInstance869: null;870871// Pending. Assume all the new children are unaltered.872for(int i = newChildren.length; i < oldChildren.length; i++) {873Object[] args = ( layout != null )874? new Object[] {oldChildren[i], layout.getConstraints( oldChildren[i] )}875: (oldLayeredPane != null)876? new Object[] {oldChildren[i], oldLayeredPane.getLayer(oldChildren[i]), Integer.valueOf(-1)}877: new Object[] {oldChildren[i]};878879invokeStatement(oldInstance, "add", args, out);880}881}882}883884// Choice885static final class java_awt_Choice_PersistenceDelegate extends DefaultPersistenceDelegate {886protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {887super.initialize(type, oldInstance, newInstance, out);888java.awt.Choice m = (java.awt.Choice)oldInstance;889java.awt.Choice n = (java.awt.Choice)newInstance;890for (int i = n.getItemCount(); i < m.getItemCount(); i++) {891invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);892}893}894}895896// Menu897static final class java_awt_Menu_PersistenceDelegate extends DefaultPersistenceDelegate {898protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {899super.initialize(type, oldInstance, newInstance, out);900java.awt.Menu m = (java.awt.Menu)oldInstance;901java.awt.Menu n = (java.awt.Menu)newInstance;902for (int i = n.getItemCount(); i < m.getItemCount(); i++) {903invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);904}905}906}907908// MenuBar909static final class java_awt_MenuBar_PersistenceDelegate extends DefaultPersistenceDelegate {910protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {911super.initialize(type, oldInstance, newInstance, out);912java.awt.MenuBar m = (java.awt.MenuBar)oldInstance;913java.awt.MenuBar n = (java.awt.MenuBar)newInstance;914for (int i = n.getMenuCount(); i < m.getMenuCount(); i++) {915invokeStatement(oldInstance, "add", new Object[]{m.getMenu(i)}, out);916}917}918}919920// List921static final class java_awt_List_PersistenceDelegate extends DefaultPersistenceDelegate {922protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {923super.initialize(type, oldInstance, newInstance, out);924java.awt.List m = (java.awt.List)oldInstance;925java.awt.List n = (java.awt.List)newInstance;926for (int i = n.getItemCount(); i < m.getItemCount(); i++) {927invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);928}929}930}931932933// LayoutManagers934935// BorderLayout936static final class java_awt_BorderLayout_PersistenceDelegate extends DefaultPersistenceDelegate {937private static final String[] CONSTRAINTS = {938BorderLayout.NORTH,939BorderLayout.SOUTH,940BorderLayout.EAST,941BorderLayout.WEST,942BorderLayout.CENTER,943BorderLayout.PAGE_START,944BorderLayout.PAGE_END,945BorderLayout.LINE_START,946BorderLayout.LINE_END,947};948@Override949protected void initialize(Class<?> type, Object oldInstance,950Object newInstance, Encoder out) {951super.initialize(type, oldInstance, newInstance, out);952BorderLayout oldLayout = (BorderLayout) oldInstance;953BorderLayout newLayout = (BorderLayout) newInstance;954for (String constraints : CONSTRAINTS) {955Object oldC = oldLayout.getLayoutComponent(constraints);956Object newC = newLayout.getLayoutComponent(constraints);957// Pending, assume any existing elements are OK.958if (oldC != null && newC == null) {959invokeStatement(oldInstance, "addLayoutComponent",960new Object[] { oldC, constraints }, out);961}962}963}964}965966// CardLayout967static final class java_awt_CardLayout_PersistenceDelegate extends DefaultPersistenceDelegate {968protected void initialize(Class<?> type, Object oldInstance,969Object newInstance, Encoder out) {970super.initialize(type, oldInstance, newInstance, out);971if (getVector(newInstance).isEmpty()) {972for (Object card : getVector(oldInstance)) {973Object[] args = {MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.name"),974MetaData.getPrivateFieldValue(card, "java.awt.CardLayout$Card.comp")};975invokeStatement(oldInstance, "addLayoutComponent", args, out);976}977}978}979protected boolean mutatesTo(Object oldInstance, Object newInstance) {980return super.mutatesTo(oldInstance, newInstance) && getVector(newInstance).isEmpty();981}982private static Vector<?> getVector(Object instance) {983return (Vector<?>) MetaData.getPrivateFieldValue(instance, "java.awt.CardLayout.vector");984}985}986987// GridBagLayout988static final class java_awt_GridBagLayout_PersistenceDelegate extends DefaultPersistenceDelegate {989protected void initialize(Class<?> type, Object oldInstance,990Object newInstance, Encoder out) {991super.initialize(type, oldInstance, newInstance, out);992if (getHashtable(newInstance).isEmpty()) {993for (Map.Entry<?,?> entry : getHashtable(oldInstance).entrySet()) {994Object[] args = {entry.getKey(), entry.getValue()};995invokeStatement(oldInstance, "addLayoutComponent", args, out);996}997}998}999protected boolean mutatesTo(Object oldInstance, Object newInstance) {1000return super.mutatesTo(oldInstance, newInstance) && getHashtable(newInstance).isEmpty();1001}1002private static Hashtable<?,?> getHashtable(Object instance) {1003return (Hashtable<?,?>) MetaData.getPrivateFieldValue(instance, "java.awt.GridBagLayout.comptable");1004}1005}10061007// Swing10081009// JFrame (If we do this for Window instead of JFrame, the setVisible call1010// will be issued before we have added all the children to the JFrame and1011// will appear blank).1012static final class javax_swing_JFrame_PersistenceDelegate extends DefaultPersistenceDelegate {1013protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1014super.initialize(type, oldInstance, newInstance, out);1015java.awt.Window oldC = (java.awt.Window)oldInstance;1016java.awt.Window newC = (java.awt.Window)newInstance;1017boolean oldV = oldC.isVisible();1018boolean newV = newC.isVisible();1019if (newV != oldV) {1020// false means: don't execute this statement at write time.1021boolean executeStatements = out.executeStatements;1022out.executeStatements = false;1023invokeStatement(oldInstance, "setVisible", new Object[]{Boolean.valueOf(oldV)}, out);1024out.executeStatements = executeStatements;1025}1026}1027}10281029// Models10301031// DefaultListModel1032static final class javax_swing_DefaultListModel_PersistenceDelegate extends DefaultPersistenceDelegate {1033protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1034// Note, the "size" property will be set here.1035super.initialize(type, oldInstance, newInstance, out);1036javax.swing.DefaultListModel<?> m = (javax.swing.DefaultListModel<?>)oldInstance;1037javax.swing.DefaultListModel<?> n = (javax.swing.DefaultListModel<?>)newInstance;1038for (int i = n.getSize(); i < m.getSize(); i++) {1039invokeStatement(oldInstance, "add", // Can also use "addElement".1040new Object[]{m.getElementAt(i)}, out);1041}1042}1043}10441045// DefaultComboBoxModel1046static final class javax_swing_DefaultComboBoxModel_PersistenceDelegate extends DefaultPersistenceDelegate {1047protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1048super.initialize(type, oldInstance, newInstance, out);1049javax.swing.DefaultComboBoxModel<?> m = (javax.swing.DefaultComboBoxModel<?>)oldInstance;1050for (int i = 0; i < m.getSize(); i++) {1051invokeStatement(oldInstance, "addElement", new Object[]{m.getElementAt(i)}, out);1052}1053}1054}105510561057// DefaultMutableTreeNode1058static final class javax_swing_tree_DefaultMutableTreeNode_PersistenceDelegate extends DefaultPersistenceDelegate {1059protected void initialize(Class<?> type, Object oldInstance, Object1060newInstance, Encoder out) {1061super.initialize(type, oldInstance, newInstance, out);1062javax.swing.tree.DefaultMutableTreeNode m =1063(javax.swing.tree.DefaultMutableTreeNode)oldInstance;1064javax.swing.tree.DefaultMutableTreeNode n =1065(javax.swing.tree.DefaultMutableTreeNode)newInstance;1066for (int i = n.getChildCount(); i < m.getChildCount(); i++) {1067invokeStatement(oldInstance, "add", new1068Object[]{m.getChildAt(i)}, out);1069}1070}1071}10721073// ToolTipManager1074static final class javax_swing_ToolTipManager_PersistenceDelegate extends PersistenceDelegate {1075protected Expression instantiate(Object oldInstance, Encoder out) {1076return new Expression(oldInstance, javax.swing.ToolTipManager.class,1077"sharedInstance", new Object[]{});1078}1079}10801081// JTabbedPane1082static final class javax_swing_JTabbedPane_PersistenceDelegate extends DefaultPersistenceDelegate {1083protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1084super.initialize(type, oldInstance, newInstance, out);1085javax.swing.JTabbedPane p = (javax.swing.JTabbedPane)oldInstance;1086for (int i = 0; i < p.getTabCount(); i++) {1087invokeStatement(oldInstance, "addTab",1088new Object[]{1089p.getTitleAt(i),1090p.getIconAt(i),1091p.getComponentAt(i)}, out);1092}1093}1094}10951096// Box1097static final class javax_swing_Box_PersistenceDelegate extends DefaultPersistenceDelegate {1098protected boolean mutatesTo(Object oldInstance, Object newInstance) {1099return super.mutatesTo(oldInstance, newInstance) && getAxis(oldInstance).equals(getAxis(newInstance));1100}11011102protected Expression instantiate(Object oldInstance, Encoder out) {1103return new Expression(oldInstance, oldInstance.getClass(), "new", new Object[] {getAxis(oldInstance)});1104}11051106private Integer getAxis(Object object) {1107Box box = (Box) object;1108return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis");1109}1110}11111112// JMenu1113// Note that we do not need to state the initialiser for1114// JMenuItems since the getComponents() method defined in1115// Container will return all of the sub menu items that1116// need to be added to the menu item.1117// Not so for JMenu apparently.1118static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {1119protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1120super.initialize(type, oldInstance, newInstance, out);1121javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;1122java.awt.Component[] c = m.getMenuComponents();1123for (int i = 0; i < c.length; i++) {1124invokeStatement(oldInstance, "add", new Object[]{c[i]}, out);1125}1126}1127}11281129/**1130* The persistence delegate for {@link MatteBorder}.1131* It is impossible to use {@link DefaultPersistenceDelegate}1132* because this class does not have writable properties.1133*1134* @author Sergey A. Malenkov1135*/1136static final class javax_swing_border_MatteBorder_PersistenceDelegate extends PersistenceDelegate {1137protected Expression instantiate(Object oldInstance, Encoder out) {1138MatteBorder border = (MatteBorder) oldInstance;1139Insets insets = border.getBorderInsets();1140Object object = border.getTileIcon();1141if (object == null) {1142object = border.getMatteColor();1143}1144Object[] args = new Object[] {1145insets.top,1146insets.left,1147insets.bottom,1148insets.right,1149object,1150};1151return new Expression(border, border.getClass(), "new", args);1152}1153}11541155/* XXX - doens't seem to work. Debug later.1156static final class javax_swing_JMenu_PersistenceDelegate extends DefaultPersistenceDelegate {1157protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {1158super.initialize(type, oldInstance, newInstance, out);1159javax.swing.JMenu m = (javax.swing.JMenu)oldInstance;1160javax.swing.JMenu n = (javax.swing.JMenu)newInstance;1161for (int i = n.getItemCount(); i < m.getItemCount(); i++) {1162invokeStatement(oldInstance, "add", new Object[]{m.getItem(i)}, out);1163}1164}1165}1166*/11671168/**1169* The persistence delegate for {@link PrintColorUIResource}.1170* It is impossible to use {@link DefaultPersistenceDelegate}1171* because this class has special rule for serialization:1172* it should be converted to {@link ColorUIResource}.1173*1174* @see PrintColorUIResource#writeReplace1175*1176* @author Sergey A. Malenkov1177*/1178static final class sun_swing_PrintColorUIResource_PersistenceDelegate extends PersistenceDelegate {1179protected boolean mutatesTo(Object oldInstance, Object newInstance) {1180return oldInstance.equals(newInstance);1181}11821183protected Expression instantiate(Object oldInstance, Encoder out) {1184Color color = (Color) oldInstance;1185Object[] args = new Object[] {color.getRGB()};1186return new Expression(color, ColorUIResource.class, "new", args);1187}1188}11891190private static final Map<String,Field> fields = Collections.synchronizedMap(new WeakHashMap<String, Field>());1191private static Hashtable<String, PersistenceDelegate> internalPersistenceDelegates = new Hashtable<>();11921193private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate();1194private static PersistenceDelegate enumPersistenceDelegate = new EnumPersistenceDelegate();1195private static PersistenceDelegate primitivePersistenceDelegate = new PrimitivePersistenceDelegate();1196private static PersistenceDelegate defaultPersistenceDelegate = new DefaultPersistenceDelegate();1197private static PersistenceDelegate arrayPersistenceDelegate;1198private static PersistenceDelegate proxyPersistenceDelegate;11991200static {12011202internalPersistenceDelegates.put("java.net.URI",1203new PrimitivePersistenceDelegate());12041205// it is possible because MatteBorder is assignable from MatteBorderUIResource1206internalPersistenceDelegates.put("javax.swing.plaf.BorderUIResource$MatteBorderUIResource",1207new javax_swing_border_MatteBorder_PersistenceDelegate());12081209// it is possible because FontUIResource is supported by java_awt_Font_PersistenceDelegate1210internalPersistenceDelegates.put("javax.swing.plaf.FontUIResource",1211new java_awt_Font_PersistenceDelegate());12121213// it is possible because KeyStroke is supported by java_awt_AWTKeyStroke_PersistenceDelegate1214internalPersistenceDelegates.put("javax.swing.KeyStroke",1215new java_awt_AWTKeyStroke_PersistenceDelegate());12161217internalPersistenceDelegates.put("java.sql.Date", new java_util_Date_PersistenceDelegate());1218internalPersistenceDelegates.put("java.sql.Time", new java_util_Date_PersistenceDelegate());1219}12201221@SuppressWarnings({"rawtypes", "deprecation"})1222public static synchronized PersistenceDelegate getPersistenceDelegate(Class type) {1223if (type == null) {1224return nullPersistenceDelegate;1225}1226if (Enum.class.isAssignableFrom(type)) {1227return enumPersistenceDelegate;1228}1229if (null != XMLEncoder.primitiveTypeFor(type)) {1230return primitivePersistenceDelegate;1231}1232// The persistence delegate for arrays is non-trivial; instantiate it lazily.1233if (type.isArray()) {1234if (arrayPersistenceDelegate == null) {1235arrayPersistenceDelegate = new ArrayPersistenceDelegate();1236}1237return arrayPersistenceDelegate;1238}1239// Handle proxies lazily for backward compatibility with 1.2.1240try {1241if (java.lang.reflect.Proxy.isProxyClass(type)) {1242if (proxyPersistenceDelegate == null) {1243proxyPersistenceDelegate = new ProxyPersistenceDelegate();1244}1245return proxyPersistenceDelegate;1246}1247}1248catch(Exception e) {}1249// else if (type.getDeclaringClass() != null) {1250// return new DefaultPersistenceDelegate(new String[]{"this$0"});1251// }12521253String typeName = type.getName();1254PersistenceDelegate pd = (PersistenceDelegate)getBeanAttribute(type, "persistenceDelegate");1255if (pd == null) {1256pd = internalPersistenceDelegates.get(typeName);1257if (pd != null) {1258return pd;1259}1260internalPersistenceDelegates.put(typeName, defaultPersistenceDelegate);1261try {1262String name = type.getName();1263Class<?> c = Class.forName("java.beans.MetaData$" + name.replace('.', '_')1264+ "_PersistenceDelegate");1265pd = (PersistenceDelegate)c.newInstance();1266internalPersistenceDelegates.put(typeName, pd);1267}1268catch (ClassNotFoundException e) {1269String[] properties = getConstructorProperties(type);1270if (properties != null) {1271pd = new DefaultPersistenceDelegate(properties);1272internalPersistenceDelegates.put(typeName, pd);1273}1274}1275catch (Exception e) {1276System.err.println("Internal error: " + e);1277}1278}12791280return (pd != null) ? pd : defaultPersistenceDelegate;1281}12821283private static String[] getConstructorProperties(Class<?> type) {1284String[] names = null;1285int length = 0;1286for (Constructor<?> constructor : type.getConstructors()) {1287String[] value = getAnnotationValue(constructor);1288if ((value != null) && (length < value.length) && isValid(constructor, value)) {1289names = value;1290length = value.length;1291}1292}1293return names;1294}12951296private static String[] getAnnotationValue(Constructor<?> constructor) {1297ConstructorProperties annotation = constructor.getAnnotation(ConstructorProperties.class);1298return (annotation != null)1299? annotation.value()1300: null;1301}13021303private static boolean isValid(Constructor<?> constructor, String[] names) {1304Class<?>[] parameters = constructor.getParameterTypes();1305if (names.length != parameters.length) {1306return false;1307}1308for (String name : names) {1309if (name == null) {1310return false;1311}1312}1313return true;1314}13151316private static Object getBeanAttribute(Class<?> type, String attribute) {1317try {1318return Introspector.getBeanInfo(type).getBeanDescriptor().getValue(attribute);1319} catch (IntrospectionException exception) {1320return null;1321}1322}13231324@SuppressWarnings("removal")1325static Object getPrivateFieldValue(Object instance, String name) {1326Field field = fields.get(name);1327if (field == null) {1328int index = name.lastIndexOf('.');1329final String className = name.substring(0, index);1330final String fieldName = name.substring(1 + index);1331field = AccessController.doPrivileged(new PrivilegedAction<Field>() {1332public Field run() {1333try {1334Field field = Class.forName(className).getDeclaredField(fieldName);1335field.setAccessible(true);1336return field;1337}1338catch (ClassNotFoundException exception) {1339throw new IllegalStateException("Could not find class", exception);1340}1341catch (NoSuchFieldException exception) {1342throw new IllegalStateException("Could not find field", exception);1343}1344}1345});1346fields.put(name, field);1347}1348try {1349return field.get(instance);1350}1351catch (IllegalAccessException exception) {1352throw new IllegalStateException("Could not get value of the field", exception);1353}1354}1355}135613571358