[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Tue Mar 30 19:14:05 UTC 2010


gordonp
Tue Mar 30 15:14:04 EDT 2010
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow
In directory dev.open-bio.org:/tmp/cvs-serv18574/src/main/ca/ucalgary/minnow

Modified Files:
	MinJarMaker.java 
Log Message:
Changes to allow secondary JAR dumping  from JARs in the classpath, before worked only for class files
moby-live/Java/src/main/ca/ucalgary/minnow MinJarMaker.java,1.5,1.6
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java	2008/10/30 02:33:24	1.5
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java	2010/03/30 19:14:04	1.6
@@ -299,73 +299,84 @@
 	    String path = pathElement + File.separator + pathSuffix;
 	    File classFile = new File(path);
 	    if(classFile.isFile()){
-		long len = classFile.length();
-		byte data[] = new byte[(int)len];
-		FileInputStream fin = new FileInputStream(classFile);
-		int r = fin.read(data);
-		if (r != len){
-		    throw new IOException( "Could only read "+r+" of "+len+" bytes from "+classFile );
-		}
-		fin.close();
-                if(Boolean.getBoolean(VERBOSE)){
-                  System.err.println("[Loaded " + name + " from " + classFile.getCanonicalPath() + "]");
-                }
-		return data;
+		return getClassBytesFromFile(classFile, name);
 	    }
 	    else{
 		// If it's not a file, maybe it's in a JAR
 		File f = new File(pathElement);
 		if(f.isFile()){
-		    JarFile jarFile = null;
-		    try{
-			jarFile = new JarFile(f);
+		    byte[] bytes = getClassBytesFromJar(f, pathSuffix);
+		    if(bytes != null){
+			return bytes;
 		    }
-		    catch(Exception e){
-			System.err.println("Class path element " + pathElement + 
-					   " was not a directory, or a valid JAR file");
-			continue;
-		    }
-
-		    JarEntry je = jarFile.getJarEntry(pathSuffix);
-		    if(je == null){
-			continue;
-		    }
-		    long classSize = je.getSize();
-
-		    InputStream classStream = jarFile.getInputStream(je);
-		    byte[] classBytes = null;
-		    // NOTE: This if case is commented out because false file sizes are sometimes
-		    // reported, which leads to invalid class definitions
-// 		    if(classSize != -1){ // We know the size of the class already
-
-// 			classBytes = new byte[(int) classSize]; //classes better not be bigger than 2 GB!
-// 			// Slurp it up in one shot
-// 			classStream.read(classBytes, 0, (int) classSize); 
-//                         if(Boolean.getBoolean(VERBOSE)){
-//                           System.err.println("[Loaded " + name + " from " + f.getCanonicalPath() + "]");
-//                         }
-// 			return classBytes;
-// 		    }
-// 		    else{
-
-			byte[] byteBufferChunk = new byte[1024];
-			ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
-			for(int r = classStream.read(byteBufferChunk, 0, 1024);
-			    r != -1; 
-			    r = classStream.read(byteBufferChunk, 0, 1024)){
-			    byteBuffer.write(byteBufferChunk, 0, r);
-			}
-                        if(Boolean.getBoolean(VERBOSE)){
-                          System.err.println("[Loaded " + name + " from " + f.getCanonicalPath() + "]");
-                        }
-			return byteBuffer.toByteArray();
-// 		    }
 		}
-		
 	    }
 	}
+	return null;
+    }
+
+    protected byte[] getClassBytesFromFile(File classFile, String name) throws IOException{
+	long len = classFile.length();
+	byte[] data = new byte[(int)len];  // 2G limit
+	FileInputStream fin = new FileInputStream(classFile);
+	int r = fin.read(data);
+	if (r != len){
+	    throw new IOException( "Could only read "+r+" of "+len+" bytes from "+classFile );
+	}
+	fin.close();
+	if(Boolean.getBoolean(VERBOSE)){
+	    System.err.println("[Loaded " + name + " from " + classFile.getCanonicalPath() + "]");
+	}
+	return data;
+    }
+    
+    protected byte[] getClassBytesFromJar(File f, String entryName) throws IOException{
+	try{
+	    return getClassBytesFromJar(new JarFile(f), entryName);
+	}
+	catch(Exception e){
+	    System.err.println("Class path element " + f.getCanonicalPath() + 
+			       " was not a directory, or a valid JAR file");
+	    return null;
+	}
+    }
+
+    protected byte[] getClassBytesFromJar(JarFile jarFile, String entryName) throws IOException{
+	JarEntry je = jarFile.getJarEntry(entryName);
+	if(je == null){
+	    return null;
+	}
+	long classSize = je.getSize();
+
+	InputStream classStream = jarFile.getInputStream(je);
+	byte[] classBytes = null;
+	// NOTE: This if case is commented out because false file sizes are sometimes
+	// reported, which leads to invalid class definitions
+	// This has to do with different versions of compression algorithms being used by different JAR makers.
+	//
+	// 		    if(classSize != -1){ // We know the size of the class already
 	
-	return null; 
+	// 			classBytes = new byte[(int) classSize]; //classes better not be bigger than 2 GB!
+	// 			// Slurp it up in one shot
+	// 			classStream.read(classBytes, 0, (int) classSize); 
+	//                         if(Boolean.getBoolean(VERBOSE)){
+	//                           System.err.println("[Loaded " + name + " from " + f.getCanonicalPath() + "]");
+	//                         }
+	// 			return classBytes;
+	// 		    }
+	// 		    else{
+
+	byte[] byteBufferChunk = new byte[1024];
+	ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
+	for(int r = classStream.read(byteBufferChunk, 0, 1024);
+	    r != -1; 
+	    r = classStream.read(byteBufferChunk, 0, 1024)){
+	    byteBuffer.write(byteBufferChunk, 0, r);
+	}
+	if(Boolean.getBoolean(VERBOSE)){
+	    System.err.println("[Loaded " + entryName + " from " + jarFile.getName() + "]");
+	}
+	return byteBuffer.toByteArray();
     }
     
     protected URL getResourceURL(String name){
@@ -696,6 +707,7 @@
                   }
                 }
                 // Only get to here if the save was successful
