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     @Override
183     public Resource addPath(String path) throws IOException, MalformedURLException
184     {
185         if(_resources==null)
186             throw new IllegalStateException("*resources* not set.");
187         
188         if(path==null)
189             throw new MalformedURLException();
190         
191         if(path.length()==0 || URIUtil.SLASH.equals(path))
192             return this;
193         
194         Resource resource=null;
195         ArrayList<Resource> resources = null;
196         int i=0;
197         for(; i<_resources.length; i++)
198         {
199             resource = _resources[i].addPath(path);  
200             if (resource.exists())
201             {
202                 if (resource.isDirectory())
203                     break;       
204                 return resource;
205             }
206         }  
207 
208         for(i++; i<_resources.length; i++)
209         {
210             Resource r = _resources[i].addPath(path); 
211             if (r.exists() && r.isDirectory())
212             {
213                 if (resource!=null)
214                 {
215                     resources = new ArrayList<Resource>();
216                     resources.add(resource);
217                     resource=null;
218                 }
219                 resources.add(r);
220             }
221         }
222 
223         if (resource!=null)
224             return resource;
225         if (resources!=null)
226             return new ResourceCollection(resources.toArray(new Resource[resources.size()]));
227         return null;
228     }
229     
230     /* ------------------------------------------------------------ */
231     /**
232      * @param path
233      * @return the resource(file) if found, returns a list of resource dirs if its a dir, else null.
234      * @throws IOException
235      * @throws MalformedURLException
236      */
237     protected Object findResource(String path) throws IOException, MalformedURLException
238     {        
239         Resource resource=null;
240         ArrayList<Resource> resources = null;
241         int i=0;
242         for(; i<_resources.length; i++)
243         {
244             resource = _resources[i].addPath(path);  
245             if (resource.exists())
246             {
247                 if (resource.isDirectory())
248                     break;
249                
250                 return resource;
251             }
252         }  
253 
254         for(i++; i<_resources.length; i++)
255         {
256             Resource r = _resources[i].addPath(path); 
257             if (r.exists() && r.isDirectory())
258             {
259                 if (resource!=null)
260                 {
261                     resources = new ArrayList<Resource>();
262                     resources.add(resource);
263                 }
264                 resources.add(r);
265             }
266         }
267         
268         if (resource!=null)
269             return resource;
270         if (resources!=null)
271             return resources;
272         return null;
273     }
274     
275     /* ------------------------------------------------------------ */
276     @Override
277     public boolean delete() throws SecurityException
278     {
279         throw new UnsupportedOperationException();
280     }
281     
282     /* ------------------------------------------------------------ */
283     @Override
284     public boolean exists()
285     {
286         if(_resources==null)
287             throw new IllegalStateException("*resources* not set.");
288         
289         return true;
290     }
291     
292     /* ------------------------------------------------------------ */
293     @Override
294     public File getFile() throws IOException
295     {
296         if(_resources==null)
297             throw new IllegalStateException("*resources* not set.");
298         
299         for(Resource r : _resources)
300         {
301             File f = r.getFile();
302             if(f!=null)
303                 return f;
304         }
305         return null;
306     }
307     
308     /* ------------------------------------------------------------ */
309     @Override
310     public InputStream getInputStream() throws IOException
311     {
312         if(_resources==null)
313             throw new IllegalStateException("*resources* not set.");
314         
315         for(Resource r : _resources)
316         {
317             InputStream is = r.getInputStream();
318             if(is!=null)
319                 return is;
320         }
321         return null;
322     }
323     
324     /* ------------------------------------------------------------ */
325     @Override
326     public String getName()
327     {
328         if(_resources==null)
329             throw new IllegalStateException("*resources* not set.");
330         
331         for(Resource r : _resources)
332         {
333             String name = r.getName();
334             if(name!=null)
335                 return name;
336         }
337         return null;
338     }
339     
340     /* ------------------------------------------------------------ */
341     @Override
342     public OutputStream getOutputStream() throws IOException, SecurityException
343     {
344         if(_resources==null)
345             throw new IllegalStateException("*resources* not set.");
346         
347         for(Resource r : _resources)
348         {
349             OutputStream os = r.getOutputStream();
350             if(os!=null)
351                 return os;
352         }
353         return null;
354     }
355     
356     /* ------------------------------------------------------------ */
357     @Override
358     public URL getURL()
359     {
360         if(_resources==null)
361             throw new IllegalStateException("*resources* not set.");
362         
363         for(Resource r : _resources)
364         {
365             URL url = r.getURL();
366             if(url!=null)
367                 return url;
368         }
369         return null;
370     }
371     
372     /* ------------------------------------------------------------ */
373     @Override
374     public boolean isDirectory()
375     {
376         if(_resources==null)
377             throw new IllegalStateException("*resources* not set.");
378         
379         return true;
380     }
381     
382     /* ------------------------------------------------------------ */
383     @Override
384     public long lastModified()
385     {
386         if(_resources==null)
387             throw new IllegalStateException("*resources* not set.");
388         
389         for(Resource r : _resources)
390         {
391             long lm = r.lastModified();
392             if (lm!=-1)
393                 return lm;
394         }
395         return -1;
396     }
397     
398     /* ------------------------------------------------------------ */
399     @Override
400     public long length()
401     {
402         return -1;
403     }    
404     
405     /* ------------------------------------------------------------ */
406     /**
407      * @return The list of resource names(merged) contained in the collection of resources.
408      */    
409     @Override
410     public String[] list()
411     {
412         if(_resources==null)
413             throw new IllegalStateException("*resources* not set.");
414         
415         HashSet<String> set = new HashSet<String>();
416         for(Resource r : _resources)
417         {
418             for(String s : r.list())
419                 set.add(s);
420         }
421         String[] result=set.toArray(new String[set.size()]);
422         Arrays.sort(result);
423         return result;
424     }
425     
426     /* ------------------------------------------------------------ */
427     @Override
428     public void release()
429     {
430         if(_resources==null)
431             throw new IllegalStateException("*resources* not set.");
432         
433         for(Resource r : _resources)
434             r.release();
435     }
436     
437     /* ------------------------------------------------------------ */
438     @Override
439     public boolean renameTo(Resource dest) throws SecurityException
440     {
441         throw new UnsupportedOperationException();
442     }
443 
444     /* ------------------------------------------------------------ */
445     @Override
446     public void copyTo(File destination)
447         throws IOException
448     {
449         for (int r=_resources.length;r-->0;)
450             _resources[r].copyTo(destination);
451     }
452     
453     /* ------------------------------------------------------------ */
454     /**
455      * @return the list of resources separated by a path separator
456      */
457     @Override
458     public String toString()
459     {
460         if(_resources==null)
461             return "";
462         
463         StringBuilder buffer = new StringBuilder();
464         for(Resource r : _resources)
465             buffer.append(r.toString()).append(';');
466         return buffer.toString();
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 }