View Javadoc
1   package com.atlassian.plugin.osgi.factory.transform;
2   
3   import com.google.common.collect.ImmutableList;
4   
5   import java.io.File;
6   import java.io.IOException;
7   import java.util.function.Function;
8   import java.util.jar.JarEntry;
9   import java.util.jar.JarFile;
10  import java.util.jar.Manifest;
11  import java.util.zip.ZipEntry;
12  
13  import static com.google.common.collect.Iterators.forEnumeration;
14  
15  /**
16   * Utility methods for getting stuff out of a jar.
17   *
18   * @since 2.6
19   */
20  public final class JarUtils {
21      /**
22       * Not for instantiation.
23       */
24      private JarUtils() {
25      }
26  
27      /**
28       * Get the {@link Manifest} from a Jar file, or create a new one if there isn't one already.
29       *
30       * @param file the file that is the jar contents
31       * @return the manifest or an empty new one if one can't be found.
32       */
33      public static Manifest getManifest(final File file) {
34          final Manifest result = withJar(file, ManifestExtractor.INSTANCE);
35          return (result == null) ? new Manifest() : result;
36      }
37  
38      public static boolean hasManifestEntry(Manifest manifest, final String entryName) {
39          return manifest != null && manifest.getMainAttributes().getValue(entryName) != null;
40      }
41  
42      /**
43       * Get the {@link JarEntry entries} from a Jar file.
44       *
45       * @param file the file that is the jar contents
46       * @return the entries the jar contains.
47       */
48      static Iterable<JarEntry> getEntries(final File file) {
49          return withJar(file, JarEntryExtractor.INSTANCE);
50      }
51  
52      /**
53       * Get a specific {@link ZipEntry entry} from a Jar file.
54       *
55       * @param file the file that is the jar contents
56       * @return the specified entry in the jar if it exists or null if it can't be found.
57       */
58      static JarEntry getEntry(final File file, final String path) {
59          return withJar(file, jarFile -> jarFile.getJarEntry(path));
60      }
61  
62      /**
63       * Extract something from a jar file.
64       * <p>
65       * Correctly opens and closes the Jar file. Must not lazily access the Jar as it has an open/closed state.
66       *
67       * @param <T>       the type of the thing to extract
68       * @param file      the file that is the jar contents
69       * @param extractor the extractor function to apply
70       * @return the result of the extractor
71       * @throws RuntimeException if there are problems accessing the jar contents.
72       */
73      public static <T> T withJar(final File file, final Extractor<T> extractor) {
74          try (JarFile jarFile = new JarFile(file)){
75              return extractor.apply(jarFile);
76          } catch (final IOException e) {
77              throw new IllegalArgumentException("File must be a jar: " + file, e);
78          }
79      }
80  
81      /**
82       * Quietly close jar file.
83       *
84       * @param jarFile the file to close.
85       */
86      public static void closeQuietly(final JarFile jarFile) {
87          if (jarFile != null) {
88              try {
89                  jarFile.close();
90              } catch (final IOException ignore) {
91              }
92          }
93      }
94  
95      public interface Extractor<T> extends Function<JarFile, T> {
96      }
97  
98      enum ManifestExtractor implements Extractor<Manifest> {
99          INSTANCE;
100 
101         public Manifest apply(final JarFile input) {
102             try {
103                 return input.getManifest();
104             } catch (final IOException e) {
105                 throw new RuntimeException(e);
106             }
107         }
108     }
109 
110     enum JarEntryExtractor implements Extractor<Iterable<JarEntry>> {
111         INSTANCE;
112 
113         public Iterable<JarEntry> apply(final JarFile jarFile) {
114             return ImmutableList.copyOf(forEnumeration(jarFile.entries()));
115         }
116     }
117 }