static TypeParameterMatcher generate(Class<?> type, ClassLoader classLoader) { final String className = "io.netty.util.internal.__matchers__." + type.getName() + "Matcher"; try { try { return (TypeParameterMatcher) Class.forName(className, true, classLoader).newInstance(); } catch (Exception e) { // Not defined in the specified class loader. } CtClass c = classPool.getAndRename(NoOpTypeParameterMatcher.class.getName(), className); c.setModifiers(c.getModifiers() | Modifier.FINAL); c.getDeclaredMethod("match").setBody("{ return $1 instanceof " + type.getName() + "; }"); byte[] byteCode = c.toBytecode(); c.detach(); Method method = ClassLoader.class.getDeclaredMethod( "defineClass", String.class, byte[].class, int.class, int.class); method.setAccessible(true); Class<?> generated = (Class<?>) method.invoke(classLoader, className, byteCode, 0, byteCode.length); logger.debug("Generated: {}", generated.getName()); return (TypeParameterMatcher) generated.newInstance(); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } }
private void processCompositeClassFile(File javaClassFile, CtClass ctClass) { try { byte[] result = enhancer.enhanceComposite(ctClass.getName(), ctClass.toBytecode()); if (result != null) { writeEnhancedClass(javaClassFile, result); } } catch (Exception e) { log("Unable to enhance class [" + ctClass.getName() + "]", e, Project.MSG_WARN); } }
static void nullJavassistAdapt(ClassPool pool, final byte[] b) throws Exception { CtClass cc = pool.makeClass(new ByteArrayInputStream(b)); CtMethod[] ms = cc.getDeclaredMethods(); for (int j = 0; j < ms.length; ++j) { if (skipDebug) { // is there a mean to remove the debug attributes? } if (compute) { // how to force recomputation of maxStack and maxLocals? } } cc.toBytecode(); }
@Override public void enhanceThisClass(final ApplicationClass applicationClass) throws Exception { final CtClass ctClass = makeClass(applicationClass); if (ctClass.isInterface()) { return; } final Map<CtField, InjectionInfo> fieldsToInject = scanForInjections(ctClass); // in all methods, replace the field accesses with a call to spring for (final CtMethod ctMethod : ctClass.getDeclaredMethods()) { ctMethod.instrument( new ExprEditor() { @Override public void edit(final FieldAccess fieldAccess) { try { final InjectionInfo injectionInfo = fieldsToInject.get(fieldAccess.getField()); if (injectionInfo != null && fieldAccess.isReader()) { switch (injectionInfo.injectionMethod) { case BY_NAME: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBean\", new Object[] {\"" + injectionInfo.beanName + "\"});"); break; case BY_TYPE: fieldAccess.replace( "$_ = ($r)play.utils.Java.invokeStatic(play.modules.spring.Spring.class, \"getBeanOfType\", new Object[] {$type});"); break; } } } catch (final Exception e) { Logger.error( e, "Error in SpringEnhancer. %s.%s has not been properly enhanced (fieldAccess %s).", applicationClass.name, ctMethod.getName(), fieldAccess); throw new UnexpectedException("Error enhancing injected field", e); } } }); } applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
private Class<?> injectToPlainClassLoader( ClassPool pool, ClassLoader classLoader, String className) throws NotFoundException, IOException, CannotCompileException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { Class<?> c = null; try { c = classLoader.loadClass(className); } catch (ClassNotFoundException ignore) { } if (c != null) { return c; } CtClass ct = pool.get(className); if (ct == null) { throw new NotFoundException(className); } CtClass superClass = ct.getSuperclass(); if (superClass != null) { injectToPlainClassLoader(pool, classLoader, superClass.getName()); } CtClass[] interfaces = ct.getInterfaces(); for (CtClass i : interfaces) { injectToPlainClassLoader(pool, classLoader, i.getName()); } Collection<String> refs = ct.getRefClasses(); for (String ref : refs) { try { injectToPlainClassLoader(pool, classLoader, ref); } catch (NotFoundException e) { logger.warn("Skip a referenced class because of NotFoundException : ", e); } } byte[] bytes = ct.toBytecode(); return (Class<?>) DEFINE_CLASS.invoke(classLoader, ct.getName(), bytes, 0, bytes.length); }
public static Getter generateGetter(OgnlContext context, String code) throws OgnlException { String className = NAME_FACTORY.getNewClassName(); try { ClassPool pool = (ClassPool) pools.get(context.getClassResolver()); EnhancedClassLoader loader = (EnhancedClassLoader) loaders.get(context.getClassResolver()); CtClass newClass; CtClass ognlContextClass; CtClass objectClass; CtClass stringClass; CtMethod method; byte[] byteCode; Class compiledClass; if ((pool == null) || (loader == null)) { ClassLoader classLoader = new ContextClassLoader(OgnlContext.class.getClassLoader(), context); pool = ClassPool.getDefault(); pool.insertClassPath(new LoaderClassPath(classLoader)); pools.put(context.getClassResolver(), pool); loader = new EnhancedClassLoader(classLoader); loaders.put(context.getClassResolver(), loader); } newClass = pool.makeClass(className); ognlContextClass = pool.get(OgnlContext.class.getName()); objectClass = pool.get(Object.class.getName()); stringClass = pool.get(String.class.getName()); newClass.addInterface(pool.get(Getter.class.getName())); method = new CtMethod( objectClass, "get", new CtClass[] {ognlContextClass, objectClass, stringClass}, newClass); method.setBody("{" + code + "}"); newClass.addMethod(method); byteCode = newClass.toBytecode(); compiledClass = loader.defineClass(className, byteCode); return (Getter) compiledClass.newInstance(); } catch (Throwable ex) { throw new OgnlException("Cannot create class", ex); } }
private void enhanceClass(Enhancer enhancer, File file) { byte[] enhancedBytecode = null; InputStream is = null; CtClass clas = null; try { is = new FileInputStream(file.toString()); clas = getClassPool().makeClass(is); if (!clas.hasAnnotation(Entity.class)) { getLog().debug("Class $file not an annotated Entity class. skipping..."); } else { enhancedBytecode = enhancer.enhance(clas.getName(), clas.toBytecode()); } } catch (Exception e) { getLog().error("Unable to enhance class [${file.toString()}]", e); return; } finally { try { if (null != is) is.close(); } catch (IOException ioe) { } } if (null != enhancedBytecode) { if (file.delete()) { try { if (!file.createNewFile()) { getLog().error("Unable to recreate class file [" + clas.getName() + "]"); } } catch (IOException ioe) { } } else { getLog().error("Unable to delete class file [" + clas.getName() + "]"); } FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file, false); outputStream.write(enhancedBytecode); outputStream.flush(); } catch (IOException ioe) { } finally { try { if (outputStream != null) outputStream.close(); clas.detach(); // release memory } catch (IOException ignore) { } } } }
public void rewrite(final CtClass clazz) throws CannotCompileException { try { ClassPool cp = ClassPool.getDefault(); byte[] b1 = clazz.toBytecode(); clazz.defrost(); ClassReader cr = new ClassReader(b1); ClassWriter cw = new ClassWriter(0); // new ClassWriter(cr, 0); // TraceClassVisitor ca = new TraceClassVisitor( cw, new PrintWriter(System.out, true) ); // CheckClassAdapter cca = new CheckClassAdapter(ca); ConcurrencyControlRewriter.Adapter ca2 = new ConcurrencyControlRewriter.Adapter(cw, clazz); cr.accept(ca2, 0); byte[] b2 = cw.toByteArray(); cp.makeClass(new ByteArrayInputStream(b2)); } catch (IOException e) { throw new CannotCompileException(e); } }
public byte[] translate( AspectManager manager, String className, ClassLoader loader, byte[] classfileBuffer) throws Exception { if (isReEntry()) { return null; } setReEntry(); super.setTransformationStarted(); try { if (manager.isNonAdvisableClassName(className)) { return null; } AOPClassPool pool = (AOPClassPool) manager.registerClassLoader(loader); CtClass clazz = obtainCtClassInfo(pool, className, classfileBuffer); CtClass woven = instrumentClass(manager, pool, clazz, true); if (woven != null) { pool.lockInCache(woven); if (AspectManager.debugClasses) { SecurityActions.debugWriteFile(clazz); } byte[] rtn = woven.toBytecode(); if (AspectManager.getPrune()) woven.prune(); return rtn; } else { pool.soften(clazz); } return null; } catch (Exception ex) { if (!(ex instanceof NotFoundException)) { if (verbose) logger.error(ex); else logger.error(ex.getMessage() + ".. Do verbose mode if you want full stack trace."); } throw ex; } finally { clearReEntry(); } }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { byte[] bytes = null; try { final ClassPool pool = ClassPool.getDefault(); pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader())); final CtClass ctClass = pool.getCtClass(className.replaceAll("/", ".")); if (ctClass != null) { try { for (CtMethod ctMethod : ctClass.getMethods()) { if (ctMethod.hasAnnotation(Retryable.class)) { try { changeMethod(ctClass, ctMethod); bytes = ctClass.toBytecode(); writeClassFile(bytes); } catch (CannotCompileException | IOException e) { e.printStackTrace(); } System.out.println("found it!"); } } } finally { ctClass.detach(); } } } catch (NotFoundException e) { e.printStackTrace(); } return bytes; }
public byte[] transform(String className) { if (transformer.filterClassName(className)) { try { CtClass classToTransform = classPool.get(className); if (!classToTransform.isFrozen() && transformer.filterCtClass(classToTransform)) { transformer.applyTransformations(classPool, classToTransform); classToTransform.getClassFile().compact(); classToTransform.rebuildClassFile(); try (ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); DataOutputStream out = new DataOutputStream(new BufferedOutputStream(baos))) { classToTransform.toBytecode(out); out.flush(); return baos.toByteArray(); } catch (IOException | CannotCompileException e) { throw new IllegalStateException(e); } } } catch (NotFoundException e) { throw new IllegalStateException(e); } } return null; }
@Override public void enhanceThisClass(ApplicationClass applicationClass) throws Exception { CtClass ctClass = makeClass(applicationClass); String entityName = ctClass.getName(); Logger.debug("Enhance class " + entityName); // Only enhance Neo4jModel classes. if (!ctClass.subtypeOf(classPool.get("play.modules.neo4j.model.Neo4jModel"))) { return; } // Add a default constructor if needed try { for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { ctClass.removeConstructor(constructor); } if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0].getClass().isInstance(Node.class)) { ctClass.removeConstructor(constructor); } } if (!ctClass.isInterface()) { Logger.debug("Adding default constructor"); CtConstructor defaultConstructor = CtNewConstructor.make("public " + ctClass.getSimpleName() + "() { super();}", ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } // for all field, we add getter / setter for (CtField ctField : ctClass.getDeclaredFields()) { try { // Property name String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1); String getter = "get" + propertyName; String setter = "set" + propertyName; Logger.debug("Field " + ctField.getName() + " is a property ?"); if (isProperty(ctField)) { Logger.debug("true"); // ~~~~~~~~~ // GETTER // ~~~~~~~ try { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); if (!ctMethod.getName().equalsIgnoreCase("getShouldBeSave")) { ctClass.removeMethod(ctMethod); throw new NotFoundException("it's not a true getter !"); } } catch (NotFoundException noGetter) { // create getter Logger.debug("Adding getter " + getter + " for class " + entityName); // @formatter:off String code = "public " + ctField.getType().getName() + " " + getter + "() {" + "if(this.shouldBeSave == Boolean.FALSE && this.node != null){" + "return ((" + ctField.getType().getName() + ") play.modules.neo4j.util.Binder.bindFromNeo4jFormat(this.node.getProperty(\"" + ctField.getName() + "\", null)," + ctField.getType().getName() + ".class ));" + "}else{" + "return " + ctField.getName() + ";" + "}" + "}"; // @formatter:on Logger.debug(code); CtMethod getMethod = CtMethod.make(code, ctClass); ctClass.addMethod(getMethod); } // ~~~~~~~~~ // SETTER // ~~~~~~~ try { CtMethod ctMethod = ctClass.getDeclaredMethod(setter); if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers()) || hasPlayPropertiesAccessorAnnotation(ctMethod)) { if (hasPlayPropertiesAccessorAnnotation(ctMethod)) { ctClass.removeMethod(ctMethod); } throw new NotFoundException("it's not a true setter !"); } } catch (NotFoundException noSetter) { // create setter Logger.debug("Adding setter " + setter + " for class " + entityName); // @formatter:off String code = "public void " + setter + "(" + ctField.getType().getName() + " value) { " + "this." + ctField.getName() + " = value;" + "this.shouldBeSave = Boolean.TRUE;" + "}"; // formatter:on CtMethod setMethod = CtMethod.make(code, ctClass); Logger.debug(code); ctClass.addMethod(setMethod); } } else { // ~~~~~~~~~ // GETTER for neo4j relation property // ~~~~~~~ if (hasNeo4jRelationAnnotation(ctField)) { // test for related annotation Neo4jRelatedTo relatedTo = getRelatedAnnotation(ctField); if (relatedTo != null) { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); ctClass.removeMethod(ctMethod); String code; if (relatedTo.lazy()) { // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "if(this." + ctField.getName() + " == null){" + "java.lang.reflect.Field field = this.getClass().getField(\"" + ctField.getName() + "\");" + "this." + ctField.getName() + "=play.modules.neo4j.relationship.Neo4jRelationFactory.getModelsFromRelation(\"" + relatedTo.value() + "\", \"" + relatedTo.direction() + "\", field, this.node);" + "}" + "return " + ctField.getName() + ";" + "}"; // @formatter:on } else { // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "return " + ctField.getName() + ";" + "}"; // @formatter:on } Logger.debug(code); CtMethod method = CtMethod.make(code, ctClass); ctClass.addMethod(method); } // test for unique relation annotation Neo4jUniqueRelation uniqueRelation = getUniqueRelationAnnotation(ctField); if (uniqueRelation != null) { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); ctClass.removeMethod(ctMethod); String code; // @formatter:off code = "public " + ctField.getType().getName() + " " + getter + "() {" + "return (" + ctField.getType().getName() + ")" + ctField.getName() + ";" + "}"; // @formatter:on Logger.debug(code); CtMethod method = CtMethod.make(code, ctClass); ctClass.addMethod(method); } } } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } } // Adding getByKey() method Logger.debug("Adding getByKey() method for class " + entityName); // @formatter:off String codeGetByKey = "public static play.modules.neo4j.model.Neo4jModel getByKey(Long key) throws play.modules.neo4j.exception.Neo4jException {" + "return (" + entityName + ")_getByKey(key, \"" + entityName + "\");" + "}"; // @formatter:on Logger.debug(codeGetByKey); CtMethod getByKeyMethod = CtMethod.make(codeGetByKey, ctClass); ctClass.addMethod(getByKeyMethod); // ~~~~~~~~~~~~~~~ // Adding findAll() method // @formatter:off String codeFindAll = "public static java.util.List findAll() {" + "return " + entityName + "._findAll(\"" + entityName + "\");" + "}"; // @formatter:on Logger.debug(codeFindAll); CtMethod findAllMethod = CtMethod.make(codeFindAll, ctClass); ctClass.addMethod(findAllMethod); // ~~~~~~~~~~~~~~~ // Adding queryIndex() method // @formatter:off String queryIndex = "public static java.util.List queryIndex(String indexname, String query) {" + "return " + entityName + "._queryIndex(indexname, query);" + "}"; // @formatter:on Logger.debug(queryIndex); CtMethod queryIndexMethod = CtMethod.make(queryIndex, ctClass); ctClass.addMethod(queryIndexMethod); // Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
@Override public void enhanceThisClass(ApplicationClass applicationClass) throws Exception { final CtClass ctClass = makeClass(applicationClass); if (ctClass.isInterface()) { return; } if (ctClass.getName().endsWith(".package")) { return; } // Add a default constructor if needed try { boolean hasDefaultConstructor = false; for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { hasDefaultConstructor = true; break; } } if (!hasDefaultConstructor && !ctClass.isInterface()) { CtConstructor defaultConstructor = CtNewConstructor.make("public " + ctClass.getSimpleName() + "() {}", ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } if (isScala(applicationClass)) { // Temporary hack for Scala. Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); return; } for (CtField ctField : ctClass.getDeclaredFields()) { try { if (isProperty(ctField)) { // Property name String propertyName = ctField.getName().substring(0, 1).toUpperCase() + ctField.getName().substring(1); String getter = "get" + propertyName; String setter = "set" + propertyName; try { CtMethod ctMethod = ctClass.getDeclaredMethod(getter); if (ctMethod.getParameterTypes().length > 0 || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a getter !"); } } catch (NotFoundException noGetter) { // Créé le getter String code = "public " + ctField.getType().getName() + " " + getter + "() { return this." + ctField.getName() + "; }"; CtMethod getMethod = CtMethod.make(code, ctClass); getMethod.setModifiers(getMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(getMethod); } if (!isFinal(ctField)) { try { CtMethod ctMethod = ctClass.getDeclaredMethod(setter); if (ctMethod.getParameterTypes().length != 1 || !ctMethod.getParameterTypes()[0].equals(ctField.getType()) || Modifier.isStatic(ctMethod.getModifiers())) { throw new NotFoundException("it's not a setter !"); } } catch (NotFoundException noSetter) { // Créé le setter CtMethod setMethod = CtMethod.make( "public void " + setter + "(" + ctField.getType().getName() + " value) { this." + ctField.getName() + " = value; }", ctClass); setMethod.setModifiers(setMethod.getModifiers() | AccessFlag.SYNTHETIC); ctClass.addMethod(setMethod); createAnnotation(getAnnotations(setMethod), PlayPropertyAccessor.class); } } } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } } // Add a default constructor if needed try { boolean hasDefaultConstructor = false; for (CtConstructor constructor : ctClass.getDeclaredConstructors()) { if (constructor.getParameterTypes().length == 0) { hasDefaultConstructor = true; break; } } if (!hasDefaultConstructor) { CtConstructor defaultConstructor = CtNewConstructor.defaultConstructor(ctClass); ctClass.addConstructor(defaultConstructor); } } catch (Exception e) { Logger.error(e, "Error in PropertiesEnhancer"); throw new UnexpectedException("Error in PropertiesEnhancer", e); } // Intercept all fields access for (final CtBehavior ctMethod : ctClass.getDeclaredBehaviors()) { ctMethod.instrument( new ExprEditor() { @Override public void edit(FieldAccess fieldAccess) throws CannotCompileException { try { // Acces à une property ? if (isProperty(fieldAccess.getField())) { // TODO : vérifier que c'est bien un champ d'une classe de l'application // (fieldAccess.getClassName()) // Si c'est un getter ou un setter String propertyName = null; if (fieldAccess .getField() .getDeclaringClass() .equals(ctMethod.getDeclaringClass()) || ctMethod .getDeclaringClass() .subclassOf(fieldAccess.getField().getDeclaringClass())) { if ((ctMethod.getName().startsWith("get") || (!isFinal(fieldAccess.getField()) && ctMethod.getName().startsWith("set"))) && ctMethod.getName().length() > 3) { propertyName = ctMethod.getName().substring(3); propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); } } // On n'intercepte pas le getter de sa propre property if (propertyName == null || !propertyName.equals(fieldAccess.getFieldName())) { String invocationPoint = ctClass.getName() + "." + ctMethod.getName() + ", line " + fieldAccess.getLineNumber(); if (fieldAccess.isReader()) { // Réécris l'accés en lecture à la property fieldAccess.replace( "$_ = ($r)play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeReadProperty($0, \"" + fieldAccess.getFieldName() + "\", \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");"); } else if (!isFinal(fieldAccess.getField()) && fieldAccess.isWriter()) { // Réécris l'accés en ecriture à la property fieldAccess.replace( "play.classloading.enhancers.PropertiesEnhancer.FieldAccessor.invokeWriteProperty($0, \"" + fieldAccess.getFieldName() + "\", " + fieldAccess.getField().getType().getName() + ".class, $1, \"" + fieldAccess.getClassName() + "\", \"" + invocationPoint + "\");"); } } } } catch (Exception e) { throw new UnexpectedException("Error in PropertiesEnhancer", e); } } }); } // Done. applicationClass.enhancedByteCode = ctClass.toBytecode(); ctClass.defrost(); }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // Be careful with Apache library usage in this class (e.g. ArrayUtils). Usage will likely cause // a ClassCircularityError // under JRebel. Favor not including outside libraries and unnecessary classes. CtClass clazz = null; try { boolean mySkipOverlaps = skipOverlaps; boolean myRenameMethodOverlaps = renameMethodOverlaps; String convertedClassName = className.replace('/', '.'); ClassPool classPool = null; String xformKey = convertedClassName; String[] xformVals = null; Boolean[] xformSkipOverlaps = null; Boolean[] xformRenameMethodOverlaps = null; if (!xformTemplates.isEmpty()) { if (xformTemplates.containsKey(xformKey)) { xformVals = xformTemplates.get(xformKey).split(","); classPool = ClassPool.getDefault(); clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); } } else { if (annotationTransformedClasses.contains(convertedClassName)) { logger.warn( convertedClassName + " has already been transformed by a previous instance of DirectCopyTransfomer. " + "Skipping this annotation based transformation. Generally, annotation-based transformation is handled " + "by bean id blAnnotationDirectCopyClassTransformer with template tokens being added to " + "blDirectCopyTransformTokenMap via EarlyStageMergeBeanPostProcessor."); } boolean isValidPattern = true; List<DirectCopyIgnorePattern> matchedPatterns = new ArrayList<DirectCopyIgnorePattern>(); for (DirectCopyIgnorePattern pattern : ignorePatterns) { boolean isPatternMatch = false; for (String patternString : pattern.getPatterns()) { isPatternMatch = convertedClassName.matches(patternString); if (isPatternMatch) { break; } } if (isPatternMatch) { matchedPatterns.add(pattern); } isValidPattern = !(isPatternMatch && pattern.getTemplateTokenPatterns() == null); if (!isValidPattern) { return null; } } if (isValidPattern) { classPool = ClassPool.getDefault(); clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); List<?> attributes = clazz.getClassFile().getAttributes(); Iterator<?> itr = attributes.iterator(); List<String> templates = new ArrayList<String>(); List<Boolean> skips = new ArrayList<Boolean>(); List<Boolean> renames = new ArrayList<Boolean>(); check: { while (itr.hasNext()) { Object object = itr.next(); if (AnnotationsAttribute.class.isAssignableFrom(object.getClass())) { AnnotationsAttribute attr = (AnnotationsAttribute) object; Annotation[] items = attr.getAnnotations(); for (Annotation annotation : items) { String typeName = annotation.getTypeName(); if (typeName.equals(DirectCopyTransform.class.getName())) { ArrayMemberValue arrayMember = (ArrayMemberValue) annotation.getMemberValue("value"); for (MemberValue arrayMemberValue : arrayMember.getValue()) { AnnotationMemberValue member = (AnnotationMemberValue) arrayMemberValue; Annotation memberAnnot = member.getValue(); ArrayMemberValue annot = (ArrayMemberValue) memberAnnot.getMemberValue("templateTokens"); for (MemberValue memberValue : annot.getValue()) { String val = ((StringMemberValue) memberValue).getValue(); if (val != null && templateTokens.containsKey(val)) { templateCheck: { for (DirectCopyIgnorePattern matchedPattern : matchedPatterns) { for (String ignoreToken : matchedPattern.getTemplateTokenPatterns()) { if (val.matches(ignoreToken)) { break templateCheck; } } } templates.add(templateTokens.get(val)); } } } BooleanMemberValue skipAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("skipOverlaps"); if (skipAnnot != null) { skips.add(skipAnnot.getValue()); } else { skips.add(mySkipOverlaps); } BooleanMemberValue renameAnnot = (BooleanMemberValue) memberAnnot.getMemberValue("renameMethodOverlaps"); if (renameAnnot != null) { renames.add(renameAnnot.getValue()); } else { renames.add(myRenameMethodOverlaps); } } xformVals = templates.toArray(new String[templates.size()]); xformSkipOverlaps = skips.toArray(new Boolean[skips.size()]); xformRenameMethodOverlaps = renames.toArray(new Boolean[renames.size()]); break check; } } } } } } } if (xformVals != null && xformVals.length > 0) { logger.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); // Load the destination class and defrost it so it is eligible for modifications clazz.defrost(); int index = 0; for (String xformVal : xformVals) { // Load the source class String trimmed = xformVal.trim(); classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader())); CtClass template = classPool.get(trimmed); // Add in extra interfaces CtClass[] interfacesToCopy = template.getInterfaces(); for (CtClass i : interfacesToCopy) { checkInterfaces: { CtClass[] myInterfaces = clazz.getInterfaces(); for (CtClass myInterface : myInterfaces) { if (myInterface.getName().equals(i.getName())) { if (xformSkipOverlaps[index]) { break checkInterfaces; } else { throw new RuntimeException( "Duplicate interface detected " + myInterface.getName()); } } } logger.debug(String.format("Adding interface [%s]", i.getName())); clazz.addInterface(i); } } // copy over any EntityListeners ClassFile classFile = clazz.getClassFile(); ClassFile templateFile = template.getClassFile(); ConstPool constantPool = classFile.getConstPool(); buildClassLevelAnnotations(classFile, templateFile, constantPool); // Copy over all declared fields from the template class // Note that we do not copy over fields with the @NonCopiedField annotation CtField[] fieldsToCopy = template.getDeclaredFields(); for (CtField field : fieldsToCopy) { if (field.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding field [%s]", field.getName())); } else { try { CtField ctField = clazz.getDeclaredField(field.getName()); String originalSignature = ctField.getSignature(); String mySignature = field.getSignature(); if (!originalSignature.equals(mySignature)) { throw new IllegalArgumentException( "Field with name (" + field.getName() + ") and signature " + "(" + field.getSignature() + ") is targeted for weaving into (" + clazz.getName() + "). " + "An incompatible field of the same name and signature of (" + ctField.getSignature() + ") " + "already exists. The field in the target class should be updated to a different name, " + "or made to have a matching type."); } if (xformSkipOverlaps[index]) { logger.debug(String.format("Skipping overlapped field [%s]", field.getName())); continue; } } catch (NotFoundException e) { // do nothing -- field does not exist } logger.debug(String.format("Adding field [%s]", field.getName())); CtField copiedField = new CtField(field, clazz); boolean defaultConstructorFound = false; String implClass = getImplementationType(field.getType().getName()); // Look through all of the constructors in the implClass to see // if there is one that takes zero parameters try { CtConstructor[] implConstructors = classPool.get(implClass).getConstructors(); if (implConstructors != null) { for (CtConstructor cons : implConstructors) { if (cons.getParameterTypes().length == 0) { defaultConstructorFound = true; break; } } } } catch (NotFoundException e) { // Do nothing -- if we don't find this implementation, it's probably because it's // an array. In this case, we will not initialize the field. } if (defaultConstructorFound) { clazz.addField(copiedField, "new " + implClass + "()"); } else { clazz.addField(copiedField); } } } // Copy over all declared methods from the template class CtMethod[] methodsToCopy = template.getDeclaredMethods(); for (CtMethod method : methodsToCopy) { if (method.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding method [%s]", method.getName())); } else { try { CtClass[] paramTypes = method.getParameterTypes(); CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes); if (xformSkipOverlaps[index]) { logger.debug( String.format( "Skipping overlapped method [%s]", methodDescription(originalMethod))); continue; } if (transformedMethods.contains(methodDescription(originalMethod))) { throw new RuntimeException( "Method already replaced " + methodDescription(originalMethod)); } else { logger.debug( String.format("Marking as replaced [%s]", methodDescription(originalMethod))); transformedMethods.add(methodDescription(originalMethod)); } logger.debug(String.format("Removing method [%s]", method.getName())); if (xformRenameMethodOverlaps[index]) { originalMethod.setName(renameMethodPrefix + method.getName()); } else { clazz.removeMethod(originalMethod); } } catch (NotFoundException e) { // Do nothing -- we don't need to remove a method because it doesn't exist } logger.debug(String.format("Adding method [%s]", method.getName())); CtMethod copiedMethod = new CtMethod(method, clazz, null); clazz.addMethod(copiedMethod); } } index++; } if (xformTemplates.isEmpty()) { annotationTransformedClasses.add(convertedClassName); } logger.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); return clazz.toBytecode(); } } catch (ClassCircularityError error) { error.printStackTrace(); throw error; } catch (Exception e) { throw new RuntimeException("Unable to transform class", e); } finally { if (clazz != null) { clazz.detach(); } } return null; }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { String convertedClassName = className.replace('/', '.'); if (xformTemplates.containsKey(convertedClassName)) { String xformKey = convertedClassName; String[] xformVals = xformTemplates.get(xformKey).split(","); logger.lifecycle( LifeCycleEvent.START, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); try { // Load the destination class and defrost it so it is eligible for modifications ClassPool classPool = ClassPool.getDefault(); CtClass clazz = classPool.makeClass(new ByteArrayInputStream(classfileBuffer), false); clazz.defrost(); for (String xformVal : xformVals) { // Load the source class String trimmed = xformVal.trim(); classPool.appendClassPath(new LoaderClassPath(Class.forName(trimmed).getClassLoader())); CtClass template = classPool.get(trimmed); // Add in extra interfaces CtClass[] interfacesToCopy = template.getInterfaces(); for (CtClass i : interfacesToCopy) { logger.debug(String.format("Adding interface [%s]", i.getName())); clazz.addInterface(i); } // Copy over all declared fields from the template class // Note that we do not copy over fields with the @NonCopiedField annotation CtField[] fieldsToCopy = template.getDeclaredFields(); for (CtField field : fieldsToCopy) { if (field.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding field [%s]", field.getName())); } else { logger.debug(String.format("Adding field [%s]", field.getName())); CtField copiedField = new CtField(field, clazz); boolean defaultConstructorFound = false; String implClass = getImplementationType(field.getType().getName()); // Look through all of the constructors in the implClass to see // if there is one that takes zero parameters try { CtConstructor[] implConstructors = classPool.get(implClass).getConstructors(); if (implConstructors != null) { for (CtConstructor cons : implConstructors) { if (cons.getParameterTypes().length == 0) { defaultConstructorFound = true; break; } } } } catch (NotFoundException e) { // Do nothing -- if we don't find this implementation, it's probably because it's // an array. In this case, we will not initialize the field. } if (defaultConstructorFound) { clazz.addField(copiedField, "new " + implClass + "()"); } else { clazz.addField(copiedField); } } } // Copy over all declared methods from the template class CtMethod[] methodsToCopy = template.getDeclaredMethods(); for (CtMethod method : methodsToCopy) { if (method.hasAnnotation(NonCopied.class)) { logger.debug(String.format("Not adding method [%s]", method.getName())); } else { try { CtClass[] paramTypes = method.getParameterTypes(); CtMethod originalMethod = clazz.getDeclaredMethod(method.getName(), paramTypes); if (transformedMethods.contains(methodDescription(originalMethod))) { throw new RuntimeException( "Method already replaced " + methodDescription(originalMethod)); } else { logger.debug( String.format("Marking as replaced [%s]", methodDescription(originalMethod))); transformedMethods.add(methodDescription(originalMethod)); } logger.debug(String.format("Removing method [%s]", method.getName())); clazz.removeMethod(originalMethod); } catch (NotFoundException e) { // Do nothing -- we don't need to remove a method because it doesn't exist } logger.debug(String.format("Adding method [%s]", method.getName())); CtMethod copiedMethod = new CtMethod(method, clazz, null); clazz.addMethod(copiedMethod); } } } logger.lifecycle( LifeCycleEvent.END, String.format( "Transform - Copying into [%s] from [%s]", xformKey, StringUtils.join(xformVals, ","))); return clazz.toBytecode(); } catch (Exception e) { throw new RuntimeException("Unable to transform class", e); } } return null; }
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(); }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { // Don't transform system classes. This reason is: // - To improve performance // - To avoid unexpected behaviors. // For example, if transforms java.lang.invoke.** classes in Java8 // even without any ctClass modification, the classes become broken // and Java stream API call fails unexpectedly. // Maybe this is because CtClass instance generated by ClassPool.makeClass method // is cached on global default ClassPool instance. if (isJavaSystemClassName(className)) { return null; } // TODO don't need to do anything for java package classes ClassPool classPool = ClassPool.getDefault(); String hookClassName = HookMethodDef.class.getCanonicalName(); String initializeSrc = hookInitializeSrc(); boolean transformed = false; InputStream stream = null; try { stream = new ByteArrayInputStream(classfileBuffer); CtClass ctClass = null; try { ctClass = classPool.makeClass(stream, true); } catch (RuntimeException e) { // makeClass raises RuntimeException when the existing class is frozen. // Since frozen classes are maybe system class, just ignore this exception return null; } for (Pair<CtMethod, TestMethod> pair : allSubMethods(srcTree, ctClass)) { CtMethod ctSubMethod = pair.getLeft(); TestMethod subMethod = pair.getRight(); if (ctSubMethod.isEmpty()) { logger.info("skip empty method: " + ctSubMethod.getLongName()); continue; // cannot hook empty method } String subClassQualifiedName = subMethod.getTestClass().getQualifiedName(); String subMethodSimpleName = subMethod.getSimpleName(); String subMethodArgClassesStr = TestMethod.argClassQualifiedNamesToArgClassesStr( getArgClassQualifiedNames(ctSubMethod)); for (int i = 0; i < subMethod.getCodeBody().size(); i++) { CodeLine codeLine = subMethod.getCodeBody().get(i); if (i + 1 < subMethod.getCodeBody().size()) { CodeLine nextCodeLine = subMethod.getCodeBody().get(i + 1); assert codeLine.getEndLine() <= nextCodeLine.getStartLine(); if (codeLine.getEndLine() == nextCodeLine.getStartLine()) { // - if multiple statements exist on a line, insert hook only after the last statement // - avoid insertion at the middle of the statement. // The problem happens when multi-line statements are like: // method(1);method( // 2); continue; } } // Hook should be inserted just after the code has finished // since the code inserted by the insertAt method is inserted just before the specified // line. int insertedLine = subMethod.getCodeBody().get(i).getEndLine() + 1; int actualInsertedLine = ctSubMethod.insertAt(insertedLine, false, null); ctSubMethod.insertAt( insertedLine, String.format( "%s%s.beforeCodeLineHook(\"%s\",\"%s\",\"%s\",\"%s\",%d, %d);", initializeSrc, hookClassName, subClassQualifiedName, subMethodSimpleName, subMethodSimpleName, subMethodArgClassesStr, codeLine.getStartLine(), actualInsertedLine)); transformed = true; } } CtClass exceptionType = classPool.get(Throwable.class.getCanonicalName()); for (Pair<CtMethod, TestMethod> pair : allRootMethods(srcTree, ctClass)) { CtMethod ctRootMethod = pair.getLeft(); TestMethod rootMethod = pair.getRight(); if (ctRootMethod.isEmpty()) { continue; // cannot hook empty method } String rootClassQualifiedName = rootMethod.getTestClass().getQualifiedName(); String rootMethodSimpleName = rootMethod.getSimpleName(); String rootMethodArgClassesStr = TestMethod.argClassQualifiedNamesToArgClassesStr( getArgClassQualifiedNames(ctRootMethod)); for (int i = 0; i < rootMethod.getCodeBody().size(); i++) { CodeLine codeLine = rootMethod.getCodeBody().get(i); if (i + 1 < rootMethod.getCodeBody().size()) { CodeLine nextCodeLine = rootMethod.getCodeBody().get(i + 1); assert codeLine.getEndLine() <= nextCodeLine.getStartLine(); if (codeLine.getEndLine() == nextCodeLine.getStartLine()) { // - if multiple statements exist on a line, insert hook only after the last statement // - avoid insertion at the middle of the statement. // The problem happens when multi-line statements are like: // method(1);method( // 2); continue; // TODO screen capture is not taken correctly for multiple statements in a line } } // Hook should be inserted just after the code has finished // since the code inserted by the insertAt method is inserted just before the specified // line. int insertedLine = rootMethod.getCodeBody().get(i).getEndLine() + 1; int actualInsertedLine = ctRootMethod.insertAt(insertedLine, false, null); ctRootMethod.insertAt( insertedLine, String.format( "%s%s.beforeCodeLineHook(\"%s\",\"%s\",\"%s\",\"%s\",%d,%d);", initializeSrc, hookClassName, rootClassQualifiedName, rootMethodSimpleName, rootMethodSimpleName, rootMethodArgClassesStr, codeLine.getStartLine(), actualInsertedLine)); } ctRootMethod.insertBefore( String.format( "%s%s.beforeMethodHook(\"%s\",\"%s\",\"%s\");", initializeSrc, hookClassName, rootClassQualifiedName, rootMethodSimpleName, rootMethodSimpleName)); ctRootMethod.addCatch( String.format( "{ %s%s.methodErrorHook(\"%s\",\"%s\",$e); throw $e; }", initializeSrc, hookClassName, rootClassQualifiedName, rootMethodSimpleName), exceptionType); ctRootMethod.insertAfter( String.format( "%s%s.afterMethodHook(\"%s\",\"%s\");", initializeSrc, hookClassName, rootClassQualifiedName, rootMethodSimpleName), true); transformed = true; } // don't transform not changed ctClass // (to improve performance and avoid unexpected error) if (transformed) { logger.info("transform " + className); return ctClass.toBytecode(); } else { return null; } } catch (CannotCompileException e) { // print error since exception in transform method is just ignored System.err.println("exception on " + className); e.printStackTrace(); throw new IllegalClassFormatException(e.getLocalizedMessage()); } catch (Exception e) { // print error since exception in transform method is just ignored System.err.println("exception on " + className); e.printStackTrace(); throw new RuntimeException(e); } finally { IOUtils.closeQuietly(stream); } }
public byte[] injectReactive(String classname) throws Exception { init(); CtClass droolsPojo = cp.get(classname); if (collectReactiveFields(droolsPojo).size() == 0) { LOG.info( "Skipped bytecode injection in class " + droolsPojo.getName() + " because no fields candidated for reactivity."); return droolsPojo.toBytecode(); } droolsPojo.addInterface(cp.get(ReactiveObject.class.getName())); CtField ltsCtField = new CtField(cp.get(Collection.class.getName()), DROOLS_LIST_OF_TUPLES, droolsPojo); ltsCtField.setModifiers(Modifier.PRIVATE); ClassType listOfTuple = new SignatureAttribute.ClassType( Collection.class.getName(), new TypeArgument[] { new TypeArgument(new SignatureAttribute.ClassType(Tuple.class.getName())) }); ltsCtField.setGenericSignature(listOfTuple.encode()); // Do not use the Initializer.byNew... as those method always pass at least 1 parameter which is // "this". droolsPojo.addField(ltsCtField, Initializer.byExpr("new java.util.HashSet();")); final CtMethod getLeftTuplesCtMethod = CtNewMethod.make( "public java.util.Collection getLeftTuples() {\n" + " return this.$$_drools_lts != null ? this.$$_drools_lts : java.util.Collections.emptyList();\n" + "}", droolsPojo); MethodSignature getLeftTuplesSignature = new MethodSignature(null, null, listOfTuple, null); getLeftTuplesCtMethod.setGenericSignature(getLeftTuplesSignature.encode()); droolsPojo.addMethod(getLeftTuplesCtMethod); final CtMethod addLeftTupleCtMethod = CtNewMethod.make( "public void addLeftTuple(" + Tuple.class.getName() + " leftTuple) {\n" + " if ($$_drools_lts == null) {\n" + " $$_drools_lts = new java.util.HashSet();\n" + " }\n" + " $$_drools_lts.add(leftTuple);\n" + "}", droolsPojo); droolsPojo.addMethod(addLeftTupleCtMethod); final CtMethod removeLeftTupleCtMethod = CtNewMethod.make( "public void removeLeftTuple(" + Tuple.class.getName() + " leftTuple) {\n" + " $$_drools_lts.remove(leftTuple);\n" + "}", droolsPojo); droolsPojo.addMethod(removeLeftTupleCtMethod); Map<String, CtField> fieldsMap = collectReactiveFields(droolsPojo); for (CtField f : fieldsMap.values()) { LOG.debug("Preparing field writer method for field: {}.", f); writeMethods.put(f.getName(), makeWriter(droolsPojo, f)); } enhanceAttributesAccess(fieldsMap, droolsPojo); // first call CtClass.toClass() before the original class is loaded, it will persist the // bytecode instrumentation changes in the classloader. return droolsPojo.toBytecode(); }
public Class<?> toClass( ToClassInvokerPoolReference pool, CtClass cc, String classFileName, ClassLoader loader, ProtectionDomain domain) throws CannotCompileException { boolean trace = logger.isTraceEnabled(); pool.lockInCache(cc); final ClassLoader myloader = pool.getClassLoader(); if (myloader == null || tmpDir == null) { if (trace) logger.trace( this + " " + pool + ".toClass() myloader:" + myloader + " tmpDir:" + tmpDir + " default to superPool.toClass for " + cc.getName()); Class<?> clazz = pool.superPoolToClass(cc, loader, domain); if (trace) logger.trace(this + " " + pool + " myloader:" + myloader + " created class:" + clazz); return clazz; } Class<?> dynClass = null; try { File classFile = null; // Write the clas file to the tmpdir synchronized (tmplock) { classFile = new File(tmpDir, classFileName); if (trace) logger.trace( this + " " + pool + ".toClass() myloader:" + myloader + " writing bytes to " + classFile); File pkgDirs = classFile.getParentFile(); pkgDirs.mkdirs(); FileOutputStream stream = new FileOutputStream(classFile); stream.write(cc.toBytecode()); stream.flush(); stream.close(); classFile.deleteOnExit(); } // We have to clear Blacklist caches or the class will never // be found // ((UnifiedClassLoader)dcl).clearBlacklists(); // To be backward compatible RepositoryClassLoader rcl = (RepositoryClassLoader) myloader; rcl.clearClassBlackList(); rcl.clearResourceBlackList(); // Now load the class through the cl dynClass = myloader.loadClass(cc.getName()); if (trace) logger.trace(this + " " + pool + " myloader:" + myloader + " created class:" + dynClass); return dynClass; } catch (Exception ex) { ClassFormatError cfe = new ClassFormatError("Failed to load dyn class: " + cc.getName()); cfe.initCause(ex); throw cfe; } }