+		//System.err.println("Saved "+relativePath);
                 savedClasses.put(relativePath, "saved");
 	    }
 	    jout.close();
@@ -718,6 +730,7 @@
 	    StringTokenizer classPathTokens = new StringTokenizer(System.getProperty("jarmaker.class.path"), File.pathSeparator);
 	    while(classPathTokens.hasMoreElements()){
 		String classPathElement = classPathTokens.nextToken();
+		System.err.println("Dumping secondary JAR for "+classPathElement);
 		try{
 		    dumpSecondaryJar(new File(classPathElement), classPathElement, (new File(jarfile)).getParent());
 		}
@@ -744,10 +757,13 @@
      * already benn included in the main dumpJar call.
      */
     private void dumpSecondaryJar(File classPath, String classPrefix, String jarFilePrefix) throws Exception{
-	if(classPath.isDirectory()){
-	    JarOutputStream jarFile = null;
-	    String packageName = null;
-	    if(classPrefix.equals(classPath.toString())){
+	boolean isDir = classPath.isDirectory();
+	JarOutputStream jarFile = null;
+	String packageName = null;
+	List entries = new Vector(); // files or jar entries
+	JarFile srcJarFile = null;
+	if(isDir){
+	    if(classPrefix.equals(classPath.toString()) || (classPrefix+File.separator).equals(classPath.toString())){
 		packageName = "no-package";
 	    }
 	    else{
@@ -755,112 +771,155 @@
 	    }
 	    File[] contents = classPath.listFiles();
 	    for(int i = 0; i < contents.length; i++){
-		String relativePath = contents[i].toString().substring(classPrefix.length()+1);
-		if(savedClasses.containsKey(relativePath) || // already saved
-		   contents[i].getName().startsWith(".") ||  // or not interesting
-		   contents[i].getName().startsWith("TEST-") ||  // JUnit output files
-		   contents[i].getName().endsWith("~") ||    //emacs scratch file
-		   contents[i].getName().endsWith(".java") || 
-		   contents[i].getName().endsWith(".jar") || 
-		   contents[i].getName().equals("META-INF") || //this one causes null pointers in jarsigner 
-		   contents[i].getName().equals("testdata") || 
-		   contents[i].getName().equals("deployment") || 
-		   contents[i].getName().equals("CVS")){
-		    continue;
-		}
-		else if(contents[i].isDirectory()){
-		    dumpSecondaryJar(contents[i], classPrefix, jarFilePrefix);
-		    continue;
-		}
-		else if(jarFile == null){ // Need to create the jar file
-		    String jarFileName = jarFilePrefix + File.separator;  //in same dir as main jar file dump
-		    jarFileName += packageName;
-		    jarFileName += ".jar";
-		    File destinationFile = new File(jarFileName);
-		    if(destinationFile.exists()){
-			System.err.println("Updating jar file " + jarFileName);
-
-			// Byte-for-byte copy the existing JAR to a temp file
-			File tmpJarFile = File.createTempFile("MinJarMaker", ".jar");
-			InputStream origInStream = new FileInputStream(destinationFile);
-			OutputStream tmpOutStream = new FileOutputStream(tmpJarFile);
-			copyFile(tmpOutStream, origInStream);
-			tmpOutStream.close();
-			origInStream.close();
-
-			// Then start writing the data out to the destination file, to be appended to later on too
-			JarInputStream existingJar = new JarInputStream(new FileInputStream(tmpJarFile));
-			jarFile = new JarOutputStream(new FileOutputStream( destinationFile ));
-			jarFile.setLevel(9); //best compression
-			for(JarEntry je = existingJar.getNextJarEntry(); je != null; je = existingJar.getNextJarEntry()){
-			    try{
-				jarFile.putNextEntry( je );
-			    }catch(java.util.zip.ZipException ze){
-				System.err.println("Skipping existing entry " + je);
-				continue;
-			    }
-			    /*jar i/o works on a per entry basis, so copy File copies one entry*/
-			    copyFile(jarFile, existingJar);  
-			    jarFile.closeEntry();
+		//System.err.println("Adding "+contents[i]);
+		entries.add(contents[i]);
+	    }
+	}
+	else{  // Get the classes from another JAR
+	    //System.err.println(classPath+" is a JAR");
+	    packageName = classPath.getName().replaceFirst(".jar$","");  // JAR file name without path or suffix
+	    JarInputStream srcJarStream = null;
+	    try{	      
+		srcJarFile = new JarFile(classPath);
+		srcJarStream = new JarInputStream(new FileInputStream(classPath));
+	    } catch(Exception e){
+		System.err.println("Skipping class path element that is neither a directory " +
+				   "nor a valid JAR file " + e);
+		return;
+	    }
+	    try{
+		for(JarEntry je = srcJarStream.getNextJarEntry(); je != null; je = srcJarStream.getNextJarEntry()){
+		    entries.add(je);
+		}
+	    } catch(Exception e){
+		System.err.println("Error while reading from JAR file "+classPath);
+		e.printStackTrace();
+		return;
+	    }
+	}
+
+	for(Object entry: entries){	    
+	    String relativePath = entry instanceof JarEntry ? ((JarEntry) entry).getName() : 
+		entry.toString().substring(classPrefix.length()+1);
+	    //System.err.println("Checking status of "+relativePath);
+
+	    if(savedClasses.containsKey(relativePath) || // already saved
+	       relativePath.startsWith(".") ||  // or not interesting
+	       relativePath.startsWith("TEST-") ||  // JUnit output files
+	       relativePath.endsWith("~") ||    //emacs scratch file
+	       relativePath.endsWith(".java") || 
+	       relativePath.endsWith(".jar") || 
+	       relativePath.equals("META-INF") || //this one causes null pointers in jarsigner 
+	       relativePath.equals("testdata") || 
+	       relativePath.equals("deployment") || 
+	       relativePath.equals("CVS")){
+		//System.err.println("Skipping " + relativePath);
+		continue;
+	    }
+	    else if(entry instanceof File && ((File) entry).isDirectory()){ //recurse for subdirs
+		//System.err.println("Recursing for " + relativePath);
+		dumpSecondaryJar((File) entry, classPrefix, jarFilePrefix);		
+		continue;
+	    }
+	    else if(jarFile == null){ // Need to create the jar file
+		String jarFileName = jarFilePrefix + File.separator;  //in same dir as main jar file dump
+		jarFileName += packageName;
+		jarFileName += ".jar";
+		File destinationFile = new File(jarFileName);
+		if(destinationFile.exists()){
+		    //System.err.println("Updating jar file " + jarFileName);
+		    
+		    // Byte-for-byte copy the existing JAR to a temp file
+		    File tmpJarFile = File.createTempFile("MinJarMaker", ".jar");
+		    InputStream origInStream = new FileInputStream(destinationFile);
+		    OutputStream tmpOutStream = new FileOutputStream(tmpJarFile);
+		    copyFile(tmpOutStream, origInStream);
+		    tmpOutStream.close();
+		    origInStream.close();
+		    
+		    // Then start writing the data out to the destination file, to be appended to later on too
+		    JarInputStream existingJar = new JarInputStream(new FileInputStream(tmpJarFile));
+		    jarFile = new JarOutputStream(new FileOutputStream( destinationFile ));
+		    jarFile.setLevel(9); //best compression
+		    for(JarEntry je = existingJar.getNextJarEntry(); je != null; je = existingJar.getNextJarEntry()){
+			try{
+			    // By the way, there is no good way to check if a JAR already contains a 
+			    jarFile.putNextEntry( je );
+			}catch(java.util.zip.ZipException ze){
+			    System.err.println("Skipping existing entry " + je);
+			    continue;
 			}
-			tmpJarFile.delete();
-		    }
-		    else{
-			System.err.println("Creating jar file " + jarFileName);
-			jarFile = new JarOutputStream(new FileOutputStream( destinationFile ));
-			jarFile.setLevel(9); //best compression
-			if(webStartIndexWriter != null){
-			    // If it's a package that's going to have each class enumerated, 
-			    // use the short id as the part name 
-			    if(corePackages.containsKey(packageName)){
-				webStartIndexWriter.write("<jar download=\"lazy\" part=\"" + corePackages.get(packageName) +
-							  "\" href=\"" + packageName + ".jar\"/>\n"); 
-			    }
-			    // Otherwise it's only going to be used once, so use the full name
-			    // for clarity's sake
-			    else{
-				webStartIndexWriter.write("<jar download=\"lazy\" part=\"" + packageName + "\" href=\"" +
-							  packageName + ".jar\"/>\n"); 
-			    }
+			/*jar i/o works on a per entry basis, so copy File copies one entry*/
+			copyFile(jarFile, existingJar);  
+			jarFile.closeEntry();
+		    }
+		    tmpJarFile.delete();
+		}
+		else{
+		    System.err.println("Creating jar file " + jarFileName);
+		    jarFile = new JarOutputStream(new FileOutputStream( destinationFile ));
+		    jarFile.setLevel(9); //best compression
+		    if(webStartIndexWriter != null){
+			// If it's a package that's going to have each class enumerated, 
+			// use the short id as the part name 
+			if(corePackages.containsKey(packageName)){
+			    webStartIndexWriter.write("<jar download=\"lazy\" part=\"" + corePackages.get(packageName) +
+						      "\" href=\"" + packageName + ".jar\"/>\n"); 
+			}
+			// Otherwise it's only going to be used once, so use the full name
+			// for clarity's sake
+			else{
+			    webStartIndexWriter.write("<jar download=\"lazy\" part=\"" + packageName + "\" href=\"" +
+						      packageName + ".jar\"/>\n"); 
 			}
 		    }
 		}
-		// A file to add to the jar, not necessarily a class (could be a resource), 
-		// so it's a bit of a misnomer.
-		String className = relativePath;
-		if(relativePath.endsWith(".class")){
-		    className = relativePath.substring(0, relativePath.length()-6).replace('/', '.'); //chops off .class
-		}
-		//System.err.println("Adding " + relativePath);
-		if(webStartIndexWriter != null){
-		    // The package is split between the core jar and this jar, so we need to 
-		    // enumerate each class explicitly that isn't part of the core
-		    if(packageName.equals("no-package")){
-			webStartIndexWriter.write("<package name=\"" + className + "\" part=\"no-package\"/>\n");
-		    }
-		    else if(corePackages.containsKey(packageName)){
-			webStartIndexWriter.write("<package name=\"" + className + "\" part=\"" + 
-						  corePackages.get(packageName) + "\"/>\n");
-		    }
-		    // Is this a purely secondary package that we haven't made an index for yet?
-		    else if(!secondaryPackageWritten.containsKey(packageName)){
-			webStartIndexWriter.write("<package name=\"" + packageName + ".*\" part=\"" + packageName + "\"/>\n");
-			secondaryPackageWritten.put(packageName, "written");
-		    }
-		}
-		try{
-		    jarFile.putNextEntry(new JarEntry(relativePath));
-		    copyFile(jarFile, contents[i].toString());
-		    jarFile.closeEntry();
-		}
-		catch(java.util.zip.ZipException ze2){
-		    System.err.println("Skipping duplicate entry: " + ze2);
-		}
-		savedClasses.put(relativePath, "saved2");
 	    }
-	    if(jarFile != null){  //We saved something
-		jarFile.close();
+	    // A file to add to the jar, not necessarily a class (could be a resource), 
+	    // so it's a bit of a misnomer.
+	    String className = relativePath;
+	    if(relativePath.endsWith(".class")){
+		className = relativePath.substring(0, relativePath.length()-6).replace('/', '.'); //chops off .class
+	    }
+	    //System.err.println("Adding " + relativePath);
+	    if(webStartIndexWriter != null){
+		// The package is split between the core jar and this jar, so we need to 
+		// enumerate each class explicitly that isn't part of the core
+		if(packageName.equals("no-package")){
+		    webStartIndexWriter.write("<package name=\"" + className + "\" part=\"no-package\"/>\n");
+		}
+		else if(corePackages.containsKey(packageName)){
+		    webStartIndexWriter.write("<package name=\"" + className + "\" part=\"" + 
+					      corePackages.get(packageName) + "\"/>\n");
+		}
+		// Is this a purely secondary package that we haven't made an index for yet?
+		else if(!secondaryPackageWritten.containsKey(packageName)){
+		    webStartIndexWriter.write("<package name=\"" + packageName + ".*\" part=\"" + packageName + "\"/>\n");
+		    secondaryPackageWritten.put(packageName, "written");
+		}
+	    }
+	    try{
+		jarFile.putNextEntry(new JarEntry(relativePath));
+		if(entry instanceof JarEntry){
+		    //copyFile(jarFile, srcJarFile.getInputStream((JarEntry) entry));
+		    // Use the line below, not above, because different JARs are zipped differently, so we need to 
+		    // get the bytes then rewrite them rather than copy zip entries to ensure entry sizes are correct,
+		    // reflecting the output JAR file's compression scheme, etc.
+		    copyFile(jarFile, getClassBytesFromJar(srcJarFile, relativePath));
+		}
+		else{
+		    copyFile(jarFile, entry.toString());
+		}
+		jarFile.closeEntry();
+	    }
+	    catch(java.util.zip.ZipException ze2){
+		System.err.println("Skipping duplicate entry: " + ze2);
+		ze2.printStackTrace();
 	    }
+	    savedClasses.put(relativePath, "saved2");
+	}
+	if(jarFile != null){  //We saved something
+	    jarFile.close();
 	}
     }
 




More information about the MOBY-guts mailing list