Mega Code Archive

 
Categories / Java Tutorial / File
 

Jar Entry OutputStream

/*  * The contents of this file are subject to the Sapient Public License  * Version 1.0 (the "License"); you may not use this file except in compliance  * with the License. You may obtain a copy of the License at  * http://carbon.sf.net/License.html.  *  * Software distributed under the License is distributed on an "AS IS" basis,  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for  * the specific language governing rights and limitations under the License.  *  * The Original Code is The Carbon Component Framework.  *  * The Initial Developer of the Original Code is Sapient Corporation  *  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.  */ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.StringTokenizer; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import java.util.zip.ZipEntry; import sun.rmi.runtime.Log; /**  * An output stream that is used by EnhancedJarFile to write entries to a jar.  * This implementation uses a ByteArrayOutputStream to buffer the output  * until the stream is closed.  When the stream is closed, the output is written  * to the jar.  *  * Copyright 2002 Sapient  * @since carbon 1.0  * @author Douglas Voet, April 2002  * @version $Revision: 1.9 $($Author: dvoet $ / $Date: 2003/05/05 21:21:23 $)  */ public class JarEntryOutputStream extends ByteArrayOutputStream {     private EnhancedJarFile jar;     private String jarEntryName;     /**      * Constructor      *      * @param jar the EnhancedJarFile that this instance will write to      * @param jarEntryName the name of the entry to be written      */     public JarEntryOutputStream(         EnhancedJarFile jar,         String jarEntryName) {         super();         this.jarEntryName = jarEntryName;         this.jar = jar;     }     /**      * Closes the stream and writes entry to the jar      */     public void close() throws IOException {         writeToJar();         super.close();     }     /**      * Writes the entry to a the jar file.  This is done by creating a      * temporary jar file, copying the contents of the existing jar to the      * temp jar, skipping the entry named by this.jarEntryName if it exists.      * Then, if the stream was written to, then contents are written as a      * new entry.  Last, a callback is made to the EnhancedJarFile to      * swap the temp jar in for the old jar.      */     private void writeToJar() throws IOException {         File jarDir = new File(this.jar.getName()).getParentFile();         // create new jar         File newJarFile = File.createTempFile("config", ".jar", jarDir);         newJarFile.deleteOnExit();         JarOutputStream jarOutputStream =             new JarOutputStream(new FileOutputStream(newJarFile));         try {             Enumeration entries = this.jar.entries();             // copy all current entries into the new jar             while (entries.hasMoreElements()) {                 JarEntry nextEntry = (JarEntry) entries.nextElement();                 // skip the entry named jarEntryName                 if (!this.jarEntryName.equals(nextEntry.getName())) {                     // the next 3 lines of code are a work around for                     // bug 4682202 in the java.sun.com bug parade, see:                     // http://developer.java.sun.com/developer/bugParade/bugs/4682202.html                     JarEntry entryCopy = new JarEntry(nextEntry);                     entryCopy.setCompressedSize(-1);                     jarOutputStream.putNextEntry(entryCopy);                     InputStream intputStream =                         this.jar.getInputStream(nextEntry);                     // write the data                     for (int data = intputStream.read();                         data != -1;                         data = intputStream.read()) {                         jarOutputStream.write(data);                     }                 }             }             // write the new or modified entry to the jar             if (size() > 0) {                 jarOutputStream.putNextEntry(new JarEntry(this.jarEntryName));                 jarOutputStream.write(super.buf, 0, size());                 jarOutputStream.closeEntry();             }         } finally {             // close close everything up             try {                 if (jarOutputStream != null) {                     jarOutputStream.close();                 }             } catch (IOException ioe) {                 // eat it, just wanted to close stream             }         }         // swap the jar         this.jar.swapJars(newJarFile);     } } /*  * The contents of this file are subject to the Sapient Public License  * Version 1.0 (the "License"); you may not use this file except in compliance  * with the License. You may obtain a copy of the License at  * http://carbon.sf.net/License.html.  *  * Software distributed under the License is distributed on an "AS IS" basis,  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for  * the specific language governing rights and limitations under the License.  *  * The Original Code is The Carbon Component Framework.  *  * The Initial Developer of the Original Code is Sapient Corporation  *  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.  */ /**  * This class enhances functionality of java.util.jar.JarFile.  * Additional functionality includes jar entry removal, the ability to list  * the entries within a directory within the jar, and the ability to get  * an output stream for modifying extisting entries.  *  * @see java.util.jar.JarFile  *  * Copyright 2002 Sapient  * @since carbon 1.0  * @author Doug Voet, April 2002  * @version $Revision: 1.11 $ ($Author: dvoet $)  */ class EnhancedJarFile {     public static final String JAR_DELIMETER = "/";       private JarFile jar;     /**      * @see java.util.jar.JarFile#JarFile(java.lang.String)      */     public EnhancedJarFile(String name) throws IOException {         this.jar = new JarFile(name);     }     /**      * @see java.util.jar.JarFile#JarFile(java.lang.String, boolean)      */     public EnhancedJarFile(String name, boolean verify) throws IOException {         this.jar = new JarFile(name, verify);     }     /**      * @see java.util.jar.JarFile#JarFile(java.io.File)      */     public EnhancedJarFile(File file) throws IOException {         this.jar = new JarFile(file);     }     /**      * @see java.util.jar.JarFile#JarFile(java.io.File, boolean)      */     public EnhancedJarFile(File file, boolean verify) throws IOException {         this.jar = new JarFile(file, verify);     }     /**      * @see java.util.jar.JarFile#JarFile(java.io.File, boolean, int)      */     public EnhancedJarFile(File file, boolean verify, int mode)         throws IOException {         this.jar = new JarFile(file, verify, mode);     }     /**      * Returns a list of entries that are      * immediately below the entry named by entryName in the jar's directory      * structure.      *      * @param entryName the name of the directory entry name      * @return List a list of java.util.jar.JarEntry objects that are      * immediately below the entry named by entryName in the jar's directory      * structure.      */     public List listSubEntries(String entryName) {         Enumeration entries = jar.entries();         List subEntries = new ArrayList();         while(entries.hasMoreElements()) {             JarEntry nextEntry = (JarEntry) entries.nextElement();             if (nextEntry.getName().startsWith(entryName)) {                 // the next entry name starts with the entryName so it                 // is a potential sub entry                 // tokenize the rest of the next entry name to see how                 // many tokens exist                 StringTokenizer tokenizer = new StringTokenizer(                     nextEntry.getName().substring(entryName.length()),                     EnhancedJarFile.JAR_DELIMETER);                 if (tokenizer.countTokens() == 1) {                     // only 1 token exists, so it is a sub-entry                     subEntries.add(nextEntry);                 }             }         }         return subEntries;     }     /**      * Creates a new output entry stream within the jar.  The entry named      * will be created if it does not exist within the jar already.      *      * @param entryName name of the entry for which to create an output      * stream.      * @return JarEntryOutputStream      */     public JarEntryOutputStream getEntryOutputStream(String entryName) {         return new JarEntryOutputStream(this, entryName);     }     /**      * Removes the given entry from the jar.  If the entry does not exist,      * the method returns without doing anything.      *      * @param entry entry to be removed      * @throws IOException if there is a problem writing the changes      * to the jar      */     public void removeEntry(JarEntry entry) throws IOException {         // opens an output stream and closes it without writing anything to it         if (entry != null && getEntry(entry.getName()) != null) {             JarEntryOutputStream outputStream =                 new JarEntryOutputStream(this, entry.getName());             outputStream.close();         }     }     /**      * @see java.util.jar.JarFile#entries()      */     public Enumeration entries() {         return this.jar.entries();     }     /**      * @see java.util.jar.JarFile#getEntry(java.lang.String)      */     public ZipEntry getEntry(String arg0) {         return this.jar.getEntry(arg0);     }     /**      * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)      */     public InputStream getInputStream(ZipEntry arg0) throws IOException {         return this.jar.getInputStream(arg0);     }     /**      * @see java.util.jar.JarFile#getJarEntry(java.lang.String)      */     public JarEntry getJarEntry(String arg0) {         return this.jar.getJarEntry(arg0);     }     /**      * @see java.util.jar.JarFile#getManifest()      */     public Manifest getManifest() throws IOException {         return this.jar.getManifest();     }     /**      * @see java.util.zip.ZipFile#close()      */     public void close() throws IOException {         this.jar.close();     }     /**      * @see java.util.zip.ZipFile#getName()      */     public String getName() {         return this.jar.getName();     }     /**      * @see java.util.zip.ZipFile#size()      */     public int size() {         return this.jar.size();     }     /**      * Utility method used to swap the underlying jar file out for the new one.      * This method closes the old jar file, deletes it, moves the new jar      * file to the location where the old one used to be and opens it.      *       * This is used when modifying the jar (removal, addition, or changes      * of entries)      *      * @param newJarFile the file object pointing to the new jar file      */     void swapJars(File newJarFile) throws IOException {         File oldJarFile = new File(getName());         this.jar.close();         oldJarFile.delete();         if (newJarFile.renameTo(oldJarFile)) {             this.jar = new JarFile(oldJarFile);         } else {             throw new IOException();         }     } }