KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > naming > resources > FileDirContext


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.naming.resources;
20
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Arrays JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.util.Hashtable JavaDoc;
30
31 import javax.naming.NameAlreadyBoundException JavaDoc;
32 import javax.naming.NamingEnumeration JavaDoc;
33 import javax.naming.NamingException JavaDoc;
34 import javax.naming.OperationNotSupportedException JavaDoc;
35 import javax.naming.directory.Attributes JavaDoc;
36 import javax.naming.directory.DirContext JavaDoc;
37 import javax.naming.directory.ModificationItem JavaDoc;
38 import javax.naming.directory.SearchControls JavaDoc;
39
40 import org.apache.naming.NamingContextBindingsEnumeration;
41 import org.apache.naming.NamingContextEnumeration;
42 import org.apache.naming.NamingEntry;
43
44 /**
45  * Filesystem Directory Context implementation helper class.
46  *
47  * @author Remy Maucherat
48  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
49  */

50
51 public class FileDirContext extends BaseDirContext {
52
53     private static org.apache.commons.logging.Log log=
54         org.apache.commons.logging.LogFactory.getLog( FileDirContext.class );
55
56     // -------------------------------------------------------------- Constants
57

58
59     /**
60      * The descriptive information string for this implementation.
61      */

62     protected static final int BUFFER_SIZE = 2048;
63
64
65     // ----------------------------------------------------------- Constructors
66

67
68     /**
69      * Builds a file directory context using the given environment.
70      */

71     public FileDirContext() {
72         super();
73     }
74
75
76     /**
77      * Builds a file directory context using the given environment.
78      */

79     public FileDirContext(Hashtable JavaDoc env) {
80         super(env);
81     }
82
83
84     // ----------------------------------------------------- Instance Variables
85

86
87     /**
88      * The document base directory.
89      */

90     protected File JavaDoc base = null;
91
92
93     /**
94      * Absolute normalized filename of the base.
95      */

96     protected String JavaDoc absoluteBase = null;
97
98
99     /**
100      * Case sensitivity.
101      */

102     protected boolean caseSensitive = true;
103
104
105     /**
106      * Allow linking.
107      */

108     protected boolean allowLinking = false;
109
110
111     // ------------------------------------------------------------- Properties
112

113
114     /**
115      * Set the document root.
116      *
117      * @param docBase The new document root
118      *
119      * @exception IllegalArgumentException if the specified value is not
120      * supported by this implementation
121      * @exception IllegalArgumentException if this would create a
122      * malformed URL
123      */

124     public void setDocBase(String JavaDoc docBase) {
125
126     // Validate the format of the proposed document root
127
if (docBase == null)
128         throw new IllegalArgumentException JavaDoc
129         (sm.getString("resources.null"));
130
131     // Calculate a File object referencing this document base directory
132
base = new File JavaDoc(docBase);
133         try {
134             base = base.getCanonicalFile();
135         } catch (IOException JavaDoc e) {
136             // Ignore
137
}
138
139     // Validate that the document base is an existing directory
140
if (!base.exists() || !base.isDirectory() || !base.canRead())
141         throw new IllegalArgumentException JavaDoc
142         (sm.getString("fileResources.base", docBase));
143         this.absoluteBase = base.getAbsolutePath();
144         super.setDocBase(docBase);
145
146     }
147
148
149     /**
150      * Set case sensitivity.
151      */

152     public void setCaseSensitive(boolean caseSensitive) {
153         this.caseSensitive = caseSensitive;
154     }
155
156
157     /**
158      * Is case sensitive ?
159      */

160     public boolean isCaseSensitive() {
161         return caseSensitive;
162     }
163
164
165     /**
166      * Set allow linking.
167      */

168     public void setAllowLinking(boolean allowLinking) {
169         this.allowLinking = allowLinking;
170     }
171
172
173     /**
174      * Is linking allowed.
175      */

176     public boolean getAllowLinking() {
177         return allowLinking;
178     }
179
180
181     // --------------------------------------------------------- Public Methods
182

183
184     /**
185      * Release any resources allocated for this directory context.
186      */

187     public void release() {
188         super.release();
189     }
190
191
192     // -------------------------------------------------------- Context Methods
193

194
195     /**
196      * Retrieves the named object.
197      *
198      * @param name the name of the object to look up
199      * @return the object bound to name
200      * @exception NamingException if a naming exception is encountered
201      */

202     public Object JavaDoc lookup(String JavaDoc name)
203         throws NamingException JavaDoc {
204         Object JavaDoc result = null;
205         File JavaDoc file = file(name);
206
207         if (file == null)
208             throw new NamingException JavaDoc
209                 (sm.getString("resources.notFound", name));
210
211         if (file.isDirectory()) {
212             FileDirContext tempContext = new FileDirContext(env);
213             tempContext.setDocBase(file.getPath());
214             tempContext.setAllowLinking(getAllowLinking());
215             tempContext.setCaseSensitive(isCaseSensitive());
216             result = tempContext;
217         } else {
218             result = new FileResource(file);
219         }
220
221         return result;
222
223     }
224
225
226     /**
227      * Unbinds the named object. Removes the terminal atomic name in name
228      * from the target context--that named by all but the terminal atomic
229      * part of name.
230      * <p>
231      * This method is idempotent. It succeeds even if the terminal atomic
232      * name is not bound in the target context, but throws
233      * NameNotFoundException if any of the intermediate contexts do not exist.
234      *
235      * @param name the name to bind; may not be empty
236      * @exception NameNotFoundException if an intermediate context does not
237      * exist
238      * @exception NamingException if a naming exception is encountered
239      */

240     public void unbind(String JavaDoc name)
241         throws NamingException JavaDoc {
242
243         File JavaDoc file = file(name);
244
245         if (file == null)
246             throw new NamingException JavaDoc
247                 (sm.getString("resources.notFound", name));
248
249         if (!file.delete())
250             throw new NamingException JavaDoc
251                 (sm.getString("resources.unbindFailed", name));
252
253     }
254
255
256     /**
257      * Binds a new name to the object bound to an old name, and unbinds the
258      * old name. Both names are relative to this context. Any attributes
259      * associated with the old name become associated with the new name.
260      * Intermediate contexts of the old name are not changed.
261      *
262      * @param oldName the name of the existing binding; may not be empty
263      * @param newName the name of the new binding; may not be empty
264      * @exception NameAlreadyBoundException if newName is already bound
265      * @exception NamingException if a naming exception is encountered
266      */

267     public void rename(String JavaDoc oldName, String JavaDoc newName)
268         throws NamingException JavaDoc {
269
270         File JavaDoc file = file(oldName);
271
272         if (file == null)
273             throw new NamingException JavaDoc
274                 (sm.getString("resources.notFound", oldName));
275
276         File JavaDoc newFile = new File JavaDoc(base, newName);
277
278         file.renameTo(newFile);
279
280     }
281
282
283     /**
284      * Enumerates the names bound in the named context, along with the class
285      * names of objects bound to them. The contents of any subcontexts are
286      * not included.
287      * <p>
288      * If a binding is added to or removed from this context, its effect on
289      * an enumeration previously returned is undefined.
290      *
291      * @param name the name of the context to list
292      * @return an enumeration of the names and class names of the bindings in
293      * this context. Each element of the enumeration is of type NameClassPair.
294      * @exception NamingException if a naming exception is encountered
295      */

296     public NamingEnumeration JavaDoc list(String JavaDoc name)
297         throws NamingException JavaDoc {
298
299         File JavaDoc file = file(name);
300
301         if (file == null)
302             throw new NamingException JavaDoc
303                 (sm.getString("resources.notFound", name));
304
305         return new NamingContextEnumeration(list(file).iterator());
306
307     }
308
309
310     /**
311      * Enumerates the names bound in the named context, along with the
312      * objects bound to them. The contents of any subcontexts are not
313      * included.
314      * <p>
315      * If a binding is added to or removed from this context, its effect on
316      * an enumeration previously returned is undefined.
317      *
318      * @param name the name of the context to list
319      * @return an enumeration of the bindings in this context.
320      * Each element of the enumeration is of type Binding.
321      * @exception NamingException if a naming exception is encountered
322      */

323     public NamingEnumeration JavaDoc listBindings(String JavaDoc name)
324         throws NamingException JavaDoc {
325
326         File JavaDoc file = file(name);
327
328         if (file == null)
329             throw new NamingException JavaDoc
330                 (sm.getString("resources.notFound", name));
331
332         return new NamingContextBindingsEnumeration(list(file).iterator(),
333                 this);
334
335     }
336
337
338     /**
339      * Destroys the named context and removes it from the namespace. Any
340      * attributes associated with the name are also removed. Intermediate
341      * contexts are not destroyed.
342      * <p>
343      * This method is idempotent. It succeeds even if the terminal atomic
344      * name is not bound in the target context, but throws
345      * NameNotFoundException if any of the intermediate contexts do not exist.
346      *
347      * In a federated naming system, a context from one naming system may be
348      * bound to a name in another. One can subsequently look up and perform
349      * operations on the foreign context using a composite name. However, an
350      * attempt destroy the context using this composite name will fail with
351      * NotContextException, because the foreign context is not a "subcontext"
352      * of the context in which it is bound. Instead, use unbind() to remove
353      * the binding of the foreign context. Destroying the foreign context
354      * requires that the destroySubcontext() be performed on a context from
355      * the foreign context's "native" naming system.
356      *
357      * @param name the name of the context to be destroyed; may not be empty
358      * @exception NameNotFoundException if an intermediate context does not
359      * exist
360      * @exception NotContextException if the name is bound but does not name
361      * a context, or does not name a context of the appropriate type
362      */

363     public void destroySubcontext(String JavaDoc name)
364         throws NamingException JavaDoc {
365         unbind(name);
366     }
367
368
369     /**
370      * Retrieves the named object, following links except for the terminal
371      * atomic component of the name. If the object bound to name is not a
372      * link, returns the object itself.
373      *
374      * @param name the name of the object to look up
375      * @return the object bound to name, not following the terminal link
376      * (if any).
377      * @exception NamingException if a naming exception is encountered
378      */

379     public Object JavaDoc lookupLink(String JavaDoc name)
380         throws NamingException JavaDoc {
381         // Note : Links are not supported
382
return lookup(name);
383     }
384
385
386     /**
387      * Retrieves the full name of this context within its own namespace.
388      * <p>
389      * Many naming services have a notion of a "full name" for objects in
390      * their respective namespaces. For example, an LDAP entry has a
391      * distinguished name, and a DNS record has a fully qualified name. This
392      * method allows the client application to retrieve this name. The string
393      * returned by this method is not a JNDI composite name and should not be
394      * passed directly to context methods. In naming systems for which the
395      * notion of full name does not make sense,
396      * OperationNotSupportedException is thrown.
397      *
398      * @return this context's name in its own namespace; never null
399      * @exception OperationNotSupportedException if the naming system does
400      * not have the notion of a full name
401      * @exception NamingException if a naming exception is encountered
402      */

403     public String JavaDoc getNameInNamespace()
404         throws NamingException JavaDoc {
405         return docBase;
406     }
407
408
409     // ----------------------------------------------------- DirContext Methods
410

411
412     /**
413      * Retrieves selected attributes associated with a named object.
414      * See the class description regarding attribute models, attribute type
415      * names, and operational attributes.
416      *
417      * @return the requested attributes; never null
418      * @param name the name of the object from which to retrieve attributes
419      * @param attrIds the identifiers of the attributes to retrieve. null
420      * indicates that all attributes should be retrieved; an empty array
421      * indicates that none should be retrieved
422      * @exception NamingException if a naming exception is encountered
423      */

424     public Attributes JavaDoc getAttributes(String JavaDoc name, String JavaDoc[] attrIds)
425         throws NamingException JavaDoc {
426
427         // Building attribute list
428
File JavaDoc file = file(name);
429
430         if (file == null)
431             throw new NamingException JavaDoc
432                 (sm.getString("resources.notFound", name));
433
434         return new FileResourceAttributes(file);
435
436     }
437
438
439     /**
440      * Modifies the attributes associated with a named object. The order of
441      * the modifications is not specified. Where possible, the modifications
442      * are performed atomically.
443      *
444      * @param name the name of the object whose attributes will be updated
445      * @param mod_op the modification operation, one of: ADD_ATTRIBUTE,
446      * REPLACE_ATTRIBUTE, REMOVE_ATTRIBUTE
447      * @param attrs the attributes to be used for the modification; may not
448      * be null
449      * @exception AttributeModificationException if the modification cannot be
450      * completed successfully
451      * @exception NamingException if a naming exception is encountered
452      */

453     public void modifyAttributes(String JavaDoc name, int mod_op, Attributes JavaDoc attrs)
454         throws NamingException JavaDoc {
455
456     }
457
458
459     /**
460      * Modifies the attributes associated with a named object using an an
461      * ordered list of modifications. The modifications are performed in the
462      * order specified. Each modification specifies a modification operation
463      * code and an attribute on which to operate. Where possible, the
464      * modifications are performed atomically.
465      *
466      * @param name the name of the object whose attributes will be updated
467      * @param mods an ordered sequence of modifications to be performed; may
468      * not be null
469      * @exception AttributeModificationException if the modification cannot be
470      * completed successfully
471      * @exception NamingException if a naming exception is encountered
472      */

473     public void modifyAttributes(String JavaDoc name, ModificationItem JavaDoc[] mods)
474         throws NamingException JavaDoc {
475
476     }
477
478
479     /**
480      * Binds a name to an object, along with associated attributes. If attrs
481      * is null, the resulting binding will have the attributes associated
482      * with obj if obj is a DirContext, and no attributes otherwise. If attrs
483      * is non-null, the resulting binding will have attrs as its attributes;
484      * any attributes associated with obj are ignored.
485      *
486      * @param name the name to bind; may not be empty
487      * @param obj the object to bind; possibly null
488      * @param attrs the attributes to associate with the binding
489      * @exception NameAlreadyBoundException if name is already bound
490      * @exception InvalidAttributesException if some "mandatory" attributes
491      * of the binding are not supplied
492      * @exception NamingException if a naming exception is encountered
493      */

494     public void bind(String JavaDoc name, Object JavaDoc obj, Attributes JavaDoc attrs)
495         throws NamingException JavaDoc {
496
497         // Note: No custom attributes allowed
498

499         File JavaDoc file = new File JavaDoc(base, name);
500         if (file.exists())
501             throw new NameAlreadyBoundException JavaDoc
502                 (sm.getString("resources.alreadyBound", name));
503
504         rebind(name, obj, attrs);
505
506     }
507
508
509     /**
510      * Binds a name to an object, along with associated attributes,
511      * overwriting any existing binding. If attrs is null and obj is a
512      * DirContext, the attributes from obj are used. If attrs is null and obj
513      * is not a DirContext, any existing attributes associated with the object
514      * already bound in the directory remain unchanged. If attrs is non-null,
515      * any existing attributes associated with the object already bound in
516      * the directory are removed and attrs is associated with the named
517      * object. If obj is a DirContext and attrs is non-null, the attributes
518      * of obj are ignored.
519      *
520      * @param name the name to bind; may not be empty
521      * @param obj the object to bind; possibly null
522      * @param attrs the attributes to associate with the binding
523      * @exception InvalidAttributesException if some "mandatory" attributes
524      * of the binding are not supplied
525      * @exception NamingException if a naming exception is encountered
526      */

527     public void rebind(String JavaDoc name, Object JavaDoc obj, Attributes JavaDoc attrs)
528         throws NamingException JavaDoc {
529
530         // Note: No custom attributes allowed
531
// Check obj type
532

533         File JavaDoc file = new File JavaDoc(base, name);
534
535         InputStream JavaDoc is = null;
536         if (obj instanceof Resource) {
537             try {
538                 is = ((Resource) obj).streamContent();
539             } catch (IOException JavaDoc e) {
540             }
541         } else if (obj instanceof InputStream JavaDoc) {
542             is = (InputStream JavaDoc) obj;
543         } else if (obj instanceof DirContext JavaDoc) {
544             if (file.exists()) {
545                 if (!file.delete())
546                     throw new NamingException JavaDoc
547                         (sm.getString("resources.bindFailed", name));
548             }
549             if (!file.mkdir())
550                 throw new NamingException JavaDoc
551                     (sm.getString("resources.bindFailed", name));
552         }
553         if (is == null)
554             throw new NamingException JavaDoc
555                 (sm.getString("resources.bindFailed", name));
556
557         // Open os
558

559         try {
560             FileOutputStream JavaDoc os = null;
561             byte buffer[] = new byte[BUFFER_SIZE];
562             int len = -1;
563             try {
564                 os = new FileOutputStream JavaDoc(file);
565                 while (true) {
566                     len = is.read(buffer);
567                     if (len == -1)
568                         break;
569                     os.write(buffer, 0, len);
570                 }
571             } finally {
572                 if (os != null)
573                     os.close();
574                 is.close();
575             }
576         } catch (IOException JavaDoc e) {
577             throw new NamingException JavaDoc
578                 (sm.getString("resources.bindFailed", e));
579         }
580
581     }
582
583
584     /**
585      * Creates and binds a new context, along with associated attributes.
586      * This method creates a new subcontext with the given name, binds it in
587      * the target context (that named by all but terminal atomic component of
588      * the name), and associates the supplied attributes with the newly
589      * created object. All intermediate and target contexts must already
590      * exist. If attrs is null, this method is equivalent to
591      * Context.createSubcontext().
592      *
593      * @param name the name of the context to create; may not be empty
594      * @param attrs the attributes to associate with the newly created context
595      * @return the newly created context
596      * @exception NameAlreadyBoundException if the name is already bound
597      * @exception InvalidAttributesException if attrs does not contain all
598      * the mandatory attributes required for creation
599      * @exception NamingException if a naming exception is encountered
600      */

601     public DirContext JavaDoc createSubcontext(String JavaDoc name, Attributes JavaDoc attrs)
602         throws NamingException JavaDoc {
603
604         File JavaDoc file = new File JavaDoc(base, name);
605         if (file.exists())
606             throw new NameAlreadyBoundException JavaDoc
607                 (sm.getString("resources.alreadyBound", name));
608         if (!file.mkdir())
609             throw new NamingException JavaDoc
610                 (sm.getString("resources.bindFailed", name));
611         return (DirContext JavaDoc) lookup(name);
612
613     }
614
615
616     /**
617      * Retrieves the schema associated with the named object. The schema
618      * describes rules regarding the structure of the namespace and the
619      * attributes stored within it. The schema specifies what types of
620      * objects can be added to the directory and where they can be added;
621      * what mandatory and optional attributes an object can have. The range
622      * of support for schemas is directory-specific.
623      *
624      * @param name the name of the object whose schema is to be retrieved
625      * @return the schema associated with the context; never null
626      * @exception OperationNotSupportedException if schema not supported
627      * @exception NamingException if a naming exception is encountered
628      */

629     public DirContext JavaDoc getSchema(String JavaDoc name)
630         throws NamingException JavaDoc {
631         throw new OperationNotSupportedException JavaDoc();
632     }
633
634
635     /**
636      * Retrieves a context containing the schema objects of the named
637      * object's class definitions.
638      *
639      * @param name the name of the object whose object class definition is to
640      * be retrieved
641      * @return the DirContext containing the named object's class
642      * definitions; never null
643      * @exception OperationNotSupportedException if schema not supported
644      * @exception NamingException if a naming exception is encountered
645      */

646     public DirContext JavaDoc getSchemaClassDefinition(String JavaDoc name)
647         throws NamingException JavaDoc {
648         throw new OperationNotSupportedException JavaDoc();
649     }
650
651
652     /**
653      * Searches in a single context for objects that contain a specified set
654      * of attributes, and retrieves selected attributes. The search is
655      * performed using the default SearchControls settings.
656      *
657      * @param name the name of the context to search
658      * @param matchingAttributes the attributes to search for. If empty or
659      * null, all objects in the target context are returned.
660      * @param attributesToReturn the attributes to return. null indicates
661      * that all attributes are to be returned; an empty array indicates that
662      * none are to be returned.
663      * @return a non-null enumeration of SearchResult objects. Each
664      * SearchResult contains the attributes identified by attributesToReturn
665      * and the name of the corresponding object, named relative to the
666      * context named by name.
667      * @exception NamingException if a naming exception is encountered
668      */

669     public NamingEnumeration JavaDoc search(String JavaDoc name, Attributes JavaDoc matchingAttributes,
670                                     String JavaDoc[] attributesToReturn)
671         throws NamingException JavaDoc {
672         return null;
673     }
674
675
676     /**
677      * Searches in a single context for objects that contain a specified set
678      * of attributes. This method returns all the attributes of such objects.
679      * It is equivalent to supplying null as the atributesToReturn parameter
680      * to the method search(Name, Attributes, String[]).
681      *
682      * @param name the name of the context to search
683      * @param matchingAttributes the attributes to search for. If empty or
684      * null, all objects in the target context are returned.
685      * @return a non-null enumeration of SearchResult objects. Each
686      * SearchResult contains the attributes identified by attributesToReturn
687      * and the name of the corresponding object, named relative to the
688      * context named by name.
689      * @exception NamingException if a naming exception is encountered
690      */

691     public NamingEnumeration JavaDoc search(String JavaDoc name, Attributes JavaDoc matchingAttributes)
692         throws NamingException JavaDoc {
693         return null;
694     }
695
696
697     /**
698      * Searches in the named context or object for entries that satisfy the
699      * given search filter. Performs the search as specified by the search
700      * controls.
701      *
702      * @param name the name of the context or object to search
703      * @param filter the filter expression to use for the search; may not be
704      * null
705      * @param cons the search controls that control the search. If null,
706      * the default search controls are used (equivalent to
707      * (new SearchControls())).
708      * @return an enumeration of SearchResults of the objects that satisfy
709      * the filter; never null
710      * @exception InvalidSearchFilterException if the search filter specified
711      * is not supported or understood by the underlying directory
712      * @exception InvalidSearchControlsException if the search controls
713      * contain invalid settings
714      * @exception NamingException if a naming exception is encountered
715      */

716     public NamingEnumeration JavaDoc search(String JavaDoc name, String JavaDoc filter,
717                                     SearchControls JavaDoc cons)
718         throws NamingException JavaDoc {
719         return null;
720     }
721
722
723     /**
724      * Searches in the named context or object for entries that satisfy the
725      * given search filter. Performs the search as specified by the search
726      * controls.
727      *
728      * @param name the name of the context or object to search
729      * @param filterExpr the filter expression to use for the search.
730      * The expression may contain variables of the form "{i}" where i is a
731      * nonnegative integer. May not be null.
732      * @param filterArgs the array of arguments to substitute for the
733      * variables in filterExpr. The value of filterArgs[i] will replace each
734      * occurrence of "{i}". If null, equivalent to an empty array.
735      * @param cons the search controls that control the search. If null, the
736      * default search controls are used (equivalent to (new SearchControls())).
737      * @return an enumeration of SearchResults of the objects that satisy the
738      * filter; never null
739      * @exception ArrayIndexOutOfBoundsException if filterExpr contains {i}
740      * expressions where i is outside the bounds of the array filterArgs
741      * @exception InvalidSearchControlsException if cons contains invalid
742      * settings
743      * @exception InvalidSearchFilterException if filterExpr with filterArgs
744      * represents an invalid search filter
745      * @exception NamingException if a naming exception is encountered
746      */

747     public NamingEnumeration JavaDoc search(String JavaDoc name, String JavaDoc filterExpr,
748                                     Object JavaDoc[] filterArgs, SearchControls JavaDoc cons)
749         throws NamingException JavaDoc {
750         return null;
751     }
752
753
754     // ------------------------------------------------------ Protected Methods
755

756
757     /**
758      * Return a context-relative path, beginning with a "/", that represents
759      * the canonical version of the specified path after ".." and "." elements
760      * are resolved out. If the specified path attempts to go outside the
761      * boundaries of the current context (i.e. too many ".." path elements
762      * are present), return <code>null</code> instead.
763      *
764      * @param path Path to be normalized
765      */

766     protected String JavaDoc normalize(String JavaDoc path) {
767
768     String JavaDoc normalized = path;
769
770     // Normalize the slashes and add leading slash if necessary
771
if (File.separatorChar == '\\' && normalized.indexOf('\\') >= 0)
772         normalized = normalized.replace('\\', '/');
773     if (!normalized.startsWith("/"))
774         normalized = "/" + normalized;
775
776     // Resolve occurrences of "//" in the normalized path
777
while (true) {
778         int index = normalized.indexOf("//");
779         if (index < 0)
780         break;
781         normalized = normalized.substring(0, index) +
782         normalized.substring(index + 1);
783     }
784
785     // Resolve occurrences of "/./" in the normalized path
786
while (true) {
787         int index = normalized.indexOf("/./");
788         if (index < 0)
789         break;
790         normalized = normalized.substring(0, index) +
791         normalized.substring(index + 2);
792     }
793
794     // Resolve occurrences of "/../" in the normalized path
795
while (true) {
796         int index = normalized.indexOf("/../");
797         if (index < 0)
798         break;
799         if (index == 0)
800         return (null); // Trying to go outside our context
801
int index2 = normalized.lastIndexOf('/', index - 1);
802         normalized = normalized.substring(0, index2) +
803         normalized.substring(index + 3);
804     }
805
806     // Return the normalized path that we have completed
807
return (normalized);
808
809     }
810
811
812     /**
813      * Return a File object representing the specified normalized
814      * context-relative path if it exists and is readable. Otherwise,
815      * return <code>null</code>.
816      *
817      * @param name Normalized context-relative path (with leading '/')
818      */

819     protected File JavaDoc file(String JavaDoc name) {
820
821         File JavaDoc file = new File JavaDoc(base, name);
822         if (file.exists() && file.canRead()) {
823
824             if (allowLinking)
825                 return file;
826             
827             // Check that this file belongs to our root path
828
String JavaDoc canPath = null;
829             try {
830                 canPath = file.getCanonicalPath();
831             } catch (IOException JavaDoc e) {
832             }
833             if (canPath == null)
834                 return null;
835
836             // Check to see if going outside of the web application root
837
if (!canPath.startsWith(absoluteBase)) {
838                 return null;
839             }
840
841             // Case sensitivity check
842
if (caseSensitive) {
843                 String JavaDoc fileAbsPath = file.getAbsolutePath();
844                 if (fileAbsPath.endsWith("."))
845                     fileAbsPath = fileAbsPath + "/";
846                 String JavaDoc absPath = normalize(fileAbsPath);
847                 if (canPath != null)
848                     canPath = normalize(canPath);
849                 if ((absoluteBase.length() < absPath.length())
850                     && (absoluteBase.length() < canPath.length())) {
851                     absPath = absPath.substring(absoluteBase.length() + 1);
852                     if ((canPath == null) || (absPath == null))
853                         return null;
854                     if (absPath.equals(""))
855                         absPath = "/";
856                     canPath = canPath.substring(absoluteBase.length() + 1);
857                     if (canPath.equals(""))
858                         canPath = "/";
859                     if (!canPath.equals(absPath))
860                         return null;
861                 }
862             }
863
864         } else {
865             return null;
866         }
867         return file;
868
869     }
870
871
872     /**
873      * List the resources which are members of a collection.
874      *
875      * @param file Collection
876      * @return Vector containg NamingEntry objects
877      */

878     protected ArrayList JavaDoc list(File JavaDoc file) {
879
880         ArrayList JavaDoc entries = new ArrayList JavaDoc();
881         if (!file.isDirectory())
882             return entries;
883         String JavaDoc[] names = file.list();
884         if (names==null) {
885             /* Some IO error occurred such as bad file permissions.
886                Prevent a NPE with Arrays.sort(names) */

887             log.warn(sm.getString("fileResources.listingNull",
888                                   file.getAbsolutePath()));
889             return entries;
890         }
891
892         Arrays.sort(names); // Sort alphabetically
893
if (names == null)
894             return entries;
895         NamingEntry entry = null;
896
897         for (int i = 0; i < names.length; i++) {
898
899             File JavaDoc currentFile = new File JavaDoc(file, names[i]);
900             Object JavaDoc object = null;
901             if (currentFile.isDirectory()) {
902                 FileDirContext tempContext = new FileDirContext(env);
903                 tempContext.setDocBase(file.getPath());
904                 tempContext.setAllowLinking(getAllowLinking());
905                 tempContext.setCaseSensitive(isCaseSensitive());
906                 object = tempContext;
907             } else {
908                 object = new FileResource(currentFile);
909             }
910             entry = new NamingEntry(names[i], object, NamingEntry.ENTRY);
911             entries.add(entry);
912
913         }
914
915         return entries;
916
917     }
918
919
920     // ----------------------------------------------- FileResource Inner Class
921

922
923     /**
924      * This specialized resource implementation avoids opening the IputStream
925      * to the file right away (which would put a lock on the file).
926      */

927     protected class FileResource extends Resource {
928
929
930         // -------------------------------------------------------- Constructor
931

932
933         public FileResource(File JavaDoc file) {
934             this.file = file;
935         }
936
937
938         // --------------------------------------------------- Member Variables
939

940
941         /**
942          * Associated file object.
943          */

944         protected File JavaDoc file;
945
946
947         /**
948          * File length.
949          */

950         protected long length = -1L;
951
952
953         // --------------------------------------------------- Resource Methods
954

955
956         /**
957          * Content accessor.
958          *
959          * @return InputStream
960          */

961         public InputStream JavaDoc streamContent()
962             throws IOException JavaDoc {
963             if (binaryContent == null) {
964                 inputStream = new FileInputStream JavaDoc(file);
965             }
966             return super.streamContent();
967         }
968
969
970     }
971
972
973     // ------------------------------------- FileResourceAttributes Inner Class
974

975
976     /**
977      * This specialized resource attribute implementation does some lazy
978      * reading (to speed up simple checks, like checking the last modified
979      * date).
980      */

981     protected class FileResourceAttributes extends ResourceAttributes {
982
983
984         // -------------------------------------------------------- Constructor
985

986
987         public FileResourceAttributes(File JavaDoc file) {
988             this.file = file;
989         }
990
991         // --------------------------------------------------- Member Variables
992

993
994         protected File JavaDoc file;
995
996
997         protected boolean accessed = false;
998
999
1000        protected String JavaDoc canonicalPath = null;
1001
1002
1003        // ----------------------------------------- ResourceAttributes Methods
1004

1005
1006        /**
1007         * Is collection.
1008         */

1009        public boolean isCollection() {
1010            if (!accessed) {
1011                collection = file.isDirectory();
1012                accessed = true;
1013            }
1014            return super.isCollection();
1015        }
1016
1017
1018        /**
1019         * Get content length.
1020         *
1021         * @return content length value
1022         */

1023        public long getContentLength() {
1024            if (contentLength != -1L)
1025                return contentLength;
1026            contentLength = file.length();
1027            return contentLength;
1028        }
1029
1030
1031        /**
1032         * Get creation time.
1033         *
1034         * @return creation time value
1035         */

1036        public long getCreation() {
1037            if (creation != -1L)
1038                return creation;
1039            creation = file.lastModified();
1040            return creation;
1041        }
1042
1043
1044        /**
1045         * Get creation date.
1046         *
1047         * @return Creation date value
1048         */

1049        public Date JavaDoc getCreationDate() {
1050            if (creation == -1L) {
1051                creation = file.lastModified();
1052            }
1053            return super.getCreationDate();
1054        }
1055
1056
1057        /**
1058         * Get last modified time.
1059         *
1060         * @return lastModified time value
1061         */

1062        public long getLastModified() {
1063            if (lastModified != -1L)
1064                return lastModified;
1065            lastModified = file.lastModified();
1066            return lastModified;
1067        }
1068
1069
1070        /**
1071         * Get lastModified date.
1072         *
1073         * @return LastModified date value
1074         */

1075        public Date JavaDoc getLastModifiedDate() {
1076            if (lastModified == -1L) {
1077                lastModified = file.lastModified();
1078            }
1079            return super.getLastModifiedDate();
1080        }
1081
1082
1083        /**
1084         * Get name.
1085         *
1086         * @return Name value
1087         */

1088        public String JavaDoc getName() {
1089            if (name == null)
1090                name = file.getName();
1091            return name;
1092        }
1093
1094
1095        /**
1096         * Get resource type.
1097         *
1098         * @return String resource type
1099         */

1100        public String JavaDoc getResourceType() {
1101            if (!accessed) {
1102                collection = file.isDirectory();
1103                accessed = true;
1104            }
1105            return super.getResourceType();
1106        }
1107
1108        
1109        /**
1110         * Get canonical path.
1111         *
1112         * @return String the file's canonical path
1113         */

1114        public String JavaDoc getCanonicalPath() {
1115            if (canonicalPath == null) {
1116                try {
1117                    canonicalPath = file.getCanonicalPath();
1118                } catch (IOException JavaDoc e) {
1119                    // Ignore
1120
}
1121            }
1122            return canonicalPath;
1123        }
1124        
1125
1126    }
1127
1128
1129}
1130
1131
Popular Tags