View Javadoc

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