1 /* 2 * Copyright 2004-2005 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.codehaus.groovy.grails.plugins; 17 18 import grails.util.GrailsNameUtils; 19 import groovy.lang.GroovyClassLoader; 20 21 import java.io.IOException; 22 import java.util.ArrayList; 23 import java.util.LinkedHashMap; 24 import java.util.List; 25 import java.util.Map; 26 27 import org.codehaus.groovy.ast.ClassCodeVisitorSupport; 28 import org.codehaus.groovy.ast.ClassNode; 29 import org.codehaus.groovy.ast.PropertyNode; 30 import org.codehaus.groovy.ast.expr.Expression; 31 import org.codehaus.groovy.ast.expr.ListExpression; 32 import org.codehaus.groovy.ast.expr.MapEntryExpression; 33 import org.codehaus.groovy.ast.expr.MapExpression; 34 import org.codehaus.groovy.classgen.GeneratorContext; 35 import org.codehaus.groovy.control.CompilationFailedException; 36 import org.codehaus.groovy.control.CompilationUnit; 37 import org.codehaus.groovy.control.Phases; 38 import org.codehaus.groovy.control.SourceUnit; 39 import org.codehaus.groovy.grails.plugins.exceptions.PluginException; 40 import org.springframework.beans.BeanWrapper; 41 import org.springframework.beans.BeanWrapperImpl; 42 import org.springframework.core.io.Resource; 43 44 /** 45 * Used to read plugin information from the AST. 46 * 47 * @author Graeme Rocher 48 * @since 1.3 49 */ 50 public class AstPluginDescriptorReader implements PluginDescriptorReader { 51 52 private GroovyClassLoader classLoader; 53 AstPluginDescriptorReader()54 public AstPluginDescriptorReader() { 55 this(new GroovyClassLoader(Thread.currentThread().getContextClassLoader())); 56 } 57 AstPluginDescriptorReader(GroovyClassLoader cl)58 public AstPluginDescriptorReader(GroovyClassLoader cl) { 59 classLoader = cl; 60 } 61 readPluginInfo(Resource pluginLocation)62 public GrailsPluginInfo readPluginInfo(Resource pluginLocation) { 63 CompilationUnit compilationUnit = new CompilationUnit(classLoader); 64 BasicGrailsPluginInfo pluginInfo = new BasicGrailsPluginInfo(pluginLocation); 65 66 try { 67 compilationUnit.addSource("dummy",pluginLocation.getInputStream()); 68 compilationUnit.addPhaseOperation(new PluginReadingPhaseOperation(pluginInfo), Phases.CONVERSION); 69 compilationUnit.compile(Phases.CONVERSION); 70 return pluginInfo; 71 } 72 catch (IOException e) { 73 throw new PluginException("Cannot read plugin info: " + e.getMessage()); 74 } 75 } 76 77 class PluginReadingPhaseOperation extends CompilationUnit.PrimaryClassNodeOperation { 78 private BasicGrailsPluginInfo pluginInfo; 79 private BeanWrapper wrapper; PluginReadingPhaseOperation(BasicGrailsPluginInfo pluginInfo)80 public PluginReadingPhaseOperation(BasicGrailsPluginInfo pluginInfo) { 81 this.pluginInfo = pluginInfo; 82 wrapper = new BeanWrapperImpl(pluginInfo); 83 } 84 85 @Override call(final SourceUnit source, GeneratorContext context, ClassNode classNode)86 public void call(final SourceUnit source, GeneratorContext context, 87 ClassNode classNode) throws CompilationFailedException { 88 89 ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() { 90 91 @Override 92 public void visitProperty(PropertyNode node) { 93 String name = node.getName(); 94 final Expression expr = node.getField().getInitialExpression(); 95 Object value; 96 if (expr instanceof ListExpression) { 97 final List<String> list = new ArrayList<String>(); 98 value = list; 99 for (Expression i : ((ListExpression)expr).getExpressions()) { 100 list.add(i.getText()); 101 } 102 } 103 else if (expr instanceof MapExpression) { 104 final Map<String, String> map = new LinkedHashMap<String, String>(); 105 value = map; 106 for (MapEntryExpression mee : ((MapExpression)expr).getMapEntryExpressions()) { 107 map.put(mee.getKeyExpression().getText(), mee.getValueExpression().getText()); 108 } 109 } 110 else { 111 value = expr.getText(); 112 } 113 114 if (wrapper.isWritableProperty(name)) { 115 wrapper.setPropertyValue(name, value); 116 } 117 else { 118 pluginInfo.setProperty(name, value); 119 } 120 super.visitProperty(node); 121 } 122 123 @Override 124 protected SourceUnit getSourceUnit() { 125 return source; 126 } 127 }; 128 129 classNode.visitContents(visitor); 130 String className = classNode.getNameWithoutPackage(); 131 132 wrapper.setPropertyValue("name", GrailsNameUtils.getPluginName(className + ".groovy")); 133 } 134 } 135 } 136