// this GwtCreateHandler has been introduced to make possible the // instanciation of abstract classes // that gwt-test-utils doesn't patch right now public Object create(Class<?> classLiteral) throws Exception { if (classLiteral.isAnnotation() || classLiteral.isArray() || classLiteral.isEnum() || classLiteral.isInterface() || !Modifier.isAbstract(classLiteral.getModifiers())) { return null; } Class<?> newClass = cache.get(classLiteral); if (newClass != null) { return newClass.newInstance(); } CtClass ctClass = GwtClassPool.getCtClass(classLiteral); CtClass subClass = GwtClassPool.get().makeClass(classLiteral.getCanonicalName() + "SubClass"); subClass.setSuperclass(ctClass); for (CtMethod m : ctClass.getDeclaredMethods()) { if (javassist.Modifier.isAbstract(m.getModifiers())) { CtMethod copy = new CtMethod(m, subClass, null); subClass.addMethod(copy); } } GwtPatcherUtils.patch(subClass, null); newClass = subClass.toClass(GwtClassLoader.get(), null); cache.put(classLiteral, newClass); return newClass.newInstance(); }
public static void patch(CtClass c, IPatcher patcher) throws Exception { treatClassToPatch(c); if (patcher != null) { patcher.initClass(c); } for (CtMethod m : c.getDeclaredMethods()) { boolean wasAbstract = false; String newBody = null; if (Modifier.isAbstract(m.getModifiers())) { m.setModifiers(m.getModifiers() - Modifier.ABSTRACT); wasAbstract = true; } if (patcher != null) { newBody = patcher.getNewBody(m); } if (newBody != null) { if (newBody.startsWith(AutomaticPatcher.INSERT_BEFORE)) { GwtPatcherUtils.insertBefore( m, newBody.substring(AutomaticPatcher.INSERT_BEFORE.length())); } else if (newBody.startsWith(AutomaticPatcher.INSERT_AFTER)) { GwtPatcherUtils.insertAfter(m, newBody.substring(AutomaticPatcher.INSERT_AFTER.length())); } else { GwtPatcherUtils.replaceImplementation(m, newBody); } } else if (wasAbstract) { if (patcher != null) { m.setBody( "{ throw new " + UnsupportedOperationException.class.getName() + "(\"Abstract method '" + c.getSimpleName() + "." + m.getName() + "()' is not patched by " + patcher.getClass().getName() + "\"); }"); } else { m.setBody( "{ throw new " + UnsupportedOperationException.class.getName() + "(\"Abstract method '" + c.getSimpleName() + "." + m.getName() + "()' is not patched by any declared " + IPatcher.class.getSimpleName() + " instance\"); }"); } } } if (patcher != null) { patcher.finalizeClass(c); } }
@Test(groups = "unit", timeOut = 1000) public void test() throws ClassNotFoundException { final Collection<Class<?>> descriptionClasses = Lists.newArrayList(); final URL url = AnnotationTests.class.getClassLoader().getResource("META-INF/jobs/persistence.xml"); final String jpaConfigContents = InputContexts.toString(InputContexts.forUrl(url)); final List<Class<? extends ActivityDescription>> activityDescriptionsMapped = Lists.newArrayList(); for (final Class<? extends ActivityFactory<?>> factoryClass : FACTORIES) { // Make sure the class is make as a ManageBean to DI context picks it up. assert factoryClass.getAnnotation(ManagedBean.class) != null : "Factory class " + factoryClass + " is not annotated with @ManagedBean"; // assert factoryClass.getDeclaredConstructors().length == 1; boolean foundInjectedConstructor = false; for (Constructor<?> constructor : factoryClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0 || constructor.getAnnotation(Inject.class) != null) { foundInjectedConstructor = true; } } assert foundInjectedConstructor; final ActivityFactoryFor factoryAnnotation = factoryClass.getAnnotation(ActivityFactoryFor.class); // Make sure this class specifies which ActivityDescription it acts an ActivityFactory for. assert factoryAnnotation != null; final Class<? extends ActivityDescription> descriptionClass = factoryAnnotation.value(); activityDescriptionsMapped.add(descriptionClass); assert ActivityDescription.class.isAssignableFrom(descriptionClass); // Make sure there are not multiple descriptions per factory assert !descriptionClasses.contains(descriptionClass); // Make sure the description can be persisted assert descriptionClass.getAnnotation(Entity.class) != null : descriptionClass + " is not annotated with entity."; assert jpaConfigContents.contains(descriptionClass.getCanonicalName()) : "Class " + descriptionClass.getCanonicalName() + " not found in JPA configuration."; } final Pattern pattern = Pattern.compile("\\<class\\>.*\\<"); final Matcher matcher = pattern.matcher(jpaConfigContents); int start = 0; while (matcher.find(start)) { final int startIdx = matcher.start() + "<class>".length(); final int endIdx = jpaConfigContents.indexOf("<", startIdx); final String classStr = jpaConfigContents.substring(startIdx, endIdx); final Class<?> clazz = Class.forName(classStr); if (ActivityDescription.class.isAssignableFrom(clazz)) { if (!Modifier.isAbstract(clazz.getModifiers())) { assert activityDescriptionsMapped.contains(clazz) : "No activity factory found for description class " + clazz; } } start = endIdx; } }
/** * Return whether or not the class has a method with the given name * * @param theClass the class to inspect * @param theName the name of the method to look for * @return true if the class contains the method, false otherwise */ private static boolean hasMethod(CtClass theClass, String theName) { try { return theClass.getDeclaredMethod(theName) != null && !Modifier.isAbstract(theClass.getDeclaredMethod(theName).getModifiers()); } catch (NotFoundException e) { try { if (theClass.getSuperclass() != null) { return hasMethod(theClass.getSuperclass(), theName); } else { return false; } } catch (NotFoundException e1) { return false; } } }
public ObjBase makeValue(ObjectId id, DBObject rawData, Class<? extends ObjBase> c) { if (Modifier.isAbstract(c.getModifiers()) || Modifier.isInterface(c.getModifiers())) { // extract declared schema from result, use that class Object schemaId = rawData.get(ReservedFieldNames.SCHEMA); try { c = (Class<ObjBase>) ClassUtil.findClass(schemaId.toString()); } catch (ClassNotFoundException ex) { log.warn("Could not find fallback schema {}", schemaId); return null; } } ObjBase value = makeStub(id, c, rawData); // update stub with the rest of the data, if (value != null && !(value instanceof Swappable)) try { unmarshaller.unmarshall(Bson.createDocument(rawData), value, this); } catch (MarshallingException me) { log.warn(me.getMessage(), me); } return value; }
private void enhance_(ApplicationClass applicationClass, boolean buildAuthorityRegistryOnly) throws Exception { Plugin.trace("about to enhance applicationClass: %s", applicationClass); CtClass ctClass = makeClass(applicationClass); Set<CtBehavior> s = new HashSet<CtBehavior>(); s.addAll(Arrays.asList(ctClass.getDeclaredMethods())); s.addAll(Arrays.asList(ctClass.getMethods())); s.addAll(Arrays.asList(ctClass.getConstructors())); s.addAll(Arrays.asList(ctClass.getDeclaredConstructors())); for (final CtBehavior ctBehavior : s) { if (!Modifier.isPublic(ctBehavior.getModifiers()) || javassist.Modifier.isAbstract(ctBehavior.getModifiers())) { continue; } boolean needsEnhance = false; RequireRight rr = null; RequirePrivilege rp = null; RequireAccounting ra = null; boolean allowSystem = false; Object[] aa = ctBehavior.getAnnotations(); for (Object o : aa) { if (o instanceof RequirePrivilege) { needsEnhance = true; rp = (RequirePrivilege) o; continue; } if (o instanceof RequireRight) { needsEnhance = true; rr = (RequireRight) o; continue; } if (o instanceof AllowSystemAccount) { allowSystem = true; continue; } if (o instanceof RequireAccounting) { needsEnhance = true; ra = (RequireAccounting) o; } } if (!needsEnhance) continue; String key = ctBehavior.getLongName(); String errMsg = String.format("Error enhancing class %s.%s: ", ctClass, ctBehavior); // process rr & rp if (null != rr || null != rp) { // check before/after enhancement Authority.registAuthoriable_(key, rr, rp); if (!buildAuthorityRegistryOnly) { // verify if before attribute of rr and rp is consistent if (null != rr && null != rp && (rr.before() != rp.before())) { String reason = "The before setting of RequireRight and RequirePrivilege doesn't match"; throw new RuntimeException(errMsg + reason); } boolean before = true; if (null != rr) before = rr.before(); if (null != rp) before = rp.before(); // try best to guess the target object String curObj = ""; if (null != rr) { // target object only impact dynamic access checking, hence rr shall not be null boolean isConstructor = ctBehavior instanceof CtConstructor; boolean isStatic = false; if (!isConstructor) isStatic = Modifier.isStatic(ctBehavior.getModifiers()); int paraCnt = ctBehavior.getParameterTypes().length; int id = rr.target(); // calibrate target id if (0 == id) { if (isConstructor) { id = -1; } else if (isStatic) { if (paraCnt > 0) id = 1; else id = -1; } } else if (id > paraCnt) { id = paraCnt; } // speculate cur target statement String sid = null; if (id == -1) sid = "_"; if (id > -1) sid = String.valueOf(id); if (null != sid) { curObj = "play.modules.aaa.PlayDynamicRightChecker.setObjectIfNoCurrent($" + sid + ");"; } if (-1 == id) before = false; } // check permission enhancement if (before) { ctBehavior.insertBefore( curObj + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\"" + key + "\", " + Boolean.toString(allowSystem) + ");"); } else { ctBehavior.insertAfter( curObj + " play.modules.aaa.enhancer.Enhancer.Authority.checkPermission(\"" + key + "\", " + Boolean.toString(allowSystem) + ");"); } } } if (buildAuthorityRegistryOnly) continue; // process ra if (null != ra) { CtClass[] paraTypes = ctBehavior.getParameterTypes(); String sParam = null; if (0 < paraTypes.length) { sParam = "new Object[0]"; } else { sParam = "{$$}"; } String msg = ra.value(); if (null == msg || "".equals(msg)) msg = key; if (ra.before()) { ctBehavior.insertBefore( "play.modules.aaa.utils.Accounting.info(\"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + ");"); } else { ctBehavior.insertAfter( "play.modules.aaa.utils.Accounting.info(\"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + ");"); } CtClass etype = ClassPool.getDefault().get("java.lang.Exception"); ctBehavior.addCatch( "{play.modules.aaa.utils.Accounting.error($e, \"" + msg + "\", " + Boolean.toString(allowSystem) + ", " + sParam + "); throw $e;}", etype); } } if (buildAuthorityRegistryOnly) return; applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.detach(); }
private boolean isJAXRSEntity(Class<?> javaClass, Class<? extends Annotation> annotation) { if (!hasAnnotation(javaClass, annotation)) return false; if (javaClass.isInterface() || Modifier.isAbstract(javaClass.getModifiers())) return false; return true; }
/** * Get the bean proeprties from the given class * * @param thePool the class pool to use when creating new fields * @param theClass the class the new fields will belong to * @param theInterface the original bean class * @return a Map of the bean property names with the new field for the property as the value * @throws javassist.CannotCompileException thrown if there is an error generating the methods * @throws javassist.NotFoundException thrown if there is an error generating the methods */ private static <T> Map<String, CtField> properties( final ClassPool thePool, final CtClass theClass, final Class<T> theInterface) throws NotFoundException, CannotCompileException { Map<String, CtField> aMap = new HashMap<String, CtField>(); for (Method aMethod : theInterface.getDeclaredMethods()) { // see if we've already processed this method. Normal .equals for a method will not work // because the classes have to be the same, // what we want is the semantics of isAssignableFrom, not .equals between the classes // declaring the methods. Thus, the FINDER // predicate implementation does exactly that. It's a copy of the Method.equals function, but // with the .equals for the declaring // class changed to isAssignableFrom so we get the expected behavior. FINDER.method = aMethod; if (Iterables2.find(processedMethods, FINDER)) { continue; } // we want to ignore methods with implementations, we should not override them. if (!Modifier.isAbstract(aMethod.getModifiers())) { // mark the method as one we've already handled in case we get this method again on a // superclass/interface processedMethods.add(aMethod); continue; } if (!aMethod.getName().startsWith("get") && !aMethod.getName().startsWith("is") && !aMethod.getName().startsWith("has") && !aMethod.getName().startsWith("set")) { if (EmpireOptions.STRICT_MODE) { throw new IllegalArgumentException( "Non-bean style methods found, implementations for them cannot not be generated"); } else { LOGGER.warn( "Non-bean style methods found, implementations for them cannot not be generated : " + aMethod.getName()); } } String aProp = aMethod.getName().substring(aMethod.getName().startsWith("is") ? 2 : 3); aProp = String.valueOf(aProp.charAt(0)).toLowerCase() + aProp.substring(1); Class aType = null; Type generics = null; if (aMethod.getName().startsWith("get") || aMethod.getName().startsWith("is") || aMethod.getName().startsWith("has")) { aType = aMethod.getReturnType(); generics = aMethod.getGenericReturnType(); } else if (aMethod.getName().startsWith("set") && aMethod.getParameterTypes().length > 0) { aType = aMethod.getParameterTypes()[0]; if (aMethod.getGenericParameterTypes() != null && aMethod.getGenericParameterTypes().length > 0) { generics = aMethod.getGenericParameterTypes()[0]; } } if (aType != null) { CtField aNewField = new CtField(thePool.get(aType.getName()), aProp, theClass); if (generics != null && generics instanceof ParameterizedTypeImpl) { for (Type t : ((ParameterizedTypeImpl) generics).getActualTypeArguments()) { String aFlag = ""; String aName; if (t instanceof WildcardTypeImpl) { WildcardTypeImpl aWildcard = (WildcardTypeImpl) t; // trying to suss out super v extends w/o resorting to string munging. if (aWildcard.getLowerBounds().length == 0 && aWildcard.getUpperBounds().length > 0) { // no lower bounds afaik indicates ? extends Foo aFlag = "+"; aName = ((Class) aWildcard.getUpperBounds()[0]).getName(); } else if (aWildcard.getLowerBounds().length > 0) { // lower & upper bounds I believe indicates something of the form Foo super Bar aFlag = "-"; aName = ((Class) aWildcard.getLowerBounds()[0]).getName(); } else { throw new CannotCompileException( "Unknown or unsupported type signature found: " + t); } } else { aName = ((Class) t).getName(); } aNewField .getFieldInfo() .addAttribute( new SignatureAttribute( aNewField.getFieldInfo().getConstPool(), "L" + aType.getName().replace('.', '/') + "<" + aFlag + "L" + aName.replace('.', '/') + ";>;")); } } aMap.put(aProp, aNewField); } // mark the method as one we've already handled in case we get this method again on a // superclass/interface processedMethods.add(aMethod); } return aMap; }