@SuppressWarnings("unchecked") public <T, I> T getImplementationClass( // QueryClassLoader classLoader, // TemplateClassDefinition<T> templateDefinition, // String entireClass, // String materializedClassName) throws ClassTransformationException { final ClassSet set = new ClassSet(null, templateDefinition.getTemplateClassName(), materializedClassName); try { final byte[][] implementationClasses = classLoader.getClassByteCode(set.generated.clazz, entireClass); Map<String, ClassNode> classesToMerge = Maps.newHashMap(); for (byte[] clazz : implementationClasses) { ClassNode node = getClassNodeFromByteCode(clazz); classesToMerge.put(node.name, node); } LinkedList<ClassSet> names = Lists.newLinkedList(); Set<ClassSet> namesCompleted = Sets.newHashSet(); names.add(set); while (!names.isEmpty()) { final ClassSet nextSet = names.removeFirst(); if (namesCompleted.contains(nextSet)) continue; final ClassNames nextPrecompiled = nextSet.precompiled; final byte[] precompiledBytes = byteCodeLoader.getClassByteCodeFromPath(nextPrecompiled.clazz); ClassNames nextGenerated = nextSet.generated; ClassNode generatedNode = classesToMerge.get(nextGenerated.slash); MergedClassResult result = MergeAdapter.getMergedClass(nextSet, precompiledBytes, generatedNode); for (String s : result.innerClasses) { s = s.replace(FileUtils.separatorChar, '.'); names.add(nextSet.getChild(s)); } classLoader.injectByteCode(nextGenerated.dot, result.bytes); namesCompleted.add(nextSet); } // logger.debug(String.format("[Compile Time] Janino: %dms, Bytecode load and parse: // %dms, Class Merge: %dms, Subclass remap and load: %dms.", // t1.elapsed(TimeUnit.MILLISECONDS), t2.elapsed(TimeUnit.MILLISECONDS), // t3.elapsed(TimeUnit.MILLISECONDS), t4.elapsed(TimeUnit.MILLISECONDS))); Class<?> c = classLoader.findClass(set.generated.dot); if (templateDefinition.getExternalInterface().isAssignableFrom(c)) { return (T) c.newInstance(); } else { throw new ClassTransformationException( "The requested class did not implement the expected interface."); } } catch (CompileException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new ClassTransformationException( String.format("Failure generating transformation classes for value: \n %s", entireClass), e); } }
@SuppressWarnings("unchecked") public <T, I> T getImplementationClass( // QueryClassLoader classLoader, // TemplateClassDefinition<T> templateDefinition, // String entireClass, // String materializedClassName) throws ClassTransformationException { try { long t1 = System.nanoTime(); final ClassSet set = new ClassSet(null, templateDefinition.getTemplateClassName(), materializedClassName); final byte[][] implementationClasses = classLoader.getClassByteCode(set.generated, entireClass); long totalBytecodeSize = 0; Map<String, ClassNode> classesToMerge = Maps.newHashMap(); for (byte[] clazz : implementationClasses) { totalBytecodeSize += clazz.length; ClassNode node = getClassNodeFromByteCode(clazz); classesToMerge.put(node.name, node); } LinkedList<ClassSet> names = Lists.newLinkedList(); Set<ClassSet> namesCompleted = Sets.newHashSet(); names.add(set); while (!names.isEmpty()) { final ClassSet nextSet = names.removeFirst(); if (namesCompleted.contains(nextSet)) continue; final ClassNames nextPrecompiled = nextSet.precompiled; final byte[] precompiledBytes = byteCodeLoader.getClassByteCodeFromPath(nextPrecompiled.clazz); ClassNames nextGenerated = nextSet.generated; ClassNode generatedNode = classesToMerge.get(nextGenerated.slash); MergedClassResult result = MergeAdapter.getMergedClass(nextSet, precompiledBytes, generatedNode); for (String s : result.innerClasses) { s = s.replace(FileUtils.separatorChar, '.'); names.add(nextSet.getChild(s)); } classLoader.injectByteCode(nextGenerated.dot, result.bytes); namesCompleted.add(nextSet); } Class<?> c = classLoader.findClass(set.generated.dot); if (templateDefinition.getExternalInterface().isAssignableFrom(c)) { T instance = (T) c.newInstance(); logger.debug( "Done compiling (bytecode size={}, time:{} millis).", DrillStringUtils.readable(totalBytecodeSize), (System.nanoTime() - t1) / 1000000); return instance; } else { throw new ClassTransformationException( "The requested class did not implement the expected interface."); } } catch (CompileException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new ClassTransformationException( String.format("Failure generating transformation classes for value: \n %s", entireClass), e); } }