View Javadoc

1   // ========================================================================
2   // Copyright (c) 2007-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.util.resource;
15  
16  import java.io.File;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.io.OutputStream;
20  import java.net.MalformedURLException;
21  import java.net.URL;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.StringTokenizer;
27  
28  import org.eclipse.jetty.util.URIUtil;
29  
30  /**
31   * A collection of resources (dirs).
32   * Allows webapps to have multiple (static) sources.
33   * The first resource in the collection is the main resource.
34   * If a resource is not found in the main resource, it looks it up in 
35   * the order the resources were constructed.
36   * 
37   * 
38   *
39   */
40  public class ResourceCollection extends Resource
41  {
42      private Resource[] _resources;
43  
44      /* ------------------------------------------------------------ */
45      /**
46       * Instantiates an empty resource collection.
47       * 
48       * This constructor is used when configuring jetty-maven-plugin.
49       */
50      public ResourceCollection()
51      {
52          _resources = new Resource[0];
53      }
54      
55      /* ------------------------------------------------------------ */
56      /**
57       * Instantiates a new resource collection.
58       *
59       * @param resources the resources to be added to collection
60       */
61      public ResourceCollection(Resource... resources)
62      {
63          List<Resource> list = new ArrayList<Resource>();
64          for (Resource r : resources)
65          {
66              if (r==null)
67                  continue;
68              if (r instanceof ResourceCollection)
69              {
70                  for (Resource r2 : ((ResourceCollection)r).getResources())
71                      list.add(r2);
72              }
73              else
74                  list.add(r);
75          }
76          _resources = list.toArray(new Resource[list.size()]);
77          for(Resource r : _resources)
78          {
79              if(!r.exists() || !r.isDirectory())
80                  throw new IllegalArgumentException(r + " is not an existing directory.");
81          }
82      }
83      
84      
85      /* ------------------------------------------------------------ */
86      /**
87       * Instantiates a new resource collection.
88       *
89       * @param resources the resource strings to be added to collection
90       */
91      public ResourceCollection(String[] resources)
92      {
93          _resources = new Resource[resources.length];
94          try
95          {
96              for(int i=0; i<resources.length; i++)
97              {
98                  _resources[i] = Resource.newResource(resources[i]);
99                  if(!_resources[i].exists() || !_resources[i].isDirectory())
100                     throw new IllegalArgumentException(_resources[i] + " is not an existing directory.");
101             }
102         }
103         catch(IllegalArgumentException e)
104         {
105             throw e;
106         }
107         catch(Exception e)
108         {
109             throw new RuntimeException(e);
110         }
111     }
112     
113     /* ------------------------------------------------------------ */
114     /**
115      * Instantiates a new resource collection.
116      *
117      * @param csvResources the string containing comma-separated resource strings
118      */
119     public ResourceCollection(String csvResources)
120     {
121         setResourcesAsCSV(csvResources);
122     }
123     
124     /* ------------------------------------------------------------ */
125     /**
126      * Retrieves the resource collection's resources.
127      * 
128      * @return the resource array
129      */
130     public Resource[] getResources()
131     {
132         return _resources;
133     }
134     
135     /* ------------------------------------------------------------ */
136     /**
137      * Sets the resource collection's resources.
138      *
139      * @param resources the new resource array
140      */
141     public void setResources(Resource[] resources)
142     {
143         _resources = resources != null ? resources : new Resource[0];
144     }
145 
146     /* ------------------------------------------------------------ */
147     /**
148      * Sets the resources as string of comma-separated values.
149      * This method should be used when configuring jetty-maven-plugin.
150      *
151      * @param csvResources the comma-separated string containing
152      *                     one or more resource strings.
153      */
154     public void setResourcesAsCSV(String csvResources)
155     {
156         StringTokenizer tokenizer = new StringTokenizer(csvResources, ",;");
157         int len = tokenizer.countTokens();
158         if(len==0)
159         {
160             throw new IllegalArgumentException("ResourceCollection@setResourcesAsCSV(String) " +
161                     " argument must be a string containing one or more comma-separated resource strings.");
162         }
163         
164         _resources = new Resource[len];
165         try
166         {            
167             for(int i=0; tokenizer.hasMoreTokens(); i++)
168             {
169                 _resources[i] = Resource.newResource(tokenizer.nextToken().trim());
170                 if(!_resources[i].exists() || !_resources[i].isDirectory())
171                     throw new IllegalArgumentException(_resources[i] + " is not an existing directory.");
172             }
173         }
174         catch(Exception e)
175         {
176             throw new RuntimeException(e);
177         }
178     }
179     
180     /* ------------------------------------------------------------ */
181     /**
182      * @param path The path segment to add
183      * @return The contained resource (found first) in the collection of resources
184      */
185     @Override
186     public Resource addPath(String path) throws IOException, MalformedURLException
187     {
188         if(_resources==null)
189             throw new IllegalStateException("*resources* not set.");
190         
191         if(path==null)
192             throw new MalformedURLException();
193         
194         if(path.length()==0 || URIUtil.SLASH.equals(path))
195             return this;
196         
197         Resource resource=null;
198         ArrayList<Resource> resources = null;
199         int i=0;
200         for(; i<_resources.length; i++)
201         {
202             resource = _resources[i].addPath(path);  
203             if (resource.exists())
204             {
205                 if (resource.isDirectory())
206                     break;       
207                 return resource;
208             }
209         }  
210 
211         for(i++; i<_resources.length; i++)
212         {
213             Resource r = _resources[i].addPath(path); 
214             if (r.exists() && r.isDirectory())
215             {
216                 if (resource!=null)
217                 {
218                     resources = new ArrayList<Resource>();
219                     resources.add(resource);
220                     resource=null;
221                 }
222                 resources.add(r);
223             }
224         }
225 
226         if (resource!=null)
227             return resource;
228         if (resources!=null)
229             return new ResourceCollection(resources.toArray(new Resource[resources.size()]));
230         return null;
231     }
232     
233     /* ------------------------------------------------------------ */
234     /**
235      * @param path
236      * @return the resource(file) if found, returns a list of resource dirs if its a dir, else null.
237      * @throws IOException
238      * @throws MalformedURLException
239      */
240     protected Object findResource(String path) throws IOException, MalformedURLException
241     {        
242         Resource resource=null;
243         ArrayList<Resource> resources = null;
244         int i=0;
245         for(; i<_resources.length; i++)
246         {
247             resource = _resources[i].addPath(path);  
248             if (resource.exists())
249             {
250                 if (resource.isDirectory())
251                     break;
252                
253                 return resource;
254             }
255         }  
256 
257         for(i++; i<_resources.length; i++)
258         {
259             Resource r = _resources[i].addPath(path); 
260             if (r.exists() && r.isDirectory())
261             {
262                 if (resource!=null)
263                 {
264                     resources = new ArrayList<Resource>();
265                     resources.add(resource);
266                 }
267                 resources.add(r);
268             }
269         }
270         
271         if (resource!=null)
272             return resource;
273         if (resources!=null)
274             return resources;
275         return null;
276     }
277     
278     /* ------------------------------------------------------------ */
279     @Override
280     public boolean delete() throws SecurityException
281     {
282         throw new UnsupportedOperationException();
283     }
284     
285     /* ------------------------------------------------------------ */
286     @Override
287     public boolean exists()
288     {
289         if(_resources==null)
290             throw new IllegalStateException("*resources* not set.");
291         
292         return true;
293     }
294     
295     /* ------------------------------------------------------------ */
296     @Override
297     public File getFile() throws IOException
298     {
299         if(_resources==null)
300             throw new IllegalStateException("*resources* not set.");
301         
302         for(Resource r : _resources)
303         {
304             File f = r.getFile();
305             if(f!=null)
306                 return f;
307         }
308         return null;
309     }
310     
311     /* ------------------------------------------------------------ */
312     @Override
313     public InputStream getInputStream() throws IOException
314     {
315         if(_resources==null)
316             throw new IllegalStateException("*resources* not set.");
317         
318         for(Resource r : _resources)
319         {
320             InputStream is = r.getInputStream();
321             if(is!=null)
322                 return is;
323         }
324         return null;
325     }
326     
327     /* ------------------------------------------------------------ */
328     @Override
329     public String getName()
330     {
331         if(_resources==null)
332             throw new IllegalStateException("*resources* not set.");
333         
334         for(Resource r : _resources)
335         {
336             String name = r.getName();
337             if(name!=null)
338                 return name;
339         }
340         return null;
341     }
342     
343     /* ------------------------------------------------------------ */
344     @Override
345     public OutputStream getOutputStream() throws IOException, SecurityException
346     {
347         if(_resources==null)
348             throw new IllegalStateException("*resources* not set.");
349         
350         for(Resource r : _resources)
351         {
352             OutputStream os = r.getOutputStream();
353             if(os!=null)
354                 return os;
355         }
356         return null;
357     }
358     
359     /* ------------------------------------------------------------ */
360     @Override
361     public URL getURL()
362     {
363         if(_resources==null)
364             throw new IllegalStateException("*resources* not set.");
365         
366         for(Resource r : _resources)
367         {
368             URL url = r.getURL();
369             if(url!=null)
370                 return url;
371         }
372         return null;
373     }
374     
375     /* ------------------------------------------------------------ */
376     @Override
377     public boolean isDirectory()
378     {
379         if(_resources==null)
380             throw new IllegalStateException("*resources* not set.");
381         
382         return true;
383     }
384     
385     /* ------------------------------------------------------------ */
386     @Override
387     public long lastModified()
388     {
389         if(_resources==null)
390             throw new IllegalStateException("*resources* not set.");
391         
392         for(Resource r : _resources)
393         {
394             long lm = r.lastModified();
395             if (lm!=-1)
396                 return lm;
397         }
398         return -1;
399     }
400     
401     /* ------------------------------------------------------------ */
402     @Override
403     public long length()
404     {
405         return -1;
406     }    
407     
408     /* ------------------------------------------------------------ */
409     /**
410      * @return The list of resource names(merged) contained in the collection of resources.
411      */    
412     @Override
413     public String[] list()
414     {
415         if(_resources==null)
416             throw new IllegalStateException("*resources* not set.");
417         
418         HashSet<String> set = new HashSet<String>();
419         for(Resource r : _resources)
420         {
421             for(String s : r.list())
422                 set.add(s);
423         }
424         String[] result=set.toArray(new String[set.size()]);
425         Arrays.sort(result);
426         return result;
427     }
428     
429     /* ------------------------------------------------------------ */
430     @Override
431     public void release()
432     {
433         if(_resources==null)
434             throw new IllegalStateException("*resources* not set.");
435         
436         for(Resource r : _resources)
437             r.release();
438     }
439     
440     /* ------------------------------------------------------------ */
441     @Override
442     public boolean renameTo(Resource dest) throws SecurityException
443     {
444         throw new UnsupportedOperationException();
445     }
446 
447     /* ------------------------------------------------------------ */
448     @Override
449     public void copyTo(File destination)
450         throws IOException
451     {
452         for (int r=_resources.length;r-->0;)
453             _resources[r].copyTo(destination);
454     }
455     
456     /* ------------------------------------------------------------ */
457     /**
458      * @return the list of resources separated by a path separator
459      */
460     @Override
461     public String toString()
462     {
463         if(_resources==null)
464             return "[]";
465         
466         return String.valueOf(Arrays.asList(_resources));
467     }
468 
469     /* ------------------------------------------------------------ */
470     @Override
471     public boolean isContainedIn(Resource r) throws MalformedURLException
472     {
473         // TODO could look at implementing the semantic of is this collection a subset of the Resource r?
474         return false;
475     }
476 
477 }