1 46 package org.codehaus.groovy.ast; 47 48 import groovy.lang.Script; 49 import groovy.lang.Binding; 50 51 import java.io.File ; 52 import java.util.ArrayList ; 53 import java.util.HashMap ; 54 import java.util.Iterator ; 55 import java.util.List ; 56 import java.util.Map ; 57 58 import org.codehaus.groovy.ast.expr.ArgumentListExpression; 59 import org.codehaus.groovy.ast.expr.ClassExpression; 60 import org.codehaus.groovy.ast.expr.Expression; 61 import org.codehaus.groovy.ast.expr.MethodCallExpression; 62 import org.codehaus.groovy.ast.expr.VariableExpression; 63 import org.codehaus.groovy.ast.stmt.BlockStatement; 64 import org.codehaus.groovy.ast.stmt.ExpressionStatement; 65 import org.codehaus.groovy.ast.stmt.Statement; 66 import org.codehaus.groovy.control.SourceUnit; 67 import org.codehaus.groovy.runtime.InvokerHelper; 68 import org.objectweb.asm.Constants; 69 70 78 public class ModuleNode extends ASTNode implements Constants { 79 80 private BlockStatement statementBlock = new BlockStatement(); 81 List classes = new ArrayList (); 82 private List methods = new ArrayList (); 83 private List imports = new ArrayList (); 84 private List importPackages = new ArrayList (); 85 private Map importIndex = new HashMap (); 86 private CompileUnit unit; 87 private String packageName; 88 private String description; 89 private boolean createClassForStatements = true; 90 private SourceUnit context; 91 92 93 public ModuleNode( SourceUnit context ) { 94 this.context = context; 95 } 96 97 public ModuleNode(CompileUnit unit) { 98 this.unit = unit; 99 } 100 101 public BlockStatement getStatementBlock() { 102 return statementBlock; 103 } 104 105 public List getMethods() { 106 return methods; 107 } 108 109 public List getClasses() { 110 if (createClassForStatements && (!statementBlock.isEmpty() || !methods.isEmpty())) { 111 ClassNode mainClass = createStatementsClass(); 112 createClassForStatements = false; 113 classes.add(0, mainClass); 114 mainClass.setModule(this); 115 addToCompileUnit(mainClass); 116 } 117 return classes; 118 } 119 120 public List getImports() { 121 return imports; 122 } 123 124 public List getImportPackages() { 125 return importPackages; 126 } 127 128 131 public String getImport(String alias) { 132 return (String ) importIndex.get(alias); 133 } 134 135 public void addImport(String alias, String className) { 136 imports.add(new ImportNode(className, alias)); 137 importIndex.put(alias, className); 138 } 139 140 public String [] addImportPackage(String packageName) { 141 importPackages.add(packageName); 142 return new String [] { }; 143 } 144 145 public void addStatement(Statement node) { 146 statementBlock.addStatement(node); 147 } 148 149 public void addClass(ClassNode node) { 150 classes.add(node); 151 node.setModule(this); 152 addToCompileUnit(node); 153 } 154 155 158 private void addToCompileUnit(ClassNode node) { 159 if (unit != null) { 161 unit.addClass(node); 162 } 163 } 164 165 public void addMethod(MethodNode node) { 166 methods.add(node); 167 } 168 169 public void visit(GroovyCodeVisitor visitor) { 170 } 171 172 public String getPackageName() { 173 return packageName; 174 } 175 176 public void setPackageName(String packageName) { 177 this.packageName = packageName; 178 } 179 180 public SourceUnit getContext() { 181 return context; 182 } 183 184 187 public String getDescription() { 188 if( context != null ) 189 { 190 return context.getName(); 191 } 192 else 193 { 194 return this.description; 195 } 196 } 197 198 public void setDescription(String description) { 199 this.description = description; 201 } 202 203 public CompileUnit getUnit() { 204 return unit; 205 } 206 207 void setUnit(CompileUnit unit) { 208 this.unit = unit; 209 } 210 211 protected ClassNode createStatementsClass() { 212 String name = getPackageName(); 213 if (name == null) { 214 name = ""; 215 } 216 else { 217 name = name + "."; 218 } 219 if (getDescription() == null) { 221 throw new RuntimeException ("Cannot generate main(String[]) class for statements when we have no file description"); 222 } 223 name += extractClassFromFileDescription(); 224 225 String baseClass = null; 226 if (unit != null) { 227 baseClass = unit.getConfig().getScriptBaseClass(); 228 } 229 if (baseClass == null) { 230 baseClass = Script.class.getName(); 231 } 232 ClassNode classNode = new ClassNode(name, ACC_PUBLIC, baseClass); 233 classNode.setScript(true); 234 235 classNode.addMethod( 237 new MethodNode( 238 "main", 239 ACC_PUBLIC | ACC_STATIC, 240 "void", 241 new Parameter[] { new Parameter("java.lang.String[]", "args")}, 242 new ExpressionStatement( 243 new MethodCallExpression( 244 new ClassExpression(InvokerHelper.class.getName()), 245 "runScript", 246 new ArgumentListExpression( 247 new Expression[] { 248 new ClassExpression(classNode.getName()), 249 new VariableExpression("args")}))))); 250 251 classNode.addMethod( 252 new MethodNode("run", ACC_PUBLIC, Object .class.getName(), Parameter.EMPTY_ARRAY, statementBlock)); 253 254 classNode.addConstructor(ACC_PUBLIC, Parameter.EMPTY_ARRAY, new BlockStatement()); 255 Statement stmt = new ExpressionStatement( 256 new MethodCallExpression( 257 new VariableExpression("super"), 258 "setBinding", 259 new ArgumentListExpression( 260 new Expression[] { 261 new VariableExpression("context")}))); 262 263 classNode.addConstructor( 264 ACC_PUBLIC, 265 new Parameter[] { new Parameter(Binding.class.getName(), "context")}, 266 stmt); 267 268 for (Iterator iter = methods.iterator(); iter.hasNext();) { 269 MethodNode node = (MethodNode) iter.next(); 270 int modifiers = node.getModifiers(); 271 if ((modifiers & ACC_ABSTRACT) != 0) { 272 throw new RuntimeException ( 273 "Cannot use abstract methods in a script, they are only available inside classes. Method: " 274 + node.getName()); 275 } 276 node.setModifiers(modifiers ); 279 280 classNode.addMethod(node); 281 } 282 return classNode; 283 } 284 285 protected String extractClassFromFileDescription() { 286 String answer = getDescription(); 288 int idx = answer.lastIndexOf('.'); 289 if (idx > 0) { 290 answer = answer.substring(0, idx); 291 } 292 idx = answer.lastIndexOf('/'); 294 if (idx >= 0) { 295 answer = answer.substring(idx + 1); 296 } 297 idx = answer.lastIndexOf(File.separatorChar); 298 if (idx >= 0) { 299 answer = answer.substring(idx + 1); 300 } 301 return answer; 302 } 303 304 public boolean isEmpty() { 305 return classes.isEmpty() && statementBlock.getStatements().isEmpty(); 306 } 307 308 } 309 | Popular Tags |