/** * Loads the given class node returning the implementation Class. * * <p>WARNING: this compilation is not synchronized * * @param classNode * @return a class */ public Class defineClass(ClassNode classNode, String file, String newCodeBase) { CodeSource codeSource = null; try { codeSource = new CodeSource(new URL("file", "", newCodeBase), (java.security.cert.Certificate[]) null); } catch (MalformedURLException e) { // swallow } CompilationUnit unit = createCompilationUnit(config, codeSource); ClassCollector collector = createCollector(unit, classNode.getModule().getContext()); try { unit.addClassNode(classNode); unit.setClassgenCallback(collector); unit.compile(Phases.CLASS_GENERATION); definePackage(collector.generatedClass.getName()); return collector.generatedClass; } catch (CompilationFailedException e) { throw new RuntimeException(e); } }
/** * Compile the specified Groovy source files, applying any {@link CompilerAutoConfiguration}s. All * classes defined in the files will be returned from this method. * * @param file the file to compile * @return compiled classes * @throws CompilationFailedException * @throws IOException */ public Class<?>[] compile(File... file) throws CompilationFailedException, IOException { this.loader.clearCache(); List<Class<?>> classes = new ArrayList<Class<?>>(); CompilerConfiguration configuration = this.loader.getConfiguration(); CompilationUnit compilationUnit = new CompilationUnit(configuration, null, this.loader); SourceUnit sourceUnit = new SourceUnit(file[0], configuration, this.loader, compilationUnit.getErrorCollector()); ClassCollector collector = this.loader.createCollector(compilationUnit, sourceUnit); compilationUnit.setClassgenCallback(collector); compilationUnit.addSources(file); addAstTransformations(compilationUnit); compilationUnit.compile(Phases.CLASS_GENERATION); for (Object loadedClass : collector.getLoadedClasses()) { classes.add((Class<?>) loadedClass); } ClassNode mainClassNode = (ClassNode) compilationUnit.getAST().getClasses().get(0); Class<?> mainClass = null; for (Class<?> loadedClass : classes) { if (mainClassNode.getName().equals(loadedClass.getName())) { mainClass = loadedClass; } } if (mainClass != null) { classes.remove(mainClass); classes.add(0, mainClass); } return classes.toArray(new Class<?>[classes.size()]); }
public static void addPhaseOperations(final CompilationUnit compilationUnit) { final ASTTransformationsContext context = compilationUnit.getASTTransformationsContext(); addGlobalTransforms(context); compilationUnit.addPhaseOperation( new CompilationUnit.PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { ASTTransformationCollectorCodeVisitor collector = new ASTTransformationCollectorCodeVisitor( source, compilationUnit.getTransformLoader()); collector.visitClass(classNode); } }, Phases.SEMANTIC_ANALYSIS); for (CompilePhase phase : CompilePhase.values()) { final ASTTransformationVisitor visitor = new ASTTransformationVisitor(phase, context); switch (phase) { case INITIALIZATION: case PARSING: case CONVERSION: // with transform detection alone these phases are inaccessible, so don't add it break; default: compilationUnit.addPhaseOperation( new CompilationUnit.PrimaryClassNodeOperation() { public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { visitor.source = source; visitor.visitClass(classNode); } }, phase.getPhaseNumber()); break; } } }
protected Class createClass(byte[] code, ClassNode classNode) { BytecodeProcessor bytecodePostprocessor = unit.getConfiguration().getBytecodePostprocessor(); byte[] fcode = code; if (bytecodePostprocessor != null) { fcode = bytecodePostprocessor.processBytecode(classNode.getName(), fcode); } GroovyClassLoader cl = getDefiningClassLoader(); Class theClass = cl.defineClass( classNode.getName(), fcode, 0, fcode.length, unit.getAST().getCodeSource()); this.loadedClasses.add(theClass); if (generatedClass == null) { ModuleNode mn = classNode.getModule(); SourceUnit msu = null; if (mn != null) msu = mn.getContext(); ClassNode main = null; if (mn != null) main = (ClassNode) mn.getClasses().get(0); if (msu == su && main == classNode) generatedClass = theClass; } return theClass; }
private Class doParseClass(GroovyCodeSource codeSource) { validate(codeSource); Class answer; // Was neither already loaded nor compiling, so compile and add to cache. CompilationUnit unit = createCompilationUnit(config, codeSource.getCodeSource()); if (recompile != null && recompile || recompile == null && config.getRecompileGroovySource()) { unit.addFirstPhaseOperation( TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber()); } SourceUnit su = null; File file = codeSource.getFile(); if (file != null) { su = unit.addSource(file); } else { URL url = codeSource.getURL(); if (url != null) { su = unit.addSource(url); } else { su = unit.addSource(codeSource.getName(), codeSource.getScriptText()); } } ClassCollector collector = createCollector(unit, su); unit.setClassgenCallback(collector); int goalPhase = Phases.CLASS_GENERATION; if (config != null && config.getTargetDirectory() != null) goalPhase = Phases.OUTPUT; unit.compile(goalPhase); answer = collector.generatedClass; String mainClass = su.getAST().getMainClassName(); for (Object o : collector.getLoadedClasses()) { Class clazz = (Class) o; String clazzName = clazz.getName(); definePackage(clazzName); setClassCacheEntry(clazz); if (clazzName.equals(mainClass)) answer = clazz; } return answer; }
public void visit(ASTNode[] nodes, final SourceUnit source) { init(nodes, source); AnnotatedNode targetClass = (AnnotatedNode) nodes[1]; AnnotationNode logAnnotation = (AnnotationNode) nodes[0]; final GroovyClassLoader classLoader = compilationUnit != null ? compilationUnit.getTransformLoader() : source.getClassLoader(); final LoggingStrategy loggingStrategy = createLoggingStrategy(logAnnotation, classLoader); if (loggingStrategy == null) return; final String logFieldName = lookupLogFieldName(logAnnotation); final String categoryName = lookupCategoryName(logAnnotation); if (!(targetClass instanceof ClassNode)) throw new GroovyBugError( "Class annotation " + logAnnotation.getClassNode().getName() + " annotated no Class, this must not happen."); final ClassNode classNode = (ClassNode) targetClass; ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() { private FieldNode logNode; @Override protected SourceUnit getSourceUnit() { return source; } public Expression transform(Expression exp) { if (exp == null) return null; if (exp instanceof MethodCallExpression) { return transformMethodCallExpression(exp); } if (exp instanceof ClosureExpression) { return transformClosureExpression((ClosureExpression) exp); } return super.transform(exp); } @Override public void visitClass(ClassNode node) { FieldNode logField = node.getField(logFieldName); if (logField != null && logField.getOwner().equals(node)) { addError( "Class annotated with Log annotation cannot have log field declared", logField); } else if (logField != null && !Modifier.isPrivate(logField.getModifiers())) { addError( "Class annotated with Log annotation cannot have log field declared because the field exists in the parent class: " + logField.getOwner().getName(), logField); } else { logNode = loggingStrategy.addLoggerFieldToClass(node, logFieldName, categoryName); } super.visitClass(node); } private Expression transformClosureExpression(ClosureExpression exp) { if (exp.getCode() instanceof BlockStatement) { BlockStatement code = (BlockStatement) exp.getCode(); super.visitBlockStatement(code); } return exp; } private Expression transformMethodCallExpression(Expression exp) { MethodCallExpression mce = (MethodCallExpression) exp; if (!(mce.getObjectExpression() instanceof VariableExpression)) { return exp; } VariableExpression variableExpression = (VariableExpression) mce.getObjectExpression(); if (!variableExpression.getName().equals(logFieldName) || !(variableExpression.getAccessedVariable() instanceof DynamicVariable)) { return exp; } String methodName = mce.getMethodAsString(); if (methodName == null) return exp; if (usesSimpleMethodArgumentsOnly(mce)) return exp; variableExpression.setAccessedVariable(logNode); if (!loggingStrategy.isLoggingMethod(methodName)) return exp; return loggingStrategy.wrapLoggingMethodCall(variableExpression, methodName, exp); } private boolean usesSimpleMethodArgumentsOnly(MethodCallExpression mce) { Expression arguments = mce.getArguments(); if (arguments instanceof TupleExpression) { TupleExpression tuple = (TupleExpression) arguments; for (Expression exp : tuple.getExpressions()) { if (!isSimpleExpression(exp)) return false; } return true; } return !isSimpleExpression(arguments); } private boolean isSimpleExpression(Expression exp) { if (exp instanceof ConstantExpression) return true; if (exp instanceof VariableExpression) return true; return false; } }; transformer.visitClass(classNode); // GROOVY-6373: references to 'log' field are normally already FieldNodes by now, so revisit // scoping new VariableScopeVisitor(sourceUnit, true).visitClass(classNode); }
private static void addPhaseOperationsForGlobalTransforms( CompilationUnit compilationUnit, Map<String, URL> transformNames, boolean isFirstScan) { GroovyClassLoader transformLoader = compilationUnit.getTransformLoader(); for (Map.Entry<String, URL> entry : transformNames.entrySet()) { try { Class gTransClass = transformLoader.loadClass(entry.getKey(), false, true, false); // no inspection unchecked GroovyASTTransformation transformAnnotation = (GroovyASTTransformation) gTransClass.getAnnotation(GroovyASTTransformation.class); if (transformAnnotation == null) { compilationUnit .getErrorCollector() .addWarning( new WarningMessage( WarningMessage.POSSIBLE_ERRORS, "Transform Class " + entry.getKey() + " is specified as a global transform in " + entry.getValue().toExternalForm() + " but it is not annotated by " + GroovyASTTransformation.class.getName() + " the global transform associated with it may fail and cause the compilation to fail.", null, null)); continue; } if (ASTTransformation.class.isAssignableFrom(gTransClass)) { final ASTTransformation instance = (ASTTransformation) gTransClass.newInstance(); if (instance instanceof CompilationUnitAware) { ((CompilationUnitAware) instance).setCompilationUnit(compilationUnit); } CompilationUnit.SourceUnitOperation suOp = new CompilationUnit.SourceUnitOperation() { public void call(SourceUnit source) throws CompilationFailedException { instance.visit(new ASTNode[] {source.getAST()}, source); } }; if (isFirstScan) { compilationUnit.addPhaseOperation(suOp, transformAnnotation.phase().getPhaseNumber()); } else { compilationUnit.addNewPhaseOperation( suOp, transformAnnotation.phase().getPhaseNumber()); } } else { compilationUnit .getErrorCollector() .addError( new SimpleMessage( "Transform Class " + entry.getKey() + " specified at " + entry.getValue().toExternalForm() + " is not an ASTTransformation.", null)); } } catch (Exception e) { compilationUnit .getErrorCollector() .addError( new SimpleMessage( "Could not instantiate global transform class " + entry.getKey() + " specified at " + entry.getValue().toExternalForm() + " because of exception " + e.toString(), null)); } } }
private static void doAddGlobalTransforms( ASTTransformationsContext context, boolean isFirstScan) { final CompilationUnit compilationUnit = context.getCompilationUnit(); GroovyClassLoader transformLoader = compilationUnit.getTransformLoader(); Map<String, URL> transformNames = new LinkedHashMap<String, URL>(); try { Enumeration<URL> globalServices = transformLoader.getResources( "META-INF/services/org.codehaus.groovy.transform.ASTTransformation"); while (globalServices.hasMoreElements()) { URL service = globalServices.nextElement(); String className; BufferedReader svcIn = null; try { svcIn = new BufferedReader(new InputStreamReader(service.openStream())); try { className = svcIn.readLine(); } catch (IOException ioe) { compilationUnit .getErrorCollector() .addError( new SimpleMessage( "IOException reading the service definition at " + service.toExternalForm() + " because of exception " + ioe.toString(), null)); continue; } Set<String> disabledGlobalTransforms = compilationUnit.getConfiguration().getDisabledGlobalASTTransformations(); if (disabledGlobalTransforms == null) disabledGlobalTransforms = Collections.emptySet(); while (className != null) { if (!className.startsWith("#") && className.length() > 0) { if (!disabledGlobalTransforms.contains(className)) { if (transformNames.containsKey(className)) { if (!service.equals(transformNames.get(className))) { compilationUnit .getErrorCollector() .addWarning( WarningMessage.POSSIBLE_ERRORS, "The global transform for class " + className + " is defined in both " + transformNames.get(className).toExternalForm() + " and " + service.toExternalForm() + " - the former definition will be used and the latter ignored.", null, null); } } else { transformNames.put(className, service); } } } try { className = svcIn.readLine(); } catch (IOException ioe) { compilationUnit .getErrorCollector() .addError( new SimpleMessage( "IOException reading the service definition at " + service.toExternalForm() + " because of exception " + ioe.toString(), null)); //noinspection UnnecessaryContinue continue; } } } finally { if (svcIn != null) svcIn.close(); } } } catch (IOException e) { // FIXME the warning message will NPE with what I have :( compilationUnit .getErrorCollector() .addError( new SimpleMessage( "IO Exception attempting to load global transforms:" + e.getMessage(), null)); } try { Class.forName("java.lang.annotation.Annotation"); // test for 1.5 JVM } catch (Exception e) { // we failed, notify the user StringBuffer sb = new StringBuffer(); sb.append("Global ASTTransformations are not enabled in retro builds of groovy.\n"); sb.append("The following transformations will be ignored:"); for (Map.Entry<String, URL> entry : transformNames.entrySet()) { sb.append('\t'); sb.append(entry.getKey()); sb.append('\n'); } compilationUnit .getErrorCollector() .addWarning( new WarningMessage(WarningMessage.POSSIBLE_ERRORS, sb.toString(), null, null)); return; } // record the transforms found in the first scan, so that in the 2nd scan, phase operations // can be added for only for new transforms that have come in if (isFirstScan) { for (Map.Entry<String, URL> entry : transformNames.entrySet()) { context.getGlobalTransformNames().add(entry.getKey()); } addPhaseOperationsForGlobalTransforms( context.getCompilationUnit(), transformNames, isFirstScan); } else { Iterator<Map.Entry<String, URL>> it = transformNames.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, URL> entry = it.next(); if (!context.getGlobalTransformNames().add(entry.getKey())) { // phase operations for this transform class have already been added before, so remove // from current scan cycle it.remove(); } } addPhaseOperationsForGlobalTransforms( context.getCompilationUnit(), transformNames, isFirstScan); } }
public void compile(File[] files) throws Exception { unit.addSources(files); unit.compile(); }
public void visit(ASTNode[] nodes, SourceUnit source) { sourceUnit = source; loader = null; initContextClassLoader = false; ModuleNode mn = (ModuleNode) nodes[0]; allowShortGrab = true; allowShortGrabExcludes = true; allowShortGrabConfig = true; allowShortGrapes = true; allowShortGrabResolver = true; grabAliases = new HashSet<String>(); grabExcludeAliases = new HashSet<String>(); grabConfigAliases = new HashSet<String>(); grapesAliases = new HashSet<String>(); grabResolverAliases = new HashSet<String>(); for (ImportNode im : mn.getImports()) { String alias = im.getAlias(); String className = im.getClassName(); if ((className.endsWith(GRAB_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRAB_CLASS_NAME.equals(alias))) { allowShortGrab = false; } else if (GRAB_CLASS_NAME.equals(className)) { grabAliases.add(im.getAlias()); } if ((className.endsWith(GRAPES_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRAPES_CLASS_NAME.equals(alias))) { allowShortGrapes = false; } else if (GRAPES_CLASS_NAME.equals(className)) { grapesAliases.add(im.getAlias()); } if ((className.endsWith(GRABRESOLVER_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRABRESOLVER_CLASS_NAME.equals(alias))) { allowShortGrabResolver = false; } else if (GRABRESOLVER_CLASS_NAME.equals(className)) { grabResolverAliases.add(im.getAlias()); } } List<Map<String, Object>> grabMaps = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> grabExcludeMaps = new ArrayList<Map<String, Object>>(); for (ClassNode classNode : sourceUnit.getAST().getClasses()) { grabAnnotations = new ArrayList<AnnotationNode>(); grabExcludeAnnotations = new ArrayList<AnnotationNode>(); grabConfigAnnotations = new ArrayList<AnnotationNode>(); grapesAnnotations = new ArrayList<AnnotationNode>(); grabResolverAnnotations = new ArrayList<AnnotationNode>(); visitClass(classNode); ClassNode grapeClassNode = ClassHelper.make(Grape.class); List<Statement> grabResolverInitializers = new ArrayList<Statement>(); if (!grapesAnnotations.isEmpty()) { for (AnnotationNode node : grapesAnnotations) { Expression init = node.getMember("initClass"); Expression value = node.getMember("value"); if (value instanceof ListExpression) { for (Object o : ((ListExpression) value).getExpressions()) { if (o instanceof ConstantExpression) { extractGrab(init, (ConstantExpression) o); } } } else if (value instanceof ConstantExpression) { extractGrab(init, (ConstantExpression) value); } // don't worry if it's not a ListExpression, or AnnotationConstant, etc. // the rest of GroovyC will flag it as a syntax error later, so we don't // need to raise the error ourselves } } if (!grabResolverAnnotations.isEmpty()) { grabResolverAnnotationLoop: for (AnnotationNode node : grabResolverAnnotations) { Map<String, Object> grabResolverMap = new HashMap<String, Object>(); Expression value = node.getMember("value"); ConstantExpression ce = null; if (value != null && value instanceof ConstantExpression) { ce = (ConstantExpression) value; } String sval = null; if (ce != null && ce.getValue() instanceof String) { sval = (String) ce.getValue(); } if (sval != null && sval.length() > 0) { for (String s : GRABRESOLVER_REQUIRED) { Expression member = node.getMember(s); if (member != null) { addError( "The attribute \"" + s + "\" conflicts with attribute 'value' in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } } grabResolverMap.put("name", sval); grabResolverMap.put("root", sval); } else { for (String s : GRABRESOLVER_REQUIRED) { Expression member = node.getMember(s); if (member == null) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } else if (member != null && !(member instanceof ConstantExpression)) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } grabResolverMap.put(s, ((ConstantExpression) member).getValue()); } } Grape.addResolver(grabResolverMap); addGrabResolverAsStaticInitIfNeeded( grapeClassNode, node, grabResolverInitializers, grabResolverMap); } } if (!grabConfigAnnotations.isEmpty()) { for (AnnotationNode node : grabConfigAnnotations) { checkForClassLoader(node); checkForInitContextClassLoader(node); checkForAutoDownload(node); checkForDisableChecksums(node); } addInitContextClassLoaderIfNeeded(classNode); } if (!grabExcludeAnnotations.isEmpty()) { grabExcludeAnnotationLoop: for (AnnotationNode node : grabExcludeAnnotations) { Map<String, Object> grabExcludeMap = new HashMap<String, Object>(); checkForConvenienceForm(node, true); for (String s : GRABEXCLUDE_REQUIRED) { Expression member = node.getMember(s); if (member == null) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabExcludeAnnotationLoop; } else if (member != null && !(member instanceof ConstantExpression)) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabExcludeAnnotationLoop; } grabExcludeMap.put(s, ((ConstantExpression) member).getValue()); } grabExcludeMaps.add(grabExcludeMap); } } if (!grabAnnotations.isEmpty()) { grabAnnotationLoop: for (AnnotationNode node : grabAnnotations) { Map<String, Object> grabMap = new HashMap<String, Object>(); checkForConvenienceForm(node, false); for (String s : GRAB_ALL) { Expression member = node.getMember(s); if (member == null && !GRAB_OPTIONAL.contains(s)) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabAnnotationLoop; } else if (member != null && !(member instanceof ConstantExpression)) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabAnnotationLoop; } if (node.getMember(s) != null) grabMap.put(s, ((ConstantExpression) member).getValue()); } grabMaps.add(grabMap); callGrabAsStaticInitIfNeeded(classNode, grapeClassNode, node, grabExcludeMaps); } } if (!grabResolverInitializers.isEmpty()) { classNode.addStaticInitializerStatements(grabResolverInitializers, true); } } if (!grabMaps.isEmpty()) { Map<String, Object> basicArgs = new HashMap<String, Object>(); basicArgs.put("classLoader", loader != null ? loader : sourceUnit.getClassLoader()); if (!grabExcludeMaps.isEmpty()) basicArgs.put("excludes", grabExcludeMaps); if (autoDownload != null) basicArgs.put(AUTO_DOWNLOAD_SETTING, autoDownload); if (disableChecksums != null) basicArgs.put(DISABLE_CHECKSUMS_SETTING, disableChecksums); try { Grape.grab(basicArgs, grabMaps.toArray(new Map[grabMaps.size()])); // grab may have added more transformations through new URLs added to classpath, so do one // more scan if (compilationUnit != null) { ASTTransformationVisitor.addGlobalTransformsAfterGrab( compilationUnit.getASTTransformationsContext()); } } catch (RuntimeException re) { // Decided against syntax exception since this is not a syntax error. // The down side is we lose line number information for the offending // @Grab annotation. source.addException(re); } } }
public void compile(String[] paths) throws Exception { unit.addSources(paths); unit.compile(); }
public void compile() { if (compiledTemplate == null) { try { long start = System.currentTimeMillis(); TClassLoader tClassLoader = new TClassLoader(); // Let's compile the groovy source final List<GroovyClass> groovyClassesForThisTemplate = new ArrayList<GroovyClass>(); // ~~~ Please ! CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); compilerConfiguration.setSourceEncoding("utf-8"); // ouf CompilationUnit compilationUnit = new CompilationUnit(compilerConfiguration); compilationUnit.addSource(new SourceUnit(name, compiledSource, compilerConfiguration, tClassLoader, compilationUnit.getErrorCollector())); Field phasesF = compilationUnit.getClass().getDeclaredField("phaseOperations"); phasesF.setAccessible(true); LinkedList[] phases = (LinkedList[]) phasesF.get(compilationUnit); LinkedList<GroovyClassOperation> output = new LinkedList<GroovyClassOperation>(); phases[Phases.OUTPUT] = output; output.add(new GroovyClassOperation() { public void call(GroovyClass gclass) { groovyClassesForThisTemplate.add(gclass); } }); compilationUnit.compile(); // ouf // Define script classes StringBuilder sb = new StringBuilder(); sb.append("LINESMATRIX" + "\n"); sb.append(Codec.encodeBASE64(Java.serialize(linesMatrix)).replaceAll("\\s", "")); sb.append("\n"); sb.append("DOBODYLINES" + "\n"); sb.append(Codec.encodeBASE64(Java.serialize(doBodyLines)).replaceAll("\\s", "")); sb.append("\n"); for (GroovyClass gclass : groovyClassesForThisTemplate) { tClassLoader.defineTemplate(gclass.getName(), gclass.getBytes()); sb.append(gclass.getName() + "\n"); sb.append(Codec.encodeBASE64(gclass.getBytes()).replaceAll("\\s", "")); sb.append("\n"); } // Cache BytecodeCache.cacheBytecode(sb.toString().getBytes("utf-8"), name, source); compiledTemplate = tClassLoader.loadClass(groovyClassesForThisTemplate.get(0).getName()); if (System.getProperty("precompile") != null) { try { // emit bytecode to standard class layout as well File f = Play.getFile("precompiled/templates/" + name.replaceAll("\\{(.*)\\}", "from_$1").replace(":", "_").replace("..", "parent")); f.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(f); fos.write(sb.toString().getBytes("utf-8")); fos.close(); } catch (Exception e) { e.printStackTrace(); } } Logger.trace("%sms to compile template %s to %d classes", System.currentTimeMillis() - start, name, groovyClassesForThisTemplate.size()); } catch (MultipleCompilationErrorsException e) { if (e.getErrorCollector().getLastError() != null) { SyntaxErrorMessage errorMessage = (SyntaxErrorMessage) e.getErrorCollector().getLastError(); SyntaxException syntaxException = errorMessage.getCause(); Integer line = this.linesMatrix.get(syntaxException.getLine()); if (line == null) { line = 0; } String message = syntaxException.getMessage(); if (message.indexOf("@") > 0) { message = message.substring(0, message.lastIndexOf("@")); } throw new TemplateCompilationException(this, line, message); } throw new UnexpectedException(e); } catch (Exception e) { throw new UnexpectedException(e); } } compiledTemplateName = compiledTemplate.getName(); }
public void visit(ASTNode[] nodes, SourceUnit source) { sourceUnit = source; loader = null; initContextClassLoader = false; ModuleNode mn = (ModuleNode) nodes[0]; allowShortGrab = true; allowShortGrabExcludes = true; allowShortGrabConfig = true; allowShortGrapes = true; allowShortGrabResolver = true; grabAliases = new HashSet<String>(); grabExcludeAliases = new HashSet<String>(); grabConfigAliases = new HashSet<String>(); grapesAliases = new HashSet<String>(); grabResolverAliases = new HashSet<String>(); for (ImportNode im : mn.getImports()) { String alias = im.getAlias(); String className = im.getClassName(); if ((className.endsWith(GRAB_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRAB_CLASS_NAME.equals(alias))) { allowShortGrab = false; } else if (GRAB_CLASS_NAME.equals(className)) { grabAliases.add(im.getAlias()); } if ((className.endsWith(GRAPES_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRAPES_CLASS_NAME.equals(alias))) { allowShortGrapes = false; } else if (GRAPES_CLASS_NAME.equals(className)) { grapesAliases.add(im.getAlias()); } if ((className.endsWith(GRABRESOLVER_DOT_NAME) && ((alias == null) || (alias.length() == 0))) || (GRABRESOLVER_CLASS_NAME.equals(alias))) { allowShortGrabResolver = false; } else if (GRABRESOLVER_CLASS_NAME.equals(className)) { grabResolverAliases.add(im.getAlias()); } } List<Map<String, Object>> grabMaps = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> grabMapsInit = new ArrayList<Map<String, Object>>(); List<Map<String, Object>> grabExcludeMaps = new ArrayList<Map<String, Object>>(); for (ClassNode classNode : sourceUnit.getAST().getClasses()) { grabAnnotations = new ArrayList<AnnotationNode>(); grabExcludeAnnotations = new ArrayList<AnnotationNode>(); grabConfigAnnotations = new ArrayList<AnnotationNode>(); grapesAnnotations = new ArrayList<AnnotationNode>(); grabResolverAnnotations = new ArrayList<AnnotationNode>(); visitClass(classNode); ClassNode grapeClassNode = ClassHelper.make(Grape.class); List<Statement> grabResolverInitializers = new ArrayList<Statement>(); if (!grapesAnnotations.isEmpty()) { for (AnnotationNode node : grapesAnnotations) { Expression init = node.getMember("initClass"); Expression value = node.getMember("value"); if (value instanceof ListExpression) { for (Object o : ((ListExpression) value).getExpressions()) { if (o instanceof ConstantExpression) { extractGrab(init, (ConstantExpression) o); } } } else if (value instanceof ConstantExpression) { extractGrab(init, (ConstantExpression) value); } // don't worry if it's not a ListExpression, or AnnotationConstant, etc. // the rest of GroovyC will flag it as a syntax error later, so we don't // need to raise the error ourselves } } if (!grabResolverAnnotations.isEmpty()) { grabResolverAnnotationLoop: for (AnnotationNode node : grabResolverAnnotations) { Map<String, Object> grabResolverMap = new HashMap<String, Object>(); String sval = getMemberStringValue(node, "value"); if (sval != null && sval.length() > 0) { for (String s : GRABRESOLVER_REQUIRED) { String mval = getMemberStringValue(node, s); if (mval != null && mval.isEmpty()) mval = null; if (mval != null) { addError( "The attribute \"" + s + "\" conflicts with attribute 'value' in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } } grabResolverMap.put("name", sval); grabResolverMap.put("root", sval); } else { for (String s : GRABRESOLVER_REQUIRED) { String mval = getMemberStringValue(node, s); if (mval != null && mval.isEmpty()) mval = null; Expression member = node.getMember(s); if (member == null || mval == null) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } else if (mval == null) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant String in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabResolverAnnotationLoop; } grabResolverMap.put(s, mval); } } // If no scheme is specified for the repository root, // then turn it into a URI relative to that of the source file. String root = (String) grabResolverMap.get("root"); if (root != null && !root.contains(":")) { URI sourceURI = null; // Since we use the data: scheme for StringReaderSources (which are fairly common) // and those are not hierarchical we can't use them for making an absolute URI. if (!(getSourceUnit().getSource() instanceof StringReaderSource)) { // Otherwise let's trust the source to know where it is from. // And actually InputStreamReaderSource doesn't know what to do and so returns null. sourceURI = getSourceUnit().getSource().getURI(); } // If source doesn't know how to get a reference to itself, // then let's use the current working directory, since the repo can be relative to that. if (sourceURI == null) { sourceURI = new File(".").toURI(); } try { URI rootURI = sourceURI.resolve(new URI(root)); grabResolverMap.put("root", rootURI.toString()); } catch (URISyntaxException e) { // We'll be silent here. // If the URI scheme is unknown or not hierarchical, then we just can't help them and // shouldn't cause any trouble either. // addError("Attribute \"root\" has value '" + root + "' which can't be turned into a // valid URI relative to it's source '" + getSourceUnit().getName() + "' @" + // node.getClassNode().getNameWithoutPackage() + " annotations", node); } } Grape.addResolver(grabResolverMap); addGrabResolverAsStaticInitIfNeeded( grapeClassNode, node, grabResolverInitializers, grabResolverMap); } } if (!grabConfigAnnotations.isEmpty()) { for (AnnotationNode node : grabConfigAnnotations) { checkForClassLoader(node); checkForInitContextClassLoader(node); checkForAutoDownload(node); checkForDisableChecksums(node); } addInitContextClassLoaderIfNeeded(classNode); } if (!grabExcludeAnnotations.isEmpty()) { grabExcludeAnnotationLoop: for (AnnotationNode node : grabExcludeAnnotations) { Map<String, Object> grabExcludeMap = new HashMap<String, Object>(); checkForConvenienceForm(node, true); for (String s : GRABEXCLUDE_REQUIRED) { Expression member = node.getMember(s); if (member == null) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabExcludeAnnotationLoop; } else if (member != null && !(member instanceof ConstantExpression)) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabExcludeAnnotationLoop; } grabExcludeMap.put(s, ((ConstantExpression) member).getValue()); } grabExcludeMaps.add(grabExcludeMap); } } if (!grabAnnotations.isEmpty()) { grabAnnotationLoop: for (AnnotationNode node : grabAnnotations) { Map<String, Object> grabMap = new HashMap<String, Object>(); checkForConvenienceForm(node, false); for (String s : GRAB_ALL) { Expression member = node.getMember(s); String mval = getMemberStringValue(node, s); if (mval != null && mval.isEmpty()) member = null; if (member == null && !GRAB_OPTIONAL.contains(s)) { addError( "The missing attribute \"" + s + "\" is required in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabAnnotationLoop; } else if (member != null && !(member instanceof ConstantExpression)) { addError( "Attribute \"" + s + "\" has value " + member.getText() + " but should be an inline constant in @" + node.getClassNode().getNameWithoutPackage() + " annotations", node); continue grabAnnotationLoop; } if (node.getMember(s) != null) { grabMap.put(s, ((ConstantExpression) member).getValue()); } } grabMaps.add(grabMap); if ((node.getMember("initClass") == null) || (node.getMember("initClass") == ConstantExpression.TRUE)) { grabMapsInit.add(grabMap); } } callGrabAsStaticInitIfNeeded(classNode, grapeClassNode, grabMapsInit, grabExcludeMaps); } if (!grabResolverInitializers.isEmpty()) { classNode.addStaticInitializerStatements(grabResolverInitializers, true); } } if (!grabMaps.isEmpty()) { Map<String, Object> basicArgs = new HashMap<String, Object>(); basicArgs.put("classLoader", loader != null ? loader : sourceUnit.getClassLoader()); if (!grabExcludeMaps.isEmpty()) basicArgs.put("excludes", grabExcludeMaps); if (autoDownload != null) basicArgs.put(AUTO_DOWNLOAD_SETTING, autoDownload); if (disableChecksums != null) basicArgs.put(DISABLE_CHECKSUMS_SETTING, disableChecksums); try { Grape.grab(basicArgs, grabMaps.toArray(new Map[grabMaps.size()])); // grab may have added more transformations through new URLs added to classpath, so do one // more scan if (compilationUnit != null) { ASTTransformationVisitor.addGlobalTransformsAfterGrab( compilationUnit.getASTTransformationsContext()); } } catch (RuntimeException re) { // Decided against syntax exception since this is not a syntax error. // The down side is we lose line number information for the offending // @Grab annotation. source.addException(re); } } }
private String getPath(Class clazz) { CompilationUnit cu = getLocalData().get().cu; String name = clazz.getName(); ClassNode classNode = cu.getClassNode(name); return classNode.getModule().getContext().getName(); }
@Override protected CompilationUnit createCompilationUnit( CompilerConfiguration configuration, CodeSource source) { CompilationUnit cu = super.createCompilationUnit(configuration, source); LocalData local = getLocalData().get(); local.cu = cu; final StringSetMap cache = local.dependencyCache; // "." is used to transfer compilation dependencies, which will be // recollected later during compilation for (String depSourcePath : cache.get(".")) { try { cu.addSource(getResourceConnection(depSourcePath).getURL()); } catch (ResourceException e) { /* ignore */ } } // remove all old entries including the "." entry cache.clear(); cu.addPhaseOperation( new CompilationUnit.PrimaryClassNodeOperation() { @Override public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { // GROOVY-4013: If it is an inner class, tracking its dependencies doesn't really // serve any purpose and also interferes with the caching done to track dependencies if (classNode instanceof InnerClassNode) return; DependencyTracker dt = new DependencyTracker(source, cache); dt.visitClass(classNode); } }, Phases.CLASS_GENERATION); cu.setClassNodeResolver( new ClassNodeResolver() { @Override public LookupResult findClassNode(String origName, CompilationUnit compilationUnit) { CompilerConfiguration cc = compilationUnit.getConfiguration(); String name = origName.replace('.', '/'); for (String ext : cc.getScriptExtensions()) { try { String finalName = name + "." + ext; URLConnection conn = rc.getResourceConnection(finalName); URL url = conn.getURL(); String path = url.toExternalForm(); ScriptCacheEntry entry = scriptCache.get(path); Class clazz = null; if (entry != null) clazz = entry.scriptClass; try { if (GroovyScriptEngine.this.isSourceNewer(entry)) { // String encoding = conn.getContentEncoding() != null ? // conn.getContentEncoding() : "UTF-8"; SourceUnit su = compilationUnit.addSource(url); return new LookupResult(su, null); } } finally { forceClose(conn); } if (clazz != null) { ClassNode cn = new ClassNode(clazz); return new LookupResult(null, cn); } } catch (ResourceException re) { // skip } } return super.findClassNode(origName, compilationUnit); } }); final List<CompilationCustomizer> customizers = config.getCompilationCustomizers(); if (customizers != null) { // GROOVY-4813 : apply configuration customizers for (CompilationCustomizer customizer : customizers) { cu.addPhaseOperation(customizer, customizer.getPhase().getPhaseNumber()); } } return cu; }