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