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