private void validateClass(Class<?> source, ValidationProblemCollector problems) { int modifiers = source.getModifiers(); if (Modifier.isInterface(modifiers)) { problems.add("Must be a class, not an interface"); } if (source.getEnclosingClass() != null) { if (Modifier.isStatic(modifiers)) { if (Modifier.isPrivate(modifiers)) { problems.add("Class cannot be private"); } } else { problems.add("Enclosed classes must be static and non private"); } } Constructor<?>[] constructors = source.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { if (constructor.getParameterTypes().length > 0) { problems.add("Cannot declare a constructor that takes arguments"); break; } } Field[] fields = source.getDeclaredFields(); for (Field field : fields) { int fieldModifiers = field.getModifiers(); if (!field.isSynthetic() && !(Modifier.isStatic(fieldModifiers) && Modifier.isFinal(fieldModifiers))) { problems.add(field, "Fields must be static final."); } } }
static Method[] getOverridableMethods(Class c) { ArrayList<Method> list = new ArrayList<Method>(); HashSet<String> skip = new HashSet<String>(); while (c != null) { Method[] methods = c.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { String methodKey = methods[i].getName() + getMethodSignature(methods[i], methods[i].getParameterTypes()); if (skip.contains(methodKey)) continue; // skip this method int mods = methods[i].getModifiers(); if (Modifier.isStatic(mods)) continue; if (Modifier.isFinal(mods)) { // Make sure we don't add a final method to the list // of overridable methods. skip.add(methodKey); continue; } if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) { list.add(methods[i]); skip.add(methodKey); } } c = c.getSuperclass(); } return list.toArray(new Method[list.size()]); }
static Method[] getOverridableMethods(Class c) { ArrayList list = new ArrayList(); while (c != null) { Method[] methods = c.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { int mods = methods[i].getModifiers(); if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) continue; if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) list.add(methods[i]); } c = c.getSuperclass(); } return (Method[]) list.toArray(new Method[list.size()]); }
private static void appendOverridableMethods( Class<?> c, ArrayList<Method> list, HashSet<String> skip) { Method[] methods = c.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { String methodKey = methods[i].getName() + getMethodSignature(methods[i], methods[i].getParameterTypes()); if (skip.contains(methodKey)) continue; // skip this method int mods = methods[i].getModifiers(); if (Modifier.isStatic(mods)) continue; if (Modifier.isFinal(mods)) { // Make sure we don't add a final method to the list // of overridable methods. skip.add(methodKey); continue; } if (Modifier.isPublic(mods) || Modifier.isProtected(mods)) { list.add(methods[i]); skip.add(methodKey); } } }
@SuppressWarnings("unchecked") LDAPObjectHandler(final Class<T> type) throws LDAPPersistException { this.type = type; final Class<? super T> superclassType = type.getSuperclass(); if (superclassType == null) { superclassHandler = null; } else { final LDAPObject superclassAnnotation = superclassType.getAnnotation(LDAPObject.class); if (superclassAnnotation == null) { superclassHandler = null; } else { superclassHandler = new LDAPObjectHandler(superclassType); } } final TreeMap<String, FieldInfo> fields = new TreeMap<String, FieldInfo>(); final TreeMap<String, GetterInfo> getters = new TreeMap<String, GetterInfo>(); final TreeMap<String, SetterInfo> setters = new TreeMap<String, SetterInfo>(); ldapObject = type.getAnnotation(LDAPObject.class); if (ldapObject == null) { throw new LDAPPersistException(ERR_OBJECT_HANDLER_OBJECT_NOT_ANNOTATED.get(type.getName())); } final LinkedHashMap<String, String> objectClasses = new LinkedHashMap<String, String>(10); final String oc = ldapObject.structuralClass(); if (oc.length() == 0) { structuralClass = getUnqualifiedClassName(type); } else { structuralClass = oc; } final StringBuilder invalidReason = new StringBuilder(); if (PersistUtils.isValidLDAPName(structuralClass, invalidReason)) { objectClasses.put(toLowerCase(structuralClass), structuralClass); } else { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_STRUCTURAL_CLASS.get( type.getName(), structuralClass, invalidReason.toString())); } auxiliaryClasses = ldapObject.auxiliaryClass(); for (final String auxiliaryClass : auxiliaryClasses) { if (PersistUtils.isValidLDAPName(auxiliaryClass, invalidReason)) { objectClasses.put(toLowerCase(auxiliaryClass), auxiliaryClass); } else { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_AUXILIARY_CLASS.get( type.getName(), auxiliaryClass, invalidReason.toString())); } } superiorClasses = ldapObject.superiorClass(); for (final String superiorClass : superiorClasses) { if (PersistUtils.isValidLDAPName(superiorClass, invalidReason)) { objectClasses.put(toLowerCase(superiorClass), superiorClass); } else { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_SUPERIOR_CLASS.get( type.getName(), superiorClass, invalidReason.toString())); } } if (superclassHandler != null) { for (final String s : superclassHandler.objectClassAttribute.getValues()) { objectClasses.put(toLowerCase(s), s); } } objectClassAttribute = new Attribute("objectClass", objectClasses.values()); final String parentDNStr = ldapObject.defaultParentDN(); try { defaultParentDN = new DN(parentDNStr); } catch (LDAPException le) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_DEFAULT_PARENT.get( type.getName(), parentDNStr, le.getMessage()), le); } final String postDecodeMethodName = ldapObject.postDecodeMethod(); if (postDecodeMethodName.length() > 0) { try { postDecodeMethod = type.getDeclaredMethod(postDecodeMethodName); postDecodeMethod.setAccessible(true); } catch (Exception e) { debugException(e); throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_POST_DECODE_METHOD.get( type.getName(), postDecodeMethodName, getExceptionMessage(e)), e); } } else { postDecodeMethod = null; } final String postEncodeMethodName = ldapObject.postEncodeMethod(); if (postEncodeMethodName.length() > 0) { try { postEncodeMethod = type.getDeclaredMethod(postEncodeMethodName, Entry.class); postEncodeMethod.setAccessible(true); } catch (Exception e) { debugException(e); throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_POST_ENCODE_METHOD.get( type.getName(), postEncodeMethodName, getExceptionMessage(e)), e); } } else { postEncodeMethod = null; } try { constructor = type.getDeclaredConstructor(); constructor.setAccessible(true); } catch (Exception e) { debugException(e); throw new LDAPPersistException( ERR_OBJECT_HANDLER_NO_DEFAULT_CONSTRUCTOR.get(type.getName()), e); } Field tmpDNField = null; Field tmpEntryField = null; final LinkedList<FieldInfo> tmpRFilterFields = new LinkedList<FieldInfo>(); final LinkedList<FieldInfo> tmpAAFilterFields = new LinkedList<FieldInfo>(); final LinkedList<FieldInfo> tmpCAFilterFields = new LinkedList<FieldInfo>(); final LinkedList<FieldInfo> tmpRDNFields = new LinkedList<FieldInfo>(); for (final Field f : type.getDeclaredFields()) { final LDAPField fieldAnnotation = f.getAnnotation(LDAPField.class); final LDAPDNField dnFieldAnnotation = f.getAnnotation(LDAPDNField.class); final LDAPEntryField entryFieldAnnotation = f.getAnnotation(LDAPEntryField.class); if (fieldAnnotation != null) { f.setAccessible(true); final FieldInfo fieldInfo = new FieldInfo(f, type); final String attrName = toLowerCase(fieldInfo.getAttributeName()); if (fields.containsKey(attrName)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_ATTR_CONFLICT.get(type.getName(), fieldInfo.getAttributeName())); } else { fields.put(attrName, fieldInfo); } switch (fieldInfo.getFilterUsage()) { case REQUIRED: tmpRFilterFields.add(fieldInfo); break; case ALWAYS_ALLOWED: tmpAAFilterFields.add(fieldInfo); break; case CONDITIONALLY_ALLOWED: tmpCAFilterFields.add(fieldInfo); break; case EXCLUDED: default: break; } if (fieldInfo.includeInRDN()) { tmpRDNFields.add(fieldInfo); } } if (dnFieldAnnotation != null) { f.setAccessible(true); if (fieldAnnotation != null) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_CONFLICTING_FIELD_ANNOTATIONS.get( type.getName(), "LDAPField", "LDAPDNField", f.getName())); } if (tmpDNField != null) { throw new LDAPPersistException(ERR_OBJECT_HANDLER_MULTIPLE_DN_FIELDS.get(type.getName())); } final int modifiers = f.getModifiers(); if (Modifier.isFinal(modifiers)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_DN_FIELD_FINAL.get(f.getName(), type.getName())); } else if (Modifier.isStatic(modifiers)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_DN_FIELD_STATIC.get(f.getName(), type.getName())); } final Class<?> fieldType = f.getType(); if (fieldType.equals(String.class)) { tmpDNField = f; } else { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_DN_FIELD_TYPE.get( type.getName(), f.getName(), fieldType.getName())); } } if (entryFieldAnnotation != null) { f.setAccessible(true); if (fieldAnnotation != null) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_CONFLICTING_FIELD_ANNOTATIONS.get( type.getName(), "LDAPField", "LDAPEntryField", f.getName())); } if (tmpEntryField != null) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_MULTIPLE_ENTRY_FIELDS.get(type.getName())); } final int modifiers = f.getModifiers(); if (Modifier.isFinal(modifiers)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_ENTRY_FIELD_FINAL.get(f.getName(), type.getName())); } else if (Modifier.isStatic(modifiers)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_ENTRY_FIELD_STATIC.get(f.getName(), type.getName())); } final Class<?> fieldType = f.getType(); if (fieldType.equals(ReadOnlyEntry.class)) { tmpEntryField = f; } else { throw new LDAPPersistException( ERR_OBJECT_HANDLER_INVALID_ENTRY_FIELD_TYPE.get( type.getName(), f.getName(), fieldType.getName())); } } } dnField = tmpDNField; entryField = tmpEntryField; requiredFilterFields = Collections.unmodifiableList(tmpRFilterFields); alwaysAllowedFilterFields = Collections.unmodifiableList(tmpAAFilterFields); conditionallyAllowedFilterFields = Collections.unmodifiableList(tmpCAFilterFields); rdnFields = Collections.unmodifiableList(tmpRDNFields); final LinkedList<GetterInfo> tmpRFilterGetters = new LinkedList<GetterInfo>(); final LinkedList<GetterInfo> tmpAAFilterGetters = new LinkedList<GetterInfo>(); final LinkedList<GetterInfo> tmpCAFilterGetters = new LinkedList<GetterInfo>(); final LinkedList<GetterInfo> tmpRDNGetters = new LinkedList<GetterInfo>(); for (final Method m : type.getDeclaredMethods()) { final LDAPGetter getter = m.getAnnotation(LDAPGetter.class); final LDAPSetter setter = m.getAnnotation(LDAPSetter.class); if (getter != null) { m.setAccessible(true); if (setter != null) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_CONFLICTING_METHOD_ANNOTATIONS.get( type.getName(), "LDAPGetter", "LDAPSetter", m.getName())); } final GetterInfo methodInfo = new GetterInfo(m, type); final String attrName = toLowerCase(methodInfo.getAttributeName()); if (fields.containsKey(attrName) || getters.containsKey(attrName)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_ATTR_CONFLICT.get(type.getName(), methodInfo.getAttributeName())); } else { getters.put(attrName, methodInfo); } switch (methodInfo.getFilterUsage()) { case REQUIRED: tmpRFilterGetters.add(methodInfo); break; case ALWAYS_ALLOWED: tmpAAFilterGetters.add(methodInfo); break; case CONDITIONALLY_ALLOWED: tmpCAFilterGetters.add(methodInfo); break; case EXCLUDED: default: // No action required. break; } if (methodInfo.includeInRDN()) { tmpRDNGetters.add(methodInfo); } } if (setter != null) { m.setAccessible(true); final SetterInfo methodInfo = new SetterInfo(m, type); final String attrName = toLowerCase(methodInfo.getAttributeName()); if (fields.containsKey(attrName) || setters.containsKey(attrName)) { throw new LDAPPersistException( ERR_OBJECT_HANDLER_ATTR_CONFLICT.get(type.getName(), methodInfo.getAttributeName())); } else { setters.put(attrName, methodInfo); } } } requiredFilterGetters = Collections.unmodifiableList(tmpRFilterGetters); alwaysAllowedFilterGetters = Collections.unmodifiableList(tmpAAFilterGetters); conditionallyAllowedFilterGetters = Collections.unmodifiableList(tmpCAFilterGetters); rdnGetters = Collections.unmodifiableList(tmpRDNGetters); if (rdnFields.isEmpty() && rdnGetters.isEmpty()) { throw new LDAPPersistException(ERR_OBJECT_HANDLER_NO_RDN_DEFINED.get(type.getName())); } fieldMap = Collections.unmodifiableMap(fields); getterMap = Collections.unmodifiableMap(getters); setterMap = Collections.unmodifiableMap(setters); final TreeSet<String> attrSet = new TreeSet<String>(); final TreeSet<String> lazySet = new TreeSet<String>(); if (ldapObject.requestAllAttributes()) { attrSet.add("*"); attrSet.add("+"); } else { for (final FieldInfo i : fields.values()) { if (i.lazilyLoad()) { lazySet.add(i.getAttributeName()); } else { attrSet.add(i.getAttributeName()); } } for (final SetterInfo i : setters.values()) { attrSet.add(i.getAttributeName()); } } attributesToRequest = new String[attrSet.size()]; attrSet.toArray(attributesToRequest); lazilyLoadedAttributes = new String[lazySet.size()]; lazySet.toArray(lazilyLoadedAttributes); }
private static Object createPlaceholder(Class<?> clazz, InvocationSequence invocationSequence) { return !Modifier.isFinal(clazz.getModifiers()) ? createProxy(new ProxyArgument(clazz, invocationSequence), clazz, false) : createArgumentPlaceholder(clazz); }
public static byte[] createAdapterCode( ObjToIntMap functionNames, String adapterName, Class<?> superClass, Class<?>[] interfaces, String scriptClassName) { ClassFileWriter cfw = new ClassFileWriter(adapterName, superClass.getName(), "<adapter>"); cfw.addField( "factory", "Laurora/javascript/ContextFactory;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); cfw.addField( "delegee", "Laurora/javascript/Scriptable;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); cfw.addField( "self", "Laurora/javascript/Scriptable;", (short) (ClassFileWriter.ACC_PUBLIC | ClassFileWriter.ACC_FINAL)); int interfacesCount = interfaces == null ? 0 : interfaces.length; for (int i = 0; i < interfacesCount; i++) { if (interfaces[i] != null) cfw.addInterface(interfaces[i].getName()); } String superName = superClass.getName().replace('.', '/'); Constructor<?>[] ctors = superClass.getConstructors(); for (Constructor<?> ctor : ctors) { generateCtor(cfw, adapterName, superName, ctor); } generateSerialCtor(cfw, adapterName, superName); if (scriptClassName != null) { generateEmptyCtor(cfw, adapterName, superName, scriptClassName); } ObjToIntMap generatedOverrides = new ObjToIntMap(); ObjToIntMap generatedMethods = new ObjToIntMap(); // generate methods to satisfy all specified interfaces. for (int i = 0; i < interfacesCount; i++) { Method[] methods = interfaces[i].getMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; int mods = method.getModifiers(); if (Modifier.isStatic(mods) || Modifier.isFinal(mods)) { continue; } String methodName = method.getName(); Class<?>[] argTypes = method.getParameterTypes(); if (!functionNames.has(methodName)) { try { superClass.getMethod(methodName, argTypes); // The class we're extending implements this method and // the JavaScript object doesn't have an override. See // bug 61226. continue; } catch (NoSuchMethodException e) { // Not implemented by superclass; fall through } } // make sure to generate only one instance of a particular // method/signature. String methodSignature = getMethodSignature(method, argTypes); String methodKey = methodName + methodSignature; if (!generatedOverrides.has(methodKey)) { generateMethod(cfw, adapterName, methodName, argTypes, method.getReturnType(), true); generatedOverrides.put(methodKey, 0); generatedMethods.put(methodName, 0); } } } // Now, go through the superclass's methods, checking for abstract // methods or additional methods to override. // generate any additional overrides that the object might contain. Method[] methods = getOverridableMethods(superClass); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; int mods = method.getModifiers(); // if a method is marked abstract, must implement it or the // resulting class won't be instantiable. otherwise, if the object // has a property of the same name, then an override is intended. boolean isAbstractMethod = Modifier.isAbstract(mods); String methodName = method.getName(); if (isAbstractMethod || functionNames.has(methodName)) { // make sure to generate only one instance of a particular // method/signature. Class<?>[] argTypes = method.getParameterTypes(); String methodSignature = getMethodSignature(method, argTypes); String methodKey = methodName + methodSignature; if (!generatedOverrides.has(methodKey)) { generateMethod(cfw, adapterName, methodName, argTypes, method.getReturnType(), true); generatedOverrides.put(methodKey, 0); generatedMethods.put(methodName, 0); // if a method was overridden, generate a "super$method" // which lets the delegate call the superclass' version. if (!isAbstractMethod) { generateSuper( cfw, adapterName, superName, methodName, methodSignature, argTypes, method.getReturnType()); } } } } // Generate Java methods for remaining properties that are not // overrides. ObjToIntMap.Iterator iter = new ObjToIntMap.Iterator(functionNames); for (iter.start(); !iter.done(); iter.next()) { String functionName = (String) iter.getKey(); if (generatedMethods.has(functionName)) continue; int length = iter.getValue(); Class<?>[] parms = new Class[length]; for (int k = 0; k < length; k++) parms[k] = ScriptRuntime.ObjectClass; generateMethod(cfw, adapterName, functionName, parms, ScriptRuntime.ObjectClass, false); } return cfw.toByteArray(); }
public TypeUniverse() { Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); metaAccess = providers.getMetaAccess(); constantReflection = providers.getConstantReflection(); snippetReflection = Graal.getRequiredCapability(SnippetReflectionProvider.class); Unsafe theUnsafe = null; try { theUnsafe = Unsafe.getUnsafe(); } catch (Exception e) { try { Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); theUnsafe = (Unsafe) theUnsafeField.get(null); } catch (Exception e1) { throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1); } } unsafe = theUnsafe; Class<?>[] initialClasses = { void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class }; for (Class<?> c : initialClasses) { addClass(c); } for (Field f : Constant.class.getDeclaredFields()) { int mods = f.getModifiers(); if (f.getType() == Constant.class && Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { try { Constant c = (Constant) f.get(null); if (c != null) { constants.add(c); } } catch (Exception e) { } } } for (Class<?> c : classes) { if (c != void.class && !c.isArray()) { constants.add(snippetReflection.forObject(Array.newInstance(c, 42))); } } constants.add(snippetReflection.forObject(new ArrayList<>())); constants.add(snippetReflection.forObject(new IdentityHashMap<>())); constants.add(snippetReflection.forObject(new LinkedHashMap<>())); constants.add(snippetReflection.forObject(new TreeMap<>())); constants.add(snippetReflection.forObject(new ArrayDeque<>())); constants.add(snippetReflection.forObject(new LinkedList<>())); constants.add(snippetReflection.forObject("a string")); constants.add(snippetReflection.forObject(42)); constants.add(snippetReflection.forObject(String.class)); constants.add(snippetReflection.forObject(String[].class)); }