View Javadoc

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