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(Exception e)
118         {
119             throw new RuntimeException(e);
120         }
121     }
122     
123     /* ------------------------------------------------------------ */
124     /**
125      * 
126      * @param csvResources Comma separated values
127      */
128     public void setResources(String csvResources)
129     {
130         if(_resources!=null)
131             throw new IllegalStateException("*resources* already set.");
132         
133         if(csvResources==null)
134             throw new IllegalArgumentException("*csvResources* must not be null.");
135         
136         StringTokenizer tokenizer = new StringTokenizer(csvResources, ",;");
137         int len = tokenizer.countTokens();
138         if(len==0)
139             throw new IllegalArgumentException("arg *resources* must be one or more resources.");
140         
141         _resources = new Resource[len];
142         try
143         {            
144             for(int i=0; tokenizer.hasMoreTokens(); i++)
145             {
146                 _resources[i] = Resource.newResource(tokenizer.nextToken().trim());
147                 if(!_resources[i].exists() || !_resources[i].isDirectory())
148                     throw new IllegalArgumentException(_resources[i] + " is not an existing directory.");
149             }
150         }
151         catch(Exception e)
152         {
153             throw new RuntimeException(e);
154         }
155     }
156     
157     /* ------------------------------------------------------------ */
158     /**
159      * 
160      * @param csvResources Comma separated values
161      */
162     public void setResourcesAsCSV(String csvResources)
163     {
164         setResources(csvResources);
165     }
166     
167     /* ------------------------------------------------------------ */
168     /**
169      * 
170      * @return the resource array
171      */
172     public Resource[] getResources()
173     {
174         return _resources;
175     }
176     
177     /* ------------------------------------------------------------ */
178     /**
179      * @param path The path segment to add
180      * @return The contained resource (found first) in the collection of resources
181      */
182     public Resource addPath(String path) throws IOException, MalformedURLException
183     {
184         if(_resources==null)
185             throw new IllegalStateException("*resources* not set.");
186         
187         if(path==null)
188             throw new MalformedURLException();
189         
190         if(path.length()==0 || URIUtil.SLASH.equals(path))
191             return this;
192         
193         Resource resource=null;
194         ArrayList<Resource> resources = null;
195         int i=0;
196         for(; i<_resources.length; i++)
197         {
198             resource = _resources[i].addPath(path);  
199             if (resource.exists())
200             {
201                 if (resource.isDirectory())
202                     break;       
203                 return resource;
204             }
205         }  
206 
207         for(i++; i<_resources.length; i++)
208         {
209             Resource r = _resources[i].addPath(path); 
210             if (r.exists() && r.isDirectory())
211             {
212                 if (resource!=null)
213                 {
214                     resources = new ArrayList<Resource>();
215                     resources.add(resource);
216                     resource=null;
217                 }
218                 resources.add(r);
219             }
220         }
221 
222         if (resource!=null)
223             return resource;
224         if (resources!=null)
225             return new ResourceCollection(resources.toArray(new Resource[resources.size()]));
226         return null;
227     }
228     
229     /* ------------------------------------------------------------ */
230     /**
231      * @param path
232      * @return the resource(file) if found, returns a list of resource dirs if its a dir, else null.
233      * @throws IOException
234      * @throws MalformedURLException
235      */
236     protected Object findResource(String path) throws IOException, MalformedURLException
237     {        
238         Resource resource=null;
239         ArrayList<Resource> resources = null;
240         int i=0;
241         for(; i<_resources.length; i++)
242         {
243             resource = _resources[i].addPath(path);  
244             if (resource.exists())
245             {
246                 if (resource.isDirectory())
247                     break;
248                
249                 return resource;
250             }
251         }  
252 
253         for(i++; i<_resources.length; i++)
254         {
255             Resource r = _resources[i].addPath(path); 
256             if (r.exists() && r.isDirectory())
257             {
258                 if (resource!=null)
259                 {
260                     resources = new ArrayList<Resource>();
261                     resources.add(resource);
262                 }
263                 resources.add(r);
264             }
265         }
266         
267         if (resource!=null)
268             return resource;
269         if (resources!=null)
270             return resources;
271         return null;
272     }
273     
274     /* ------------------------------------------------------------ */
275     public boolean delete() throws SecurityException
276     {
277         throw new UnsupportedOperationException();
278     }
279     
280     /* ------------------------------------------------------------ */
281     public boolean exists()
282     {
283         if(_resources==null)
284             throw new IllegalStateException("*resources* not set.");
285         
286         return true;
287     }
288     
289     /* ------------------------------------------------------------ */
290     public File getFile() throws IOException
291     {
292         if(_resources==null)
293             throw new IllegalStateException("*resources* not set.");
294         
295         for(Resource r : _resources)
296         {
297             File f = r.getFile();
298             if(f!=null)
299                 return f;
300         }
301         return null;
302     }
303     
304     /* ------------------------------------------------------------ */
305     public InputStream getInputStream() throws IOException
306     {
307         if(_resources==null)
308             throw new IllegalStateException("*resources* not set.");
309         
310         for(Resource r : _resources)
311         {
312             InputStream is = r.getInputStream();
313             if(is!=null)
314                 return is;
315         }
316         return null;
317     }
318     
319     /* ------------------------------------------------------------ */
320     public String getName()
321     {
322         if(_resources==null)
323             throw new IllegalStateException("*resources* not set.");
324         
325         for(Resource r : _resources)
326         {
327             String name = r.getName();
328             if(name!=null)
329                 return name;
330         }
331         return null;
332     }
333     
334     /* ------------------------------------------------------------ */
335     public OutputStream getOutputStream() throws IOException, SecurityException
336     {
337         if(_resources==null)
338             throw new IllegalStateException("*resources* not set.");
339         
340         for(Resource r : _resources)
341         {
342             OutputStream os = r.getOutputStream();
343             if(os!=null)
344                 return os;
345         }
346         return null;
347     }
348     
349     /* ------------------------------------------------------------ */
350     public URL getURL()
351     {
352         if(_resources==null)
353             throw new IllegalStateException("*resources* not set.");
354         
355         for(Resource r : _resources)
356         {
357             URL url = r.getURL();
358             if(url!=null)
359                 return url;
360         }
361         return null;
362     }
363     
364     /* ------------------------------------------------------------ */
365     public boolean isDirectory()
366     {
367         if(_resources==null)
368             throw new IllegalStateException("*resources* not set.");
369         
370         return true;
371     }
372     
373     /* ------------------------------------------------------------ */
374     public long lastModified()
375     {
376         if(_resources==null)
377             throw new IllegalStateException("*resources* not set.");
378         
379         for(Resource r : _resources)
380         {
381             long lm = r.lastModified();
382             if (lm!=-1)
383                 return lm;
384         }
385         return -1;
386     }
387     
388     /* ------------------------------------------------------------ */
389     public long length()
390     {
391         return -1;
392     }    
393     
394     /* ------------------------------------------------------------ */
395     /**
396      * @return The list of resource names(merged) contained in the collection of resources.
397      */    
398     public String[] list()
399     {
400         if(_resources==null)
401             throw new IllegalStateException("*resources* not set.");
402         
403         HashSet<String> set = new HashSet<String>();
404         for(Resource r : _resources)
405         {
406             for(String s : r.list())
407                 set.add(s);
408         }
409         String[] result=set.toArray(new String[set.size()]);
410         Arrays.sort(result);
411         return result;
412     }
413     
414     /* ------------------------------------------------------------ */
415     public void release()
416     {
417         if(_resources==null)
418             throw new IllegalStateException("*resources* not set.");
419         
420         for(Resource r : _resources)
421             r.release();
422     }
423     
424     /* ------------------------------------------------------------ */
425     @Override
426     public boolean renameTo(Resource dest) throws SecurityException
427     {
428         throw new UnsupportedOperationException();
429     }
430 
431     /* ------------------------------------------------------------ */
432     @Override
433     public void copyTo(File destination)
434         throws IOException
435     {
436         for (int r=_resources.length;r-->0;)
437             _resources[r].copyTo(destination);
438     }
439     
440     /* ------------------------------------------------------------ */
441     /**
442      * @return the list of resources separated by a path separator
443      */
444     @Override
445     public String toString()
446     {
447         if(_resources==null)
448             return "";
449         
450         StringBuilder buffer = new StringBuilder();
451         for(Resource r : _resources)
452             buffer.append(r.toString()).append(';');
453         return buffer.toString();
454     }
455 
456     /* ------------------------------------------------------------ */
457     @Override
458     public boolean isContainedIn(Resource r) throws MalformedURLException
459     {
460         // TODO could look at implementing the semantic of is this collection a subset of the Resource r?
461         return false;
462     }
463 
464 }