View Javadoc

1   package com.atlassian.plugin;
2   
3   import org.apache.commons.lang.Validate;
4   import org.apache.commons.io.IOUtils;
5   
6   import java.util.jar.JarFile;
7   import java.util.zip.ZipEntry;
8   import java.io.*;
9   
10  /**
11   * The implementation of PluginArtifact that is backed by a jar file.
12   *
13   * @see PluginArtifact
14   * @since 2.0.0
15   */
16  public class JarPluginArtifact implements PluginArtifact
17  {
18      private final File jarFile;
19  
20      public JarPluginArtifact(File jarFile)
21      {
22          Validate.notNull(jarFile);
23          this.jarFile = jarFile;
24      }
25  
26      public boolean doesResourceExist(String name)
27      {
28          InputStream in = null;
29          try
30          {
31              in = getResourceAsStream(name);
32              return (in != null);
33          }
34          finally
35          {
36              IOUtils.closeQuietly(in);
37          }
38      }
39  
40      /**
41       * @return an input stream for the this file in the jar. Closing this stream also closes the jar file this stream comes from.
42       */
43      public InputStream getResourceAsStream(String fileName) throws PluginParseException
44      {
45          Validate.notNull(fileName, "The file name must not be null");
46          final JarFile jar;
47          final ZipEntry entry;
48          try
49          {
50              jar = new JarFile(jarFile);
51              entry = jar.getEntry(fileName);
52              if (entry == null)
53              {
54                  jar.close();
55                  return null;
56              }
57          }
58          catch (IOException e)
59          {
60              throw new PluginParseException("Cannot open JAR file for reading: " + jarFile, e);
61          }
62  
63          InputStream descriptorStream;
64          try
65          {
66              descriptorStream = new BufferedInputStream(jar.getInputStream(entry)) {
67  
68                  // because we do not expose a handle to the jar file this stream is associated with, we need to make sure
69                  // we explicitly close the jar file when we're done with the stream (else we'll have a file handle leak)
70                  public void close() throws IOException
71                  {
72                      super.close();
73                      jar.close();
74                  }
75              };
76          }
77          catch (IOException e)
78          {
79              throw new PluginParseException("Cannot retrieve " + fileName + " from plugin JAR [" + jarFile + "]", e);
80          }
81          return descriptorStream;
82      }
83  
84      public String getName()
85      {
86          return jarFile.getName();
87      }
88  
89      @Override
90      public String toString()
91      {
92          return getName();
93      }
94  
95      /**
96       * @return a buffered file input stream of the file on disk. This input stream
97       * is not resettable.
98       */
99      public InputStream getInputStream()
100     {
101         try
102         {
103             return new BufferedInputStream(new FileInputStream(jarFile));
104         }
105         catch (FileNotFoundException e)
106         {
107             throw new RuntimeException("Could not open JAR file for reading: " + jarFile, e);
108         }
109     }
110 
111     public File toFile()
112     {
113         return jarFile;
114     }
115 }