Class Jar

  • All Implemented Interfaces:
    java.io.Closeable, java.lang.AutoCloseable

    public class Jar
    extends java.lang.Object
    implements java.io.Closeable
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      static class  Jar.Compression  
    • Constructor Summary

      Constructors 
      Constructor Description
      Jar​(java.io.File f)  
      Jar​(java.lang.String name)  
      Jar​(java.lang.String string, java.io.File file)  
      Jar​(java.lang.String name, java.io.File dirOrFile, java.util.regex.Pattern doNotCopy)  
      Jar​(java.lang.String name, java.io.InputStream in)  
      Jar​(java.lang.String name, java.io.InputStream in, long lastModified)  
      Jar​(java.lang.String name, java.lang.String path)  
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      boolean addAll​(Jar src)  
      boolean addAll​(Jar sub, Instruction filter)
      Add all the resources in the given jar that match the given filter.
      boolean addAll​(Jar sub, Instruction filter, java.lang.String destination)
      Add all the resources in the given jar that match the given filter.
      boolean addDirectory​(java.util.Map<java.lang.String,​Resource> directory, boolean overwrite)  
      private static void attributes​(java.util.jar.Attributes value, java.io.OutputStream out)
      Output an Attributes map.
      (package private) java.lang.String automaticModuleName()  
      private Jar buildFromDirectory​(java.nio.file.Path baseDir, java.util.regex.Pattern doNotCopy)  
      private Jar buildFromInputStream​(java.io.InputStream in)  
      private Jar buildFromResource​(Resource resource)  
      private Jar buildFromZip​(java.io.File file)  
      void calcChecksums​(java.lang.String[] algorithms)
      Calculate the checksums and set them in the manifest.
      (package private) void check()  
      private static java.lang.String clean​(java.lang.String s)  
      private static java.util.jar.Manifest clean​(java.util.jar.Manifest org)  
      void close()  
      void copy​(Jar srce, java.lang.String path, boolean overwrite)  
      private void copyResource​(java.io.File dir, java.lang.String path, Resource resource)  
      (package private) void createDirectories​(java.util.Set<java.lang.String> directories, java.util.zip.ZipOutputStream zip, java.lang.String name)  
      void doChecksums​(java.io.OutputStream out)  
      private void doManifest​(java.util.zip.ZipOutputStream jout, java.util.Set<java.lang.String> directories, java.lang.String manifestName)  
      void ensureManifest()
      Make sure we have a manifest
      boolean exists​(java.lang.String path)  
      void expand​(java.io.File dir)
      Expand the JAR file to a directory.
      static Jar fromResource​(java.lang.String name, Resource resource)  
      java.lang.String getBsn()
      Get the jar bsn from the Constants.BUNDLE_SYMBOLICNAME manifest header.
      java.net.URI getDataURI​(java.lang.String path, java.lang.String mime, int max)
      Return a data uri from the JAR.
      java.util.Map<java.lang.String,​java.util.Map<java.lang.String,​Resource>> getDirectories()  
      java.util.Map<java.lang.String,​Resource> getDirectory​(java.lang.String path)  
      int getLength()
      Get the length of the last written file or -1 if unavailable.
      java.util.jar.Manifest getManifest()  
      java.lang.String getModuleName()  
      java.lang.String getModuleVersion()  
      java.lang.String getName()  
      private static java.lang.String getName​(java.io.File f)
      Make the JAR file name the project name if we get a src or bin directory.
      java.util.List<java.lang.String> getPackages()  
      private java.lang.String getParent​(java.lang.String path)  
      java.util.stream.Stream<Resource> getPomXmlResources()  
      Resource getResource​(java.lang.String path)  
      java.util.stream.Stream<java.lang.String> getResourceNames​(java.util.function.Predicate<java.lang.String> matches)  
      java.util.Map<java.lang.String,​Resource> getResources()  
      static java.util.stream.Stream<Resource> getResources​(Resource jarResource, java.util.function.Predicate<java.lang.String> filter)  
      java.util.stream.Stream<Resource> getResources​(java.util.function.Predicate<java.lang.String> matches)  
      java.util.Optional<byte[]> getSHA256()
      Get the SHA256 digest of the last write operation when setCalculateFileDigest(boolean) was on.
      java.io.File getSource()  
      byte[] getTimelessDigest()  
      java.lang.String getVersion()
      Get the jar version from the Constants.BUNDLE_VERSION manifest header.
      Jar.Compression hasCompression()  
      boolean hasDirectory​(java.lang.String path)  
      boolean isEmpty()  
      boolean isManifestFirst()
      Answer if the manifest was the first entry
      boolean isReproducible()  
      long lastModified()  
      (package private) java.lang.String lastModifiedReason()  
      (package private) java.util.Optional<java.util.jar.Manifest> manifest()  
      (package private) java.util.Optional<ModuleAttribute> moduleAttribute()  
      static void outputManifest​(java.util.jar.Manifest manifest, java.io.OutputStream out)
      Main function to output a manifest properly in UTF-8.
      private java.lang.String padString​(java.lang.String s, int length, char pad)  
      private void putEntry​(java.util.zip.ZipOutputStream jout, java.util.zip.ZipEntry entry, Resource r)  
      boolean putResource​(java.lang.String path, Resource resource)  
      boolean putResource​(java.lang.String path, Resource resource, boolean overwrite)  
      Resource remove​(java.lang.String path)  
      void removePrefix​(java.lang.String prefixLow)  
      void removeSubDirs​(java.lang.String dir)  
      boolean rename​(java.lang.String oldPath, java.lang.String newPath)  
      Jar setCalculateFileDigest​(boolean onOrOff)
      Make this jar calculate the SHA256 when it is saved as a file.
      void setCompression​(Jar.Compression compression)  
      void setDigestAlgorithms​(java.lang.String[] algorithms)  
      void setDoNotTouchManifest()
      Make sure nobody touches the manifest! If the bundle is signed, we do not want anybody to touch the manifest after the digests have been calculated.
      void setManifest​(java.io.File file)  
      void setManifest​(java.util.jar.Manifest manifest)  
      void setManifestName​(java.lang.String manifestName)  
      void setName​(java.lang.String name)  
      void setReproducible​(boolean reproducible)  
      void stripSignatures()  
      java.lang.String toString()  
      void updateModified​(long time, java.lang.String reason)  
      void write​(java.io.File file)  
      void write​(java.io.OutputStream to)  
      private static int write​(java.io.OutputStream out, int width, byte[] bytes)
      Write the bytes but ensure that the line length does not exceed 72 characters.
      private static int write​(java.io.OutputStream out, int width, java.lang.String s)
      Convert a string to bytes with UTF-8 and then output in max 72 bytes
      void write​(java.lang.String file)  
      private static void writeEntry​(java.io.OutputStream out, java.lang.String name, java.lang.String value)
      Write out an entry, handling proper unicode and line length constraints
      void writeFolder​(java.io.File dir)  
      void writeManifest​(java.io.OutputStream out)
      Cleanup the manifest for writing.
      static void writeManifest​(java.util.jar.Manifest manifest, java.io.OutputStream out)  
      private void writeResource​(java.util.zip.ZipOutputStream jout, java.util.Set<java.lang.String> directories, java.lang.String path, Resource resource)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • ZIP_ENTRY_CONSTANT_TIME

        private static final long ZIP_ENTRY_CONSTANT_TIME
        Note that setting the January 1st 1980 (or even worse, "0", as time) won't work due to Java 8 doing some interesting time processing: It checks if this date is before January 1st 1980 and if it is it starts setting some extra fields in the zip. Java 7 does not do that - but in the zip not the milliseconds are saved but values for each of the date fields - but no time zone. And 1980 is the first year which can be saved. If you use January 1st 1980 then it is treated as a special flag in Java 8. Moreover, only even seconds can be stored in the zip file. Java 8 uses the upper half of some other long to store the remaining millis while Java 7 doesn't do that. So make sure that your seconds are even. Moreover, parsing happens via `new Date(millis)` in ZipUtils#javaToDosTime() so we must use default timezone and locale. The date is 1980 February 1st CET.
      • DEFAULT_MANIFEST_NAME

        private static final java.lang.String DEFAULT_MANIFEST_NAME
        See Also:
        Constant Field Values
      • DEFAULT_DO_NOT_COPY

        private static final java.util.regex.Pattern DEFAULT_DO_NOT_COPY
      • EMPTY_ARRAY

        public static final java.lang.Object[] EMPTY_ARRAY
      • resources

        private final java.util.NavigableMap<java.lang.String,​Resource> resources
      • directories

        private final java.util.NavigableMap<java.lang.String,​java.util.Map<java.lang.String,​Resource>> directories
      • manifest

        private java.util.Optional<java.util.jar.Manifest> manifest
      • moduleAttribute

        private java.util.Optional<ModuleAttribute> moduleAttribute
      • manifestFirst

        private boolean manifestFirst
      • manifestName

        private java.lang.String manifestName
      • name

        private java.lang.String name
      • source

        private java.io.File source
      • zipFile

        private java.util.zip.ZipFile zipFile
      • lastModified

        private long lastModified
      • lastModifiedReason

        private java.lang.String lastModifiedReason
      • doNotTouchManifest

        private boolean doNotTouchManifest
      • nomanifest

        private boolean nomanifest
      • reproducible

        private boolean reproducible
      • closed

        private boolean closed
      • algorithms

        private java.lang.String[] algorithms
      • sha256

        private SHA256 sha256
      • calculateFileDigest

        private boolean calculateFileDigest
      • fileLength

        private int fileLength
      • EOL

        private static final byte[] EOL
        Unfortunately we have to write our own manifest :-( because of a stupid bug in the manifest code. It tries to handle UTF-8 but the way it does it it makes the bytes platform dependent. So the following code outputs the manifest. A Manifest consists of
          'Manifest-Version: 1.0\r\n'
         main-attributes * \r\n name-section main-attributes ::= attributes
         attributes ::= key ': ' value '\r\n' name-section ::= 'Name: ' name
         '\r\n' attributes
         
        Lines in the manifest should not exceed 72 bytes (! this is where the manifest screwed up as well when 16 bit unicodes were used).

        As a bonus, we can now sort the manifest!

      • SEPARATOR

        private static final byte[] SEPARATOR
      • BSN

        private static final java.util.regex.Pattern BSN
      • SIGNER_FILES_P

        private static final java.util.regex.Pattern SIGNER_FILES_P
      • pomXmlFilter

        private static final java.util.function.Predicate<java.lang.String> pomXmlFilter
    • Constructor Detail

      • Jar

        public Jar​(java.lang.String name)
      • Jar

        public Jar​(java.lang.String name,
                   java.io.File dirOrFile,
                   java.util.regex.Pattern doNotCopy)
            throws java.io.IOException
        Throws:
        java.io.IOException
      • Jar

        public Jar​(java.lang.String name,
                   java.io.InputStream in,
                   long lastModified)
            throws java.io.IOException
        Throws:
        java.io.IOException
      • Jar

        public Jar​(java.lang.String name,
                   java.lang.String path)
            throws java.io.IOException
        Throws:
        java.io.IOException
      • Jar

        public Jar​(java.io.File f)
            throws java.io.IOException
        Throws:
        java.io.IOException
      • Jar

        public Jar​(java.lang.String name,
                   java.io.InputStream in)
            throws java.io.IOException
        Throws:
        java.io.IOException
      • Jar

        public Jar​(java.lang.String string,
                   java.io.File file)
            throws java.io.IOException
        Throws:
        java.io.IOException
    • Method Detail

      • fromResource

        public static Jar fromResource​(java.lang.String name,
                                       Resource resource)
                                throws java.lang.Exception
        Throws:
        java.lang.Exception
      • getResources

        public static java.util.stream.Stream<Resource> getResources​(Resource jarResource,
                                                                     java.util.function.Predicate<java.lang.String> filter)
                                                              throws java.lang.Exception
        Throws:
        java.lang.Exception
      • getName

        private static java.lang.String getName​(java.io.File f)
        Make the JAR file name the project name if we get a src or bin directory.
        Parameters:
        f -
      • buildFromDirectory

        private Jar buildFromDirectory​(java.nio.file.Path baseDir,
                                       java.util.regex.Pattern doNotCopy)
                                throws java.io.IOException
        Throws:
        java.io.IOException
      • buildFromZip

        private Jar buildFromZip​(java.io.File file)
                          throws java.io.IOException
        Throws:
        java.io.IOException
      • buildFromResource

        private Jar buildFromResource​(Resource resource)
                               throws java.lang.Exception
        Throws:
        java.lang.Exception
      • buildFromInputStream

        private Jar buildFromInputStream​(java.io.InputStream in)
                                  throws java.io.IOException
        Throws:
        java.io.IOException
      • setName

        public void setName​(java.lang.String name)
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • putResource

        public boolean putResource​(java.lang.String path,
                                   Resource resource)
      • putResource

        public boolean putResource​(java.lang.String path,
                                   Resource resource,
                                   boolean overwrite)
      • getResource

        public Resource getResource​(java.lang.String path)
      • getResourceNames

        public java.util.stream.Stream<java.lang.String> getResourceNames​(java.util.function.Predicate<java.lang.String> matches)
      • getResources

        public java.util.stream.Stream<Resource> getResources​(java.util.function.Predicate<java.lang.String> matches)
      • getParent

        private java.lang.String getParent​(java.lang.String path)
      • getDirectories

        public java.util.Map<java.lang.String,​java.util.Map<java.lang.String,​Resource>> getDirectories()
      • getDirectory

        public java.util.Map<java.lang.String,​Resource> getDirectory​(java.lang.String path)
      • getResources

        public java.util.Map<java.lang.String,​Resource> getResources()
      • addDirectory

        public boolean addDirectory​(java.util.Map<java.lang.String,​Resource> directory,
                                    boolean overwrite)
      • getManifest

        public java.util.jar.Manifest getManifest()
                                           throws java.lang.Exception
        Throws:
        java.lang.Exception
      • manifest

        java.util.Optional<java.util.jar.Manifest> manifest()
      • moduleAttribute

        java.util.Optional<ModuleAttribute> moduleAttribute()
                                                     throws java.lang.Exception
        Throws:
        java.lang.Exception
      • getModuleName

        public java.lang.String getModuleName()
                                       throws java.lang.Exception
        Throws:
        java.lang.Exception
      • automaticModuleName

        java.lang.String automaticModuleName()
      • getModuleVersion

        public java.lang.String getModuleVersion()
                                          throws java.lang.Exception
        Throws:
        java.lang.Exception
      • exists

        public boolean exists​(java.lang.String path)
      • isEmpty

        public boolean isEmpty()
      • setManifest

        public void setManifest​(java.util.jar.Manifest manifest)
      • setManifest

        public void setManifest​(java.io.File file)
                         throws java.io.IOException
        Throws:
        java.io.IOException
      • setManifestName

        public void setManifestName​(java.lang.String manifestName)
      • write

        public void write​(java.io.File file)
                   throws java.lang.Exception
        Throws:
        java.lang.Exception
      • write

        public void write​(java.lang.String file)
                   throws java.lang.Exception
        Throws:
        java.lang.Exception
      • write

        public void write​(java.io.OutputStream to)
                   throws java.lang.Exception
        Throws:
        java.lang.Exception
      • writeFolder

        public void writeFolder​(java.io.File dir)
                         throws java.lang.Exception
        Throws:
        java.lang.Exception
      • copyResource

        private void copyResource​(java.io.File dir,
                                  java.lang.String path,
                                  Resource resource)
                           throws java.lang.Exception
        Throws:
        java.lang.Exception
      • doChecksums

        public void doChecksums​(java.io.OutputStream out)
                         throws java.lang.Exception
        Throws:
        java.lang.Exception
      • padString

        private java.lang.String padString​(java.lang.String s,
                                           int length,
                                           char pad)
      • doManifest

        private void doManifest​(java.util.zip.ZipOutputStream jout,
                                java.util.Set<java.lang.String> directories,
                                java.lang.String manifestName)
                         throws java.lang.Exception
        Throws:
        java.lang.Exception
      • putEntry

        private void putEntry​(java.util.zip.ZipOutputStream jout,
                              java.util.zip.ZipEntry entry,
                              Resource r)
                       throws java.lang.Exception
        Throws:
        java.lang.Exception
      • writeManifest

        public void writeManifest​(java.io.OutputStream out)
                           throws java.lang.Exception
        Cleanup the manifest for writing. Cleaning up consists of adding a space after any \n to prevent the manifest to see this newline as a delimiter.
        Parameters:
        out - Output
        Throws:
        java.io.IOException
        java.lang.Exception
      • writeManifest

        public static void writeManifest​(java.util.jar.Manifest manifest,
                                         java.io.OutputStream out)
                                  throws java.io.IOException
        Throws:
        java.io.IOException
      • outputManifest

        public static void outputManifest​(java.util.jar.Manifest manifest,
                                          java.io.OutputStream out)
                                   throws java.io.IOException
        Main function to output a manifest properly in UTF-8.
        Parameters:
        manifest - The manifest to output
        out - The output stream
        Throws:
        java.io.IOException - when something fails
      • writeEntry

        private static void writeEntry​(java.io.OutputStream out,
                                       java.lang.String name,
                                       java.lang.String value)
                                throws java.io.IOException
        Write out an entry, handling proper unicode and line length constraints
        Throws:
        java.io.IOException
      • write

        private static int write​(java.io.OutputStream out,
                                 int width,
                                 java.lang.String s)
                          throws java.io.IOException
        Convert a string to bytes with UTF-8 and then output in max 72 bytes
        Parameters:
        out - the output string
        width - the current width
        s - the string to output
        Returns:
        the new width
        Throws:
        java.io.IOException - when something fails
      • write

        private static int write​(java.io.OutputStream out,
                                 int width,
                                 byte[] bytes)
                          throws java.io.IOException
        Write the bytes but ensure that the line length does not exceed 72 characters. If it is more than 70 characters, we just put a cr/lf + space.
        Parameters:
        out - The output stream
        width - The nr of characters output in a line before this method started
        bytes - the bytes to output
        Returns:
        the nr of characters in the last line
        Throws:
        java.io.IOException - if something fails
      • attributes

        private static void attributes​(java.util.jar.Attributes value,
                                       java.io.OutputStream out)
                                throws java.io.IOException
        Output an Attributes map. We will sort this map before outputing.
        Parameters:
        value - the attributes
        out - the output stream
        Throws:
        java.io.IOException - when something fails
      • clean

        private static java.util.jar.Manifest clean​(java.util.jar.Manifest org)
      • clean

        private static java.lang.String clean​(java.lang.String s)
      • writeResource

        private void writeResource​(java.util.zip.ZipOutputStream jout,
                                   java.util.Set<java.lang.String> directories,
                                   java.lang.String path,
                                   Resource resource)
                            throws java.lang.Exception
        Throws:
        java.lang.Exception
      • createDirectories

        void createDirectories​(java.util.Set<java.lang.String> directories,
                               java.util.zip.ZipOutputStream zip,
                               java.lang.String name)
                        throws java.io.IOException
        Throws:
        java.io.IOException
      • getName

        public java.lang.String getName()
      • addAll

        public boolean addAll​(Jar sub,
                              Instruction filter)
        Add all the resources in the given jar that match the given filter.
        Parameters:
        sub - the jar
        filter - a pattern that should match the resoures in sub to be added
      • addAll

        public boolean addAll​(Jar sub,
                              Instruction filter,
                              java.lang.String destination)
        Add all the resources in the given jar that match the given filter.
        Parameters:
        sub - the jar
        filter - a pattern that should match the resoures in sub to be added
      • close

        public void close()
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface java.io.Closeable
      • lastModified

        public long lastModified()
      • lastModifiedReason

        java.lang.String lastModifiedReason()
      • updateModified

        public void updateModified​(long time,
                                   java.lang.String reason)
      • hasDirectory

        public boolean hasDirectory​(java.lang.String path)
      • getPackages

        public java.util.List<java.lang.String> getPackages()
      • getSource

        public java.io.File getSource()
      • addAll

        public boolean addAll​(Jar src)
      • rename

        public boolean rename​(java.lang.String oldPath,
                              java.lang.String newPath)
      • remove

        public Resource remove​(java.lang.String path)
      • setDoNotTouchManifest

        public void setDoNotTouchManifest()
        Make sure nobody touches the manifest! If the bundle is signed, we do not want anybody to touch the manifest after the digests have been calculated.
      • calcChecksums

        public void calcChecksums​(java.lang.String[] algorithms)
                           throws java.lang.Exception
        Calculate the checksums and set them in the manifest.
        Throws:
        java.lang.Exception
      • getBsn

        public java.lang.String getBsn()
                                throws java.lang.Exception
        Get the jar bsn from the Constants.BUNDLE_SYMBOLICNAME manifest header.
        Returns:
        null when the jar has no manifest, when the manifest has no Constants.BUNDLE_SYMBOLICNAME header, or when the value of the header is not a valid bsn according to BSN.
        Throws:
        java.lang.Exception - when the jar is closed or when the manifest could not be retrieved.
      • getVersion

        public java.lang.String getVersion()
                                    throws java.lang.Exception
        Get the jar version from the Constants.BUNDLE_VERSION manifest header.
        Returns:
        null when the jar has no manifest or when the manifest has no Constants.BUNDLE_VERSION header
        Throws:
        java.lang.Exception - when the jar is closed or when the manifest could not be retrieved.
      • expand

        public void expand​(java.io.File dir)
                    throws java.lang.Exception
        Expand the JAR file to a directory.
        Parameters:
        dir - the dst directory, is not required to exist
        Throws:
        java.lang.Exception - if anything does not work as expected.
      • ensureManifest

        public void ensureManifest()
                            throws java.lang.Exception
        Make sure we have a manifest
        Throws:
        java.lang.Exception
      • isManifestFirst

        public boolean isManifestFirst()
        Answer if the manifest was the first entry
      • isReproducible

        public boolean isReproducible()
      • setReproducible

        public void setReproducible​(boolean reproducible)
      • copy

        public void copy​(Jar srce,
                         java.lang.String path,
                         boolean overwrite)
      • setCompression

        public void setCompression​(Jar.Compression compression)
      • check

        void check()
      • getDataURI

        public java.net.URI getDataURI​(java.lang.String path,
                                       java.lang.String mime,
                                       int max)
                                throws java.lang.Exception
        Return a data uri from the JAR. The data must be less than 32k
        Parameters:
        path - the path in the jar
        mime - the mime type
        Returns:
        a URI or null if conversion could not take place
        Throws:
        java.lang.Exception
      • setDigestAlgorithms

        public void setDigestAlgorithms​(java.lang.String[] algorithms)
      • getTimelessDigest

        public byte[] getTimelessDigest()
                                 throws java.lang.Exception
        Throws:
        java.lang.Exception
      • stripSignatures

        public void stripSignatures()
      • removePrefix

        public void removePrefix​(java.lang.String prefixLow)
      • removeSubDirs

        public void removeSubDirs​(java.lang.String dir)
      • getPomXmlResources

        public java.util.stream.Stream<Resource> getPomXmlResources()
      • setCalculateFileDigest

        public Jar setCalculateFileDigest​(boolean onOrOff)
        Make this jar calculate the SHA256 when it is saved as a file. When this JAR is written, the digest is always cleared. If this flag is on, it will be calculated and set when the file is successfully saved.
        Parameters:
        onOrOff - state of calculating the digest when writing this jar. true is on, otherwise off
      • getSHA256

        public java.util.Optional<byte[]> getSHA256()
        Get the SHA256 digest of the last write operation when setCalculateFileDigest(boolean) was on.
        Returns:
        the SHA 256 digest or empty
      • getLength

        public int getLength()
        Get the length of the last written file or -1 if unavailable. The length is only calculated when the checksum calculation was on during the write.
        Returns:
        the length of the last written file or -1 if unavailable.