View Javadoc

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