1 4 5 package org.objectweb.fractal.jar; 6 7 import java.io.FileInputStream ; 8 import java.io.FileOutputStream ; 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.io.OutputStream ; 12 import java.util.HashSet ; 13 import java.util.Iterator ; 14 import java.util.Map ; 15 import java.util.Set ; 16 import java.util.zip.ZipEntry ; 17 import java.util.zip.ZipOutputStream ; 18 19 import org.objectweb.asm.Attribute; 20 import org.objectweb.asm.ClassReader; 21 import org.objectweb.asm.ClassVisitor; 22 import org.objectweb.asm.CodeVisitor; 23 import org.objectweb.asm.Label; 24 import org.objectweb.asm.Type; 25 26 import org.objectweb.fractal.adl.ADLException; 27 import org.objectweb.fractal.adl.Definition; 28 import org.objectweb.fractal.adl.Loader; 29 import org.objectweb.fractal.adl.Node; 30 import org.objectweb.fractal.adl.Parser; 31 import org.objectweb.fractal.adl.ParserException; 32 import org.objectweb.fractal.adl.components.Component; 33 import org.objectweb.fractal.adl.components.ComponentContainer; 34 import org.objectweb.fractal.adl.components.ComponentDefinition; 35 import org.objectweb.fractal.adl.xml.XMLParser; 36 37 import org.objectweb.fractal.jar.adl.File; 38 import org.objectweb.fractal.jar.adl.FileContainer; 39 import org.objectweb.fractal.jar.adl.FileLoader; 40 import org.objectweb.fractal.jar.adl.VersionDefinition; 41 42 public class CreatePackage { 43 44 String src; 45 46 String dst; 47 48 String definition; 49 50 boolean recursive; 51 52 Set excludes; 53 54 Set content; 55 56 Set classes; 57 58 Set dependencies; 59 60 Set libraryDependencies; 61 62 Loader loader; 63 64 public CreatePackage ( 65 String src, 66 String dst, 67 String definition, 68 boolean recursive, 69 Set excludes) 70 { 71 this.src = src; 72 this.dst = dst; 73 this.definition = definition; 74 this.recursive = recursive; 75 this.excludes = excludes; 76 this.content = new HashSet (); 77 this.classes = new HashSet (); 78 this.dependencies = new HashSet (); 79 this.libraryDependencies = new HashSet (); 80 } 81 82 public void create () throws Exception { 83 FileLoader fl = new FileLoader(); 84 fl.clientLoader = new XMLLoader(); 85 loader = fl; 86 87 Definition d = loader.load(definition, null); 88 String version = ((VersionDefinition)d).getVersion(); 89 90 String f = definition + "-" + version + ".far"; 91 OutputStream os = new FileOutputStream (new java.io.File (dst, f)); 92 ZipOutputStream zos = new ZipOutputStream (os); 93 94 zos.putNextEntry(new ZipEntry ("META-INF/MANIFEST.MF")); 95 zos.write("Manifest-Version: 1.0\n".getBytes()); 96 zos.write(("Component-Name: " + definition + "-" + version + "\n").getBytes()); 97 zos.closeEntry(); 98 99 addFile(definition.replace('.', '/') + ".fractal", version, zos, true); 100 addFiles((Node)d, version, zos, true); 101 102 zos.close(); 103 104 dependencies.removeAll(classes); 105 if (dependencies.size() > 0) { 106 Iterator i = dependencies.iterator(); 107 System.out.println( 108 "WARNING: the following classes are needed by the classes " + 109 "listed in the ADL files, but they are not listed in the ADL files"); 110 while (i.hasNext()) { 111 System.out.println(" " + i.next()); 112 } 113 } 114 } 115 116 private void addFiles (Node n, String version, ZipOutputStream z, boolean add) throws Exception { 117 if (n instanceof FileContainer) { 118 File[] files = ((FileContainer)n).getFiles(); 119 for (int i = 0; i < files.length; ++i) { 120 try { 121 addFile(files[i].getName(), version, z, add); 122 } catch (Exception e) { 123 throw new ADLException("Cannot add file", (Node)files[i], e); 124 } 125 } 126 } 127 if (n instanceof ComponentContainer) { 128 Component[] components = ((ComponentContainer)n).getComponents(); 129 for (int i = 0; i < components.length; ++i) { 130 addFiles((Node)components[i], version, z, add); 131 } 132 } 133 134 if (n instanceof ComponentDefinition) { 135 try { 136 addDefinitions(((ComponentDefinition)n).getExtends(), z, recursive); 137 } catch (Exception e) { 138 throw new ADLException("Cannot read or add inherited files", n, e); 139 } 140 } 141 if (n instanceof Component) { 142 try { 143 addDefinitions(((Component)n).getDefinition(), z, recursive); 144 } catch (Exception e) { 145 throw new ADLException("Cannot read or add referenced files", n, e); 146 } 147 } 148 } 149 150 private void addFile (String f, String version, ZipOutputStream z, boolean add) throws Exception { 151 if (add) { 152 String entry = version + '/' + f; 153 if (content.contains(entry)) { 154 return; 155 } else { 156 content.add(entry); 157 } 158 InputStream is = new FileInputStream (new java.io.File (src, f)); 159 z.putNextEntry(new ZipEntry (entry)); 160 161 byte[] b = new byte[Math.min(100000, is.available())]; 162 while (true) { 163 int n = is.read(b, 0, b.length); 164 if (n == -1) { 165 break; 166 } else { 167 z.write(b, 0, n); 168 } 169 } 170 171 z.closeEntry(); 172 } 173 174 if (f.endsWith(".class")) { 175 classes.add(f); 176 InputStream is = new FileInputStream (new java.io.File (src, f)); 177 new ClassReader(is).accept(new DependencyClassVisitor(), true); 178 } 179 } 180 181 private void addDefinitions (String definitions, ZipOutputStream z, boolean add) 182 throws Exception 183 { 184 if (definitions == null) { 185 return; 186 } 187 int comma = definitions.indexOf(','); 188 if (comma != -1) { 189 addDefinitions(definitions.substring(0, comma), z, add); 190 addDefinitions(definitions.substring(comma + 1), z, add); 191 return; 192 } 193 int dash = definitions.indexOf('-'); 194 String definition = definitions.substring(0, dash); 195 String version = definitions.substring(dash + 1); 196 197 if (!excludes.contains(definition)) { 198 Definition d = loader.load(definition, null); 199 if (!((VersionDefinition)d).getVersion().equals(version)) { 200 throw new Exception ("The declared version does not match the requested version"); 201 } 202 addFile(definition.replace('.', '/') + ".fractal", version, z, add); 203 addFiles((Node)d, version, z, add); 204 } 205 } 206 207 209 class XMLLoader implements Loader { 210 211 private Parser parser = new XMLParser(true); 212 213 public Definition load (final String name, final Map context) 214 throws ADLException 215 { 216 try { 217 String file = name.replace('.', '/') + ".fractal"; 218 InputStream is; 219 try { 220 is = new FileInputStream (new java.io.File (src, file)); 221 } catch (IOException e) { 222 throw new ADLException( 223 "Cannot find file " + src + '/' + file, null, e); 224 } 225 Definition d = (Definition)parser.parse(is, file); 226 if (d.getName() == null) { 227 throw new ADLException("Definition name missing", (Node)d); 228 } 229 if (!d.getName().equals(name)) { 230 throw new ADLException( 231 "Wrong definition name ('" + name + 232 "' expected, instead of '" + d.getName() + "')", (Node)d); 233 } 234 return d; 235 } catch (ParserException e) { 236 throw new ADLException("Cannot load '" + name + "'", null, e); 237 } 238 } 239 } 240 241 243 void addClassDependency (String s) { 244 if (s.startsWith("java") || s.startsWith("org/objectweb/fractal/api")) { 245 libraryDependencies.add(s + ".class"); 246 } else { 247 dependencies.add(s + ".class"); 248 } 249 } 250 251 void addTypeDependency (Type type) { 252 if (type.getSort() == Type.ARRAY) { 253 addTypeDependency(type.getElementType()); 254 } else if (type.getSort() == Type.OBJECT) { 255 addClassDependency(type.getClassName().replace('.', '/')); 256 } 257 } 258 259 void addTypeDependency (Type[] types) { 260 for (int i = 0; i < types.length; ++i) { 261 addTypeDependency(types[i]); 262 } 263 } 264 265 class DependencyClassVisitor implements ClassVisitor, CodeVisitor { 266 267 public void visit ( 268 final int version, 269 final int access, 270 final String name, 271 final String superName, 272 final String [] interfaces, 273 final String sourceFile) 274 { 275 addClassDependency(superName); 276 if (interfaces != null) { 277 for (int i = 0; i < interfaces.length; ++i) { 278 addClassDependency(interfaces[i]); 279 } 280 } 281 } 282 283 public void visitInnerClass ( 284 final String name, 285 final String outerName, 286 final String innerName, 287 final int access) 288 { 289 } 290 291 public void visitField ( 292 final int access, 293 final String name, 294 final String desc, 295 final Object value, 296 final Attribute attrs) 297 { 298 addTypeDependency(Type.getType(desc)); 299 } 300 301 public CodeVisitor visitMethod ( 302 final int access, 303 final String name, 304 final String desc, 305 final String [] exceptions, 306 final Attribute attrs) 307 { 308 addTypeDependency(Type.getArgumentTypes(desc)); 309 addTypeDependency(Type.getReturnType(desc)); 310 if (exceptions != null) { 311 for (int i = 0; i < exceptions.length; ++i) { 312 addClassDependency(exceptions[i]); 313 } 314 } 315 return this; 316 } 317 318 public void visitAttribute (final Attribute attr) { 319 } 320 321 public void visitEnd () { 322 } 323 324 public void visitInsn (final int opcode) { 325 } 326 327 public void visitIntInsn (final int opcode, final int operand) { 328 } 329 330 public void visitVarInsn (final int opcode, final int var) { 331 } 332 333 public void visitTypeInsn (final int opcode, final String desc) { 334 if (desc.charAt(0) == '[') { 335 addTypeDependency(Type.getType(desc)); 336 } else { 337 addClassDependency(desc); 338 } 339 } 340 341 public void visitFieldInsn ( 342 final int opcode, 343 final String owner, 344 final String name, 345 final String desc) 346 { 347 addClassDependency(owner); 348 addTypeDependency(Type.getType(desc)); 349 } 350 351 public void visitMethodInsn ( 352 final int opcode, 353 final String owner, 354 final String name, 355 final String desc) 356 { 357 addClassDependency(owner); 358 addTypeDependency(Type.getArgumentTypes(desc)); 359 addTypeDependency(Type.getReturnType(desc)); 360 } 361 362 public void visitJumpInsn (final int opcode, final Label label) { 363 } 364 365 public void visitLabel (final Label label) { 366 } 367 368 public void visitLdcInsn (final Object cst) { 369 } 370 371 public void visitIincInsn (final int var, final int increment) { 372 } 373 374 public void visitTableSwitchInsn ( 375 final int min, 376 final int max, 377 final Label dflt, 378 final Label[] labels) 379 { 380 } 381 382 public void visitLookupSwitchInsn ( 383 final Label dflt, 384 final int[] keys, 385 final Label[] labels) 386 { 387 } 388 389 public void visitMultiANewArrayInsn (final String desc, final int dims) { 390 addTypeDependency(Type.getType(desc)); 391 } 392 393 public void visitTryCatchBlock ( 394 final Label start, 395 final Label end, 396 final Label handler, 397 final String type) 398 { 399 addClassDependency(type); 400 } 401 402 public void visitMaxs (final int maxStack, final int maxLocals) { 403 } 404 405 public void visitLocalVariable ( 406 final String name, 407 final String desc, 408 final Label start, 409 final Label end, 410 final int index) 411 { 412 } 413 414 public void visitLineNumber (final int line, final Label start) { 415 } 416 } 417 418 420 public static void main (String [] args) throws Exception { 421 if (args.length < 3) { 422 printUsage(); 423 } 424 boolean recursive = false; 425 Set excludes = new HashSet (); 426 for (int i = 3; i < args.length; ++i) { 427 if (args[i].equals("-r")) { 428 recursive = true; 429 } else if (args[i].equals("-e")) { 430 if (i < args.length - 1) { 431 excludes.add(args[++i]); 432 } else { 433 printUsage(); 434 } 435 } else { 436 printUsage(); 437 } 438 } 439 new CreatePackage(args[0], args[1], args[2], recursive, excludes).create(); 440 } 441 442 private static void printUsage () { 443 System.err.println("Usage: <src> <dst> <definition> [-r] [-e xxx]*"); 444 System.exit(0); 445 } 446 } 447 | Popular Tags |