/** * Create a new CachedIntrospectionResults instance for the given class. * * @param beanClass the bean class to analyze * @throws BeansException in case of introspection failure */ private CachedIntrospectionResults(Class beanClass) throws BeansException { try { if (logger.isTraceEnabled()) { logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]"); } this.beanInfo = Introspector.getBeanInfo(beanClass); // Immediately remove class from Introspector cache, to allow for proper // garbage collection on class loader shutdown - we cache it here anyway, // in a GC-friendly manner. In contrast to CachedIntrospectionResults, // Introspector does not use WeakReferences as values of its WeakHashMap! Class classToFlush = beanClass; do { Introspector.flushFromCaches(classToFlush); classToFlush = classToFlush.getSuperclass(); } while (classToFlush != null); if (logger.isTraceEnabled()) { logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]"); } this.propertyDescriptorCache = new HashMap(); // This call is slow so we do it once. PropertyDescriptor[] pds = this.beanInfo.getPropertyDescriptors(); for (int i = 0; i < pds.length; i++) { PropertyDescriptor pd = pds[i]; if (logger.isTraceEnabled()) { logger.trace( "Found bean property '" + pd.getName() + "'" + (pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") + (pd.getPropertyEditorClass() != null ? "; editor [" + pd.getPropertyEditorClass().getName() + "]" : "")); } if (JdkVersion.isAtLeastJava15()) { pd = new GenericTypeAwarePropertyDescriptor( beanClass, pd.getName(), pd.getReadMethod(), pd.getWriteMethod(), pd.getPropertyEditorClass()); } this.propertyDescriptorCache.put(pd.getName(), pd); } } catch (IntrospectionException ex) { throw new FatalBeanException( "Cannot get BeanInfo for object of class [" + beanClass.getName() + "]", ex); } }
/** * Compares this <code>PropertyDescriptor</code> against the specified object. Returns true if the * objects are the same. Two <code>PropertyDescriptor</code>s are the same if the read, write, * property types, property editor and flags are equivalent. * * @since 1.4 */ public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj instanceof PropertyDescriptor) { PropertyDescriptor other = (PropertyDescriptor) obj; Method otherReadMethod = other.getReadMethod(); Method otherWriteMethod = other.getWriteMethod(); if (!compareMethods(getReadMethod(), otherReadMethod)) { return false; } if (!compareMethods(getWriteMethod(), otherWriteMethod)) { return false; } if (getPropertyType() == other.getPropertyType() && getPropertyEditorClass() == other.getPropertyEditorClass() && bound == other.isBound() && constrained == other.isConstrained() && writeMethodName == other.writeMethodName && readMethodName == other.readMethodName) { return true; } } return false; }
/** * Get the appropriate editor for the given property. * * @param prop Property to get editor for. * @return Editor to use, or null if none found. */ private PropertyEditor getEditorForProperty(PropertyDescriptor prop) { PropertyEditor retval = null; Class type = prop.getPropertyEditorClass(); if (type != null) { try { retval = (PropertyEditor) type.newInstance(); } catch (Exception ex) { ex.printStackTrace(); } } // Handle case where there is no special editor // associated with the property. In that case we ask the // PropertyEditor manager for the editor registered for the // given property type. if (retval == null) { Class t = prop.getPropertyType(); if (t != null) { retval = PropertyEditorManager.findEditor(t); } } // In the worse case we resort to the generic editor for Object types. if (retval == null) { retval = PropertyEditorManager.findEditor(Object.class); } return retval; }
@SuppressWarnings({"rawtypes"}) private EditorHelper findHelperFor(PropertyDescriptor prop, Editable subject) { EditorHelper res = null; // is there an explicit editor specified? Class specificEditor = prop.getPropertyEditorClass(); // did we find one? if (specificEditor != null) { Object theEditor = null; try { theEditor = specificEditor.newInstance(); } catch (Exception e) { CorePlugin.logError(Status.ERROR, "whilst finding helper", e); } if (theEditor instanceof java.beans.PropertyEditor) { final java.beans.PropertyEditor propEditor = (java.beans.PropertyEditor) theEditor; // ok. wrap it. if (!(propEditor instanceof DoNotUseTagEditorInPropertiesView)) { if (propEditor.getTags() != null) { // ok - do one of the combo-box editor types final String[] theTags = propEditor.getTags(); res = new TagListHelper(theTags, propEditor); } } } } if (res == null) { // ok, find the type of object we're working with Class rawClass = EditableWrapper.getPropertyClass(_thisProp); for (Iterator iter = _myHelperList.iterator(); iter.hasNext(); ) { EditorHelper thisHelper = (EditorHelper) iter.next(); if (thisHelper.editsThis(rawClass)) { res = thisHelper; break; } } if (res == null) { // ok, log the error String msg = "editor not found for:" + EditableWrapper.getPropertyClass(prop) + "(" + prop.getDisplayName() + ")"; System.out.println(msg); } } return res; }
/** * Compare the given {@link PropertyDescriptor} against the given {@link Object} and return {@code * true} if they are objects are equivalent, i.e. both are {@code PropertyDescriptor}s whose read * method, write method, property types, property editor and flags are equivalent. * * @see PropertyDescriptor#equals(Object) */ public static boolean equals(PropertyDescriptor pd1, Object obj) { if (pd1 == obj) { return true; } if (obj != null && obj instanceof PropertyDescriptor) { PropertyDescriptor pd2 = (PropertyDescriptor) obj; if (!compareMethods(pd1.getReadMethod(), pd2.getReadMethod())) { return false; } if (!compareMethods(pd1.getWriteMethod(), pd2.getWriteMethod())) { return false; } if (pd1.getPropertyType() == pd2.getPropertyType() && pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() && pd1.isBound() == pd2.isBound() && pd1.isConstrained() == pd2.isConstrained()) { return true; } } return false; }
/* * see java.beans.FeatureDescriptor#FeatureDescriptor(FeatureDescriptor) */ public static void copyNonMethodProperties(PropertyDescriptor source, PropertyDescriptor target) throws IntrospectionException { target.setExpert(source.isExpert()); target.setHidden(source.isHidden()); target.setPreferred(source.isPreferred()); target.setName(source.getName()); target.setShortDescription(source.getShortDescription()); target.setDisplayName(source.getDisplayName()); // copy all attributes (emulating behavior of private FeatureDescriptor#addTable) Enumeration<String> keys = source.attributeNames(); while (keys.hasMoreElements()) { String key = keys.nextElement(); target.setValue(key, source.getValue(key)); } // see java.beans.PropertyDescriptor#PropertyDescriptor(PropertyDescriptor) target.setPropertyEditorClass(source.getPropertyEditorClass()); target.setBound(source.isBound()); target.setConstrained(source.isConstrained()); }
/** * can we edit this property with a drop-down list? * * @param thisP * @return yes/no */ @SuppressWarnings("rawtypes") private static boolean supportsListEditor(final PropertyDescriptor thisP) { boolean res = false; // find out the type of the editor final Method m = thisP.getReadMethod(); final Class cl = m.getReturnType(); // is there a custom editor for this type? final Class c = thisP.getPropertyEditorClass(); PropertyEditor pe = null; // try to create an editor for this class try { if (c != null) pe = (PropertyEditor) c.newInstance(); } catch (final Exception e) { MWC.Utilities.Errors.Trace.trace(e); } // did it work? if (pe == null) { // try to find an editor for this through our manager pe = PropertyEditorManager.findEditor(cl); } // have we managed to create an editor? if (pe != null) { // retrieve the tags final String[] tags = pe.getTags(); // are there any tags for this class? if (tags != null) { res = true; } } return res; }
/** * Package-private constructor. Merge two property descriptors. Where they conflict, give the * second argument (y) priority over the first argument (x). * * @param x The first (lower priority) PropertyDescriptor * @param y The second (higher priority) PropertyDescriptor */ PropertyDescriptor(PropertyDescriptor x, PropertyDescriptor y) { super(x, y); if (y.baseName != null) { baseName = y.baseName; } else { baseName = x.baseName; } if (y.readMethodName != null) { readMethodName = y.readMethodName; } else { readMethodName = x.readMethodName; } if (y.writeMethodName != null) { writeMethodName = y.writeMethodName; } else { writeMethodName = x.writeMethodName; } if (y.propertyTypeRef != null) { propertyTypeRef = y.propertyTypeRef; } else { propertyTypeRef = x.propertyTypeRef; } // Figure out the merged read method. Method xr = x.getReadMethod(); Method yr = y.getReadMethod(); // Normally give priority to y's readMethod. try { if (yr != null && yr.getDeclaringClass() == getClass0()) { setReadMethod(yr); } else { setReadMethod(xr); } } catch (IntrospectionException ex) { // fall through } // However, if both x and y reference read methods in the same class, // give priority to a boolean "is" method over a boolean "get" method. if (xr != null && yr != null && xr.getDeclaringClass() == yr.getDeclaringClass() && xr.getReturnType() == boolean.class && yr.getReturnType() == boolean.class && xr.getName().indexOf("is") == 0 && yr.getName().indexOf("get") == 0) { try { setReadMethod(xr); } catch (IntrospectionException ex) { // fall through } } Method xw = x.getWriteMethod(); Method yw = y.getWriteMethod(); try { if (yw != null && yw.getDeclaringClass() == getClass0()) { setWriteMethod(yw); } else { setWriteMethod(xw); } } catch (IntrospectionException ex) { // Fall through } if (y.getPropertyEditorClass() != null) { setPropertyEditorClass(y.getPropertyEditorClass()); } else { setPropertyEditorClass(x.getPropertyEditorClass()); } bound = x.bound | y.bound; constrained = x.constrained | y.constrained; }
/** * @param prop * @param value * @return */ public static PropertyEditor findEditor(PropertyDescriptor prop, Object value) { PropertyEditor editor = null; Class pec = prop.getPropertyEditorClass(); Class type = prop.getPropertyType(); try { if (pec != null) { editor = (PropertyEditor) pec.newInstance(); } } catch (Exception e) { editor = null; } if (editor == null) { if (value != null) { // Try to unwrap primitives if (Primitives.isWrapperType(value.getClass())) { editor = PropertyEditorManager.findEditor(Primitives.unwrap(value.getClass())); } else { editor = PropertyEditorManager.findEditor(value.getClass()); } } if (editor == null && (BeanInspector.isJavaPrimitive(value.getClass()))) { Class<?> prim = BeanInspector.getBoxedType(value.getClass()); if (prim != null) { editor = PropertyEditorManager.findEditor(prim); } if (editor == null) { prim = BeanInspector.getUnboxedType(value.getClass()); if (prim != null) { editor = PropertyEditorManager.findEditor(prim); } } } if (editor == null) { editor = PropertyEditorManager.findEditor(type); } if ((editor == null) && useDefaultGOE) { if (type.isArray()) { Class<?> unwrapped = Primitives.isWrapperType(type.getComponentType()) ? Primitives.unwrap(type.getComponentType()) : type; if (unwrapped.isPrimitive()) { editor = new ArrayEditor(); } else { editor = new ObjectArrayEditor<>(unwrapped.getComponentType()); } } else if (type.isEnum()) { editor = new EnumEditor(); } else { editor = new GenericObjectEditor(); ((GenericObjectEditor) editor).setClassType(type); } } } if (editor == null) { // If it's a user-defined property we give a warning. String getterClass = prop.getReadMethod().getDeclaringClass().getName(); if (getterClass.indexOf("java.") != 0) { System.err.println( "Warning: Can't find public property editor" + " for property \"" + prop.getDisplayName() + "\" (class \"" + type.getName() + "\"). Skipping."); } } else if (editor instanceof GenericObjectEditor) { ((GenericObjectEditor) editor).setClassType(type); } return editor; }
@SuppressWarnings("rawtypes") private static MenuManager generateListEditorFor( final IMenuManager manager, final MenuManager subMenu, final PropertyDescriptor thisP, final Editable[] editables, final Layers theLayers, final Layer topLevelLayer) { // find out the type of the editor final Method m = thisP.getReadMethod(); final Class cl = m.getReturnType(); MenuManager result = subMenu; // is there a custom editor for this type? final Class c = thisP.getPropertyEditorClass(); PropertyEditor pe = null; // try to create an editor for this class try { if (c != null) pe = (PropertyEditor) c.newInstance(); } catch (final Exception e) { MWC.Utilities.Errors.Trace.trace(e); } // did it work? if (pe == null) { // try to find an editor for this through our manager pe = PropertyEditorManager.findEditor(cl); } // retrieve the tags final String[] tags = pe.getTags(); // are there any tags for this class? if (tags != null) { // create a drop-down list final MenuManager thisChoice = new MenuManager(thisP.getDisplayName()); // sort out the setter details final Method getter = thisP.getReadMethod(); // get the current value Object val = null; try { val = getter.invoke(editables[0], (Object[]) null); } catch (final Exception e) { MWC.Utilities.Errors.Trace.trace(e); } pe.setValue(val); // convert the current value to text final String currentValue = pe.getAsText(); // and now a drop-down item for each options for (int j = 0; j < tags.length; j++) { final String thisTag = tags[j]; pe.setAsText(thisTag); final Object thisValue = pe.getValue(); // create the item final IAction thisA = new Action(thisTag, IAction.AS_RADIO_BUTTON) { public void run() { try { // hey, since this is a radio button, we get two events when the // selection changes - one for the value being unset, and the // other // for the value being set. So just fire for the new value (the // one that's checked) if (isChecked()) { final Method setter = thisP.getWriteMethod(); // ok, place the change in the action final ListPropertyAction la = new ListPropertyAction( thisP.getDisplayName(), editables, getter, setter, thisValue, theLayers, topLevelLayer); // and add it to the history CorePlugin.run(la); } } catch (final Exception e) { CorePlugin.logError( IStatus.INFO, "While executing select editor for:" + thisP, e); } } }; // is this the current one? if (thisTag.equals(currentValue)) { thisA.setChecked(true); } // add it to the menu thisChoice.add(thisA); } // is our sub-menu already created? if (result == null) { String nameStr; if (editables.length > 1) nameStr = MULTIPLE_ITEMS_STR; else nameStr = editables[0].getName(); result = new MenuManager(nameStr); manager.add(result); } result.add(thisChoice); } return result; }
/* * Attempt to find custom property editor on descriptor first, else try the propery editor manager. */ protected PropertyEditor getPropertyEditor(PropertyDescriptor desc) throws InstantiationException, IllegalAccessException { Class<?> cls = desc.getPropertyEditorClass(); if (null != cls) return (PropertyEditor) cls.newInstance(); return getPropertyEditorValue(desc.getPropertyType()); }