View Javadoc
1   package org.codehaus.plexus.resource.loader;
2   
3   /*
4    * The MIT License
5    *
6    * Copyright (c) 2004, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  
27  import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
28  import org.codehaus.plexus.resource.PlexusResource;
29  
30  import java.util.LinkedHashMap;
31  import java.util.Map;
32  
33  /**
34   * @author Jason van Zyl
35   * @plexus.component role-hint="jar" instantiation-strategy="per-lookup"
36   */
37  public class JarResourceLoader
38      extends AbstractResourceLoader
39  {
40      public static final String ID = "jar";
41  
42      /**
43       * Maps entries to the parent JAR File (key = the entry *excluding* plain directories, value = the JAR URL).
44       */
45      private Map entryDirectory = new LinkedHashMap( 559 );
46  
47      /**
48       * Maps JAR URLs to the actual JAR (key = the JAR URL, value = the JAR).
49       */
50      private Map jarfiles = new LinkedHashMap( 89 );
51      
52      private boolean initializeCalled;
53  
54      public void initialize()
55          throws InitializationException
56      {
57          initializeCalled = true;
58          
59          if ( paths != null )
60          {
61              for ( int i = 0; i < paths.size(); i++ )
62              {
63                  loadJar( (String) paths.get( i ) );
64              }
65          }
66      }
67  
68      private void loadJar( String path )
69      {
70          if ( getLogger().isDebugEnabled() )
71          {
72              getLogger().debug( "JarResourceLoader : trying to load \"" + path + "\"" );
73          }
74  
75          // Check path information
76          if ( path == null )
77          {
78              getLogger().error( "JarResourceLoader : can not load JAR - JAR path is null" );
79              return;
80          }
81          if ( !path.startsWith( "jar:" ) )
82          {
83              getLogger().error(
84                                 "JarResourceLoader : JAR path must start with jar: -> "
85                                     + "see java.net.JarURLConnection for information" );
86              return;
87          }
88          if ( !path.endsWith( "!/" ) )
89          {
90              path += "!/";
91          }
92  
93          // Close the jar if it's already open this is useful for a reload
94          closeJar( path );
95  
96          // Create a new JarHolder
97          JarHolder temp = new JarHolder( path );
98  
99          // Add it's entries to the entryCollection
100         addEntries( temp.getEntries() );
101 
102         // Add it to the Jar table
103         jarfiles.put( temp.getUrlPath(), temp );
104     }
105 
106     /**
107      * Closes a Jar file and set its URLConnection to null.
108      */
109     private void closeJar( String path )
110     {
111         if ( jarfiles.containsKey( path ) )
112         {
113             JarHolder theJar = (JarHolder) jarfiles.get( path );
114 
115             theJar.close();
116         }
117     }
118 
119     /**
120      * Copy all the entries into the entryDirectory. It will overwrite any duplicate keys.
121      */
122     private void addEntries( Map entries )
123     {
124         entryDirectory.putAll( entries );
125     }
126 
127     /**
128      * Get an InputStream so that the Runtime can build a template with it.
129      * 
130      * @param source name of template to get
131      * @return InputStream containing the template
132      * @throws ResourceNotFoundException if template not found in the file template path.
133      */
134     public PlexusResource getResource( String source )
135         throws ResourceNotFoundException
136     {
137         if ( !initializeCalled )
138         {
139             try
140             {
141                 initialize();
142             }
143             catch ( InitializationException e )
144             {
145                 throw new ResourceNotFoundException( e.getMessage(), e );
146             }
147         }
148         
149         if ( source == null || source.length() == 0 )
150         {
151             throw new ResourceNotFoundException( "Need to have a resource!" );
152         }
153 
154         /*
155          * if a / leads off, then just nip that :)
156          */
157         if ( source.startsWith( "/" ) )
158         {
159             source = source.substring( 1 );
160         }
161 
162         if ( entryDirectory.containsKey( source ) )
163         {
164             String jarurl = (String) entryDirectory.get( source );
165 
166             final JarHolder holder = (JarHolder) jarfiles.get( jarurl );
167             if ( holder != null )
168             {
169                 return holder.getPlexusResource( source );
170             }
171         }
172 
173         throw new ResourceNotFoundException( "JarResourceLoader Error: cannot find resource " + source );
174     }
175 
176     public void addSearchPath( String path )
177     {
178         if ( !paths.contains( path ) )
179         {
180             if ( initializeCalled )
181             {
182                 loadJar( path );
183             }
184             paths.add( path );
185         }
186     }
187 }