001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.core;
018:
019: import java.io.File;
020: import java.io.InputStream;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.Enumeration;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.Set;
028:
029: import javax.naming.Binding;
030: import javax.naming.NamingException;
031: import javax.naming.directory.DirContext;
032: import javax.servlet.RequestDispatcher;
033: import javax.servlet.Servlet;
034: import javax.servlet.ServletContext;
035: import javax.servlet.ServletContextAttributeEvent;
036: import javax.servlet.ServletContextAttributeListener;
037:
038: import org.apache.catalina.Context;
039: import org.apache.catalina.Host;
040: import org.apache.catalina.Logger;
041: import org.apache.catalina.Wrapper;
042: import org.apache.catalina.deploy.ApplicationParameter;
043: import org.apache.catalina.util.Enumerator;
044: import org.apache.catalina.util.ResourceSet;
045: import org.apache.catalina.util.ServerInfo;
046: import org.apache.catalina.util.StringManager;
047: import org.apache.naming.resources.DirContextURLStreamHandler;
048: import org.apache.naming.resources.Resource;
049: import org.apache.tomcat.util.buf.CharChunk;
050: import org.apache.tomcat.util.buf.MessageBytes;
051: import org.apache.tomcat.util.http.mapper.MappingData;
052:
053: /**
054: * Standard implementation of <code>ServletContext</code> that represents
055: * a web application's execution environment. An instance of this class is
056: * associated with each instance of <code>StandardContext</code>.
057: *
058: * @author Craig R. McClanahan
059: * @author Remy Maucherat
060: * @version $Revision: 1.25 $ $Date: 2004/04/01 20:09:21 $
061: */
062:
063: public class ApplicationContext implements ServletContext {
064:
065: // ----------------------------------------------------------- Constructors
066:
067: /**
068: * Construct a new instance of this class, associated with the specified
069: * Context instance.
070: *
071: * @param context The associated Context instance
072: */
073: public ApplicationContext(String basePath, StandardContext context) {
074: super ();
075: this .context = context;
076: this .basePath = basePath;
077: }
078:
079: // ----------------------------------------------------- Instance Variables
080:
081: /**
082: * The context attributes for this context.
083: */
084: private HashMap attributes = new HashMap();
085:
086: /**
087: * List of read only attributes for this context.
088: */
089: private HashMap readOnlyAttributes = new HashMap();
090:
091: /**
092: * The Context instance with which we are associated.
093: */
094: private StandardContext context = null;
095:
096: /**
097: * Empty collection to serve as the basis for empty enumerations.
098: * <strong>DO NOT ADD ANY ELEMENTS TO THIS COLLECTION!</strong>
099: */
100: private static final ArrayList empty = new ArrayList();
101:
102: /**
103: * The facade around this object.
104: */
105: private ServletContext facade = new ApplicationContextFacade(this );
106:
107: /**
108: * The merged context initialization parameters for this Context.
109: */
110: private HashMap parameters = null;
111:
112: /**
113: * The string manager for this package.
114: */
115: private static final StringManager sm = StringManager
116: .getManager(Constants.Package);
117:
118: /**
119: * Base path.
120: */
121: private String basePath = null;
122:
123: /**
124: * Thread local mapping data.
125: */
126: private ThreadLocal localMappingData = new ThreadLocal();
127:
128: /**
129: * Thread local URI message bytes.
130: */
131: private ThreadLocal localUriMB = new ThreadLocal();
132:
133: // --------------------------------------------------------- Public Methods
134:
135: /**
136: * Return the resources object that is mapped to a specified path.
137: * The path must begin with a "/" and is interpreted as relative to the
138: * current context root.
139: */
140: public DirContext getResources() {
141:
142: return context.getResources();
143:
144: }
145:
146: // ------------------------------------------------- ServletContext Methods
147:
148: /**
149: * Return the value of the specified context attribute, if any;
150: * otherwise return <code>null</code>.
151: *
152: * @param name Name of the context attribute to return
153: */
154: public Object getAttribute(String name) {
155:
156: synchronized (attributes) {
157: return (attributes.get(name));
158: }
159:
160: }
161:
162: /**
163: * Return an enumeration of the names of the context attributes
164: * associated with this context.
165: */
166: public Enumeration getAttributeNames() {
167:
168: synchronized (attributes) {
169: return new Enumerator(attributes.keySet(), true);
170: }
171:
172: }
173:
174: /**
175: * Return a <code>ServletContext</code> object that corresponds to a
176: * specified URI on the server. This method allows servlets to gain
177: * access to the context for various parts of the server, and as needed
178: * obtain <code>RequestDispatcher</code> objects or resources from the
179: * context. The given path must be absolute (beginning with a "/"),
180: * and is interpreted based on our virtual host's document root.
181: *
182: * @param uri Absolute URI of a resource on the server
183: */
184: public ServletContext getContext(String uri) {
185:
186: // Validate the format of the specified argument
187: if ((uri == null) || (!uri.startsWith("/")))
188: return (null);
189:
190: // Return the current context if requested
191: String contextPath = context.getPath();
192: if (!contextPath.endsWith("/"))
193: contextPath = contextPath + "/";
194:
195: if (((contextPath.length() > 1) && (uri.startsWith(contextPath)))
196: || ((contextPath.equals("/")) && (uri.equals("/")))) {
197: return (this );
198: }
199:
200: // Return other contexts only if allowed
201: if (!context.getCrossContext())
202: return (null);
203: try {
204: Host host = (Host) context.getParent();
205: Context child = null;
206: String mapuri = uri;
207: while (true) {
208: child = (Context) host.findChild(mapuri);
209: if (child != null)
210: break;
211: int slash = mapuri.lastIndexOf('/');
212: if (slash < 0)
213: break;
214: mapuri = mapuri.substring(0, slash);
215: }
216: if (child == null) {
217: child = (Context) host.findChild("");
218: }
219: if (child != null)
220: return (child.getServletContext());
221: else
222: return (null);
223: } catch (Throwable t) {
224: return (null);
225: }
226:
227: }
228:
229: /**
230: * Return the value of the specified initialization parameter, or
231: * <code>null</code> if this parameter does not exist.
232: *
233: * @param name Name of the initialization parameter to retrieve
234: */
235: public String getInitParameter(final String name) {
236:
237: mergeParameters();
238: synchronized (parameters) {
239: return ((String) parameters.get(name));
240: }
241: }
242:
243: /**
244: * Return the names of the context's initialization parameters, or an
245: * empty enumeration if the context has no initialization parameters.
246: */
247: public Enumeration getInitParameterNames() {
248:
249: mergeParameters();
250: synchronized (parameters) {
251: return (new Enumerator(parameters.keySet()));
252: }
253:
254: }
255:
256: /**
257: * Return the major version of the Java Servlet API that we implement.
258: */
259: public int getMajorVersion() {
260:
261: return (Constants.MAJOR_VERSION);
262:
263: }
264:
265: /**
266: * Return the minor version of the Java Servlet API that we implement.
267: */
268: public int getMinorVersion() {
269:
270: return (Constants.MINOR_VERSION);
271:
272: }
273:
274: /**
275: * Return the MIME type of the specified file, or <code>null</code> if
276: * the MIME type cannot be determined.
277: *
278: * @param file Filename for which to identify a MIME type
279: */
280: public String getMimeType(String file) {
281:
282: if (file == null)
283: return (null);
284: int period = file.lastIndexOf(".");
285: if (period < 0)
286: return (null);
287: String extension = file.substring(period + 1);
288: if (extension.length() < 1)
289: return (null);
290: return (context.findMimeMapping(extension));
291:
292: }
293:
294: /**
295: * Return a <code>RequestDispatcher</code> object that acts as a
296: * wrapper for the named servlet.
297: *
298: * @param name Name of the servlet for which a dispatcher is requested
299: */
300: public RequestDispatcher getNamedDispatcher(String name) {
301:
302: // Validate the name argument
303: if (name == null)
304: return (null);
305:
306: // Create and return a corresponding request dispatcher
307: Wrapper wrapper = (Wrapper) context.findChild(name);
308: if (wrapper == null)
309: return (null);
310:
311: ApplicationDispatcher dispatcher;
312: dispatcher = new ApplicationDispatcher(wrapper, null, null,
313: null, null, name);
314:
315: return ((RequestDispatcher) dispatcher);
316:
317: }
318:
319: /**
320: * Return the real path for a given virtual path, if possible; otherwise
321: * return <code>null</code>.
322: *
323: * @param path The path to the desired resource
324: */
325: public String getRealPath(String path) {
326:
327: if (!context.isFilesystemBased())
328: return null;
329:
330: File file = new File(basePath, path);
331: return (file.getAbsolutePath());
332:
333: }
334:
335: /**
336: * Return a <code>RequestDispatcher</code> instance that acts as a
337: * wrapper for the resource at the given path. The path must begin
338: * with a "/" and is interpreted as relative to the current context root.
339: *
340: * @param path The path to the desired resource.
341: */
342: public RequestDispatcher getRequestDispatcher(String path) {
343:
344: // Validate the path argument
345: if (path == null)
346: return (null);
347: if (!path.startsWith("/"))
348: throw new IllegalArgumentException(sm.getString(
349: "applicationContext.requestDispatcher.iae", path));
350: path = normalize(path);
351: if (path == null)
352: return (null);
353:
354: // Retrieve the thread local URI
355: MessageBytes uriMB = (MessageBytes) localUriMB.get();
356: if (uriMB == null) {
357: uriMB = new MessageBytes();
358: CharChunk uriCC = uriMB.getCharChunk();
359: uriCC.setLimit(-1);
360: localUriMB.set(uriMB);
361: } else {
362: uriMB.recycle();
363: }
364:
365: // Get query string
366: String queryString = null;
367: int pos = path.indexOf('?');
368: if (pos >= 0) {
369: queryString = path.substring(pos + 1);
370: } else {
371: pos = path.length();
372: }
373:
374: // Retrieve the thread local mapping data
375: MappingData mappingData = (MappingData) localMappingData.get();
376: if (mappingData == null) {
377: mappingData = new MappingData();
378: localMappingData.set(mappingData);
379: }
380:
381: // Map the URI
382: CharChunk uriCC = uriMB.getCharChunk();
383: try {
384: uriCC.append(context.getPath(), 0, context.getPath()
385: .length());
386: /*
387: * Ignore any trailing path params (separated by ';') for mapping
388: * purposes
389: */
390: int semicolon = path.indexOf(';');
391: uriCC.append(path, 0, semicolon > 0 ? semicolon : pos);
392: context.getMapper().map(uriMB, mappingData);
393: if (mappingData.wrapper == null) {
394: return (null);
395: }
396: /*
397: * Append any trailing path params (separated by ';') that were
398: * ignored for mapping purposes, so that they're reflected in the
399: * RequestDispatcher's requestURI
400: */
401: if (semicolon > 0) {
402: uriCC.append(path, semicolon, pos - semicolon);
403: }
404: } catch (Exception e) {
405: // Should never happen
406: log(sm.getString("applicationContext.mapping.error"), e);
407: return (null);
408: }
409:
410: Wrapper wrapper = (Wrapper) mappingData.wrapper;
411: String wrapperPath = mappingData.wrapperPath.toString();
412: String pathInfo = mappingData.pathInfo.toString();
413:
414: mappingData.recycle();
415:
416: // Construct a RequestDispatcher to process this request
417: return (RequestDispatcher) new ApplicationDispatcher(wrapper,
418: uriCC.toString(), wrapperPath, pathInfo, queryString,
419: null);
420:
421: }
422:
423: /**
424: * Return the URL to the resource that is mapped to a specified path.
425: * The path must begin with a "/" and is interpreted as relative to the
426: * current context root.
427: *
428: * @param path The path to the desired resource
429: *
430: * @exception MalformedURLException if the path is not given
431: * in the correct form
432: */
433: public URL getResource(String path) throws MalformedURLException {
434:
435: if (path == null || !path.startsWith("/")) {
436: throw new MalformedURLException(sm.getString(
437: "applicationContext.requestDispatcher.iae", path));
438: }
439:
440: path = normalize(path);
441: if (path == null)
442: return (null);
443:
444: String libPath = "/WEB-INF/lib/";
445: if ((path.startsWith(libPath)) && (path.endsWith(".jar"))) {
446: File jarFile = null;
447: if (context.isFilesystemBased()) {
448: jarFile = new File(basePath, path);
449: } else {
450: jarFile = new File(context.getWorkPath(), path);
451: }
452: if (jarFile.exists()) {
453: return jarFile.toURL();
454: } else {
455: return null;
456: }
457: } else {
458:
459: DirContext resources = context.getResources();
460: if (resources != null) {
461: String fullPath = context.getName() + path;
462: String hostName = context.getParent().getName();
463: try {
464: resources.lookup(path);
465: return new URL("jndi", null, 0, getJNDIUri(
466: hostName, fullPath),
467: new DirContextURLStreamHandler(resources));
468: } catch (Exception e) {
469: // Ignore
470: }
471: }
472: }
473:
474: return (null);
475:
476: }
477:
478: /**
479: * Return the requested resource as an <code>InputStream</code>. The
480: * path must be specified according to the rules described under
481: * <code>getResource</code>. If no such resource can be identified,
482: * return <code>null</code>.
483: *
484: * @param path The path to the desired resource.
485: */
486: public InputStream getResourceAsStream(String path) {
487:
488: path = normalize(path);
489: if (path == null)
490: return (null);
491:
492: DirContext resources = context.getResources();
493: if (resources != null) {
494: try {
495: Object resource = resources.lookup(path);
496: if (resource instanceof Resource)
497: return (((Resource) resource).streamContent());
498: } catch (Exception e) {
499: }
500: }
501: return (null);
502:
503: }
504:
505: /**
506: * Return a Set containing the resource paths of resources member of the
507: * specified collection. Each path will be a String starting with
508: * a "/" character. The returned set is immutable.
509: *
510: * @param path Collection path
511: */
512: public Set getResourcePaths(String path) {
513:
514: path = normalize(path);
515: if (path == null)
516: return (null);
517:
518: DirContext resources = context.getResources();
519: if (resources != null) {
520: return (getResourcePathsInternal(resources, path));
521: }
522: return (null);
523:
524: }
525:
526: /**
527: * Internal implementation of getResourcesPath() logic.
528: *
529: * @param resources Directory context to search
530: * @param path Collection path
531: */
532: private Set getResourcePathsInternal(DirContext resources,
533: String path) {
534:
535: ResourceSet set = new ResourceSet();
536: try {
537: listCollectionPaths(set, resources, path);
538: } catch (NamingException e) {
539: return (null);
540: }
541: set.setLocked(true);
542: return (set);
543:
544: }
545:
546: /**
547: * Return the name and version of the servlet container.
548: */
549: public String getServerInfo() {
550:
551: return (ServerInfo.getServerInfo());
552:
553: }
554:
555: /**
556: * @deprecated As of Java Servlet API 2.1, with no direct replacement.
557: */
558: public Servlet getServlet(String name) {
559:
560: return (null);
561:
562: }
563:
564: /**
565: * Return the display name of this web application.
566: */
567: public String getServletContextName() {
568:
569: return (context.getDisplayName());
570:
571: }
572:
573: /**
574: * @deprecated As of Java Servlet API 2.1, with no direct replacement.
575: */
576: public Enumeration getServletNames() {
577: return (new Enumerator(empty));
578: }
579:
580: /**
581: * @deprecated As of Java Servlet API 2.1, with no direct replacement.
582: */
583: public Enumeration getServlets() {
584: return (new Enumerator(empty));
585: }
586:
587: /**
588: * Writes the specified message to a servlet log file.
589: *
590: * @param message Message to be written
591: */
592: public void log(String message) {
593:
594: Logger logger = context.getLogger();
595: if (logger != null)
596: logger.log(context.logName() + message);
597:
598: }
599:
600: /**
601: * Writes the specified exception and message to a servlet log file.
602: *
603: * @param exception Exception to be reported
604: * @param message Message to be written
605: *
606: * @deprecated As of Java Servlet API 2.1, use
607: * <code>log(String, Throwable)</code> instead
608: */
609: public void log(Exception exception, String message) {
610:
611: Logger logger = context.getLogger();
612: if (logger != null)
613: logger.log(exception, context.logName() + message);
614:
615: }
616:
617: /**
618: * Writes the specified message and exception to a servlet log file.
619: *
620: * @param message Message to be written
621: * @param throwable Exception to be reported
622: */
623: public void log(String message, Throwable throwable) {
624:
625: Logger logger = context.getLogger();
626: if (logger != null)
627: logger.log(context.logName() + message, throwable);
628:
629: }
630:
631: /**
632: * Remove the context attribute with the specified name, if any.
633: *
634: * @param name Name of the context attribute to be removed
635: */
636: public void removeAttribute(String name) {
637:
638: Object value = null;
639: boolean found = false;
640:
641: // Remove the specified attribute
642: synchronized (attributes) {
643: // Check for read only attribute
644: if (readOnlyAttributes.containsKey(name))
645: return;
646: found = attributes.containsKey(name);
647: if (found) {
648: value = attributes.get(name);
649: attributes.remove(name);
650: } else {
651: return;
652: }
653: }
654:
655: // Notify interested application event listeners
656: Object listeners[] = context.getApplicationEventListeners();
657: if ((listeners == null) || (listeners.length == 0))
658: return;
659: ServletContextAttributeEvent event = new ServletContextAttributeEvent(
660: context.getServletContext(), name, value);
661: for (int i = 0; i < listeners.length; i++) {
662: if (!(listeners[i] instanceof ServletContextAttributeListener))
663: continue;
664: ServletContextAttributeListener listener = (ServletContextAttributeListener) listeners[i];
665: try {
666: context.fireContainerEvent(
667: "beforeContextAttributeRemoved", listener);
668: listener.attributeRemoved(event);
669: context.fireContainerEvent(
670: "afterContextAttributeRemoved", listener);
671: } catch (Throwable t) {
672: context.fireContainerEvent(
673: "afterContextAttributeRemoved", listener);
674: // FIXME - should we do anything besides log these?
675: log(sm.getString("applicationContext.attributeEvent"),
676: t);
677: }
678: }
679:
680: }
681:
682: /**
683: * Bind the specified value with the specified context attribute name,
684: * replacing any existing value for that name.
685: *
686: * @param name Attribute name to be bound
687: * @param value New attribute value to be bound
688: */
689: public void setAttribute(String name, Object value) {
690:
691: // Name cannot be null
692: if (name == null)
693: throw new IllegalArgumentException(
694: sm
695: .getString("applicationContext.setAttribute.namenull"));
696:
697: // Null value is the same as removeAttribute()
698: if (value == null) {
699: removeAttribute(name);
700: return;
701: }
702:
703: Object oldValue = null;
704: boolean replaced = false;
705:
706: // Add or replace the specified attribute
707: synchronized (attributes) {
708: // Check for read only attribute
709: if (readOnlyAttributes.containsKey(name))
710: return;
711: oldValue = attributes.get(name);
712: if (oldValue != null)
713: replaced = true;
714: attributes.put(name, value);
715: }
716:
717: // Notify interested application event listeners
718: Object listeners[] = context.getApplicationEventListeners();
719: if ((listeners == null) || (listeners.length == 0))
720: return;
721: ServletContextAttributeEvent event = null;
722: if (replaced)
723: event = new ServletContextAttributeEvent(context
724: .getServletContext(), name, oldValue);
725: else
726: event = new ServletContextAttributeEvent(context
727: .getServletContext(), name, value);
728:
729: for (int i = 0; i < listeners.length; i++) {
730: if (!(listeners[i] instanceof ServletContextAttributeListener))
731: continue;
732: ServletContextAttributeListener listener = (ServletContextAttributeListener) listeners[i];
733: try {
734: if (replaced) {
735: context.fireContainerEvent(
736: "beforeContextAttributeReplaced", listener);
737: listener.attributeReplaced(event);
738: context.fireContainerEvent(
739: "afterContextAttributeReplaced", listener);
740: } else {
741: context.fireContainerEvent(
742: "beforeContextAttributeAdded", listener);
743: listener.attributeAdded(event);
744: context.fireContainerEvent(
745: "afterContextAttributeAdded", listener);
746: }
747: } catch (Throwable t) {
748: if (replaced)
749: context.fireContainerEvent(
750: "afterContextAttributeReplaced", listener);
751: else
752: context.fireContainerEvent(
753: "afterContextAttributeAdded", listener);
754: // FIXME - should we do anything besides log these?
755: log(sm.getString("applicationContext.attributeEvent"),
756: t);
757: }
758: }
759:
760: }
761:
762: // -------------------------------------------------------- Package Methods
763:
764: /**
765: * Clear all application-created attributes.
766: */
767: void clearAttributes() {
768:
769: // Create list of attributes to be removed
770: ArrayList list = new ArrayList();
771: synchronized (attributes) {
772: Iterator iter = attributes.keySet().iterator();
773: while (iter.hasNext()) {
774: list.add(iter.next());
775: }
776: }
777:
778: // Remove application originated attributes
779: // (read only attributes will be left in place)
780: Iterator keys = list.iterator();
781: while (keys.hasNext()) {
782: String key = (String) keys.next();
783: removeAttribute(key);
784: }
785:
786: }
787:
788: /**
789: * Return the facade associated with this ApplicationContext.
790: */
791: protected ServletContext getFacade() {
792:
793: return (this .facade);
794:
795: }
796:
797: /**
798: * Set an attribute as read only.
799: */
800: void setAttributeReadOnly(String name) {
801:
802: synchronized (attributes) {
803: if (attributes.containsKey(name))
804: readOnlyAttributes.put(name, name);
805: }
806:
807: }
808:
809: // -------------------------------------------------------- Private Methods
810:
811: /**
812: * Return a context-relative path, beginning with a "/", that represents
813: * the canonical version of the specified path after ".." and "." elements
814: * are resolved out. If the specified path attempts to go outside the
815: * boundaries of the current context (i.e. too many ".." path elements
816: * are present), return <code>null</code> instead.
817: *
818: * @param path Path to be normalized
819: */
820: private String normalize(String path) {
821:
822: String normalized = path;
823:
824: // Normalize the slashes and add leading slash if necessary
825: if (normalized.indexOf('\\') >= 0)
826: normalized = normalized.replace('\\', '/');
827:
828: // Resolve occurrences of "/../" in the normalized path
829: while (true) {
830: int index = normalized.indexOf("/../");
831: if (index < 0)
832: break;
833: if (index == 0)
834: return (null); // Trying to go outside our context
835: int index2 = normalized.lastIndexOf('/', index - 1);
836: normalized = normalized.substring(0, index2)
837: + normalized.substring(index + 3);
838: }
839:
840: // Return the normalized path that we have completed
841: return (normalized);
842:
843: }
844:
845: /**
846: * Merge the context initialization parameters specified in the application
847: * deployment descriptor with the application parameters described in the
848: * server configuration, respecting the <code>override</code> property of
849: * the application parameters appropriately.
850: */
851: private void mergeParameters() {
852:
853: if (parameters != null)
854: return;
855: HashMap results = new HashMap();
856: String names[] = context.findParameters();
857: for (int i = 0; i < names.length; i++)
858: results.put(names[i], context.findParameter(names[i]));
859: ApplicationParameter params[] = context
860: .findApplicationParameters();
861: for (int i = 0; i < params.length; i++) {
862: if (params[i].getOverride()) {
863: if (results.get(params[i].getName()) == null)
864: results.put(params[i].getName(), params[i]
865: .getValue());
866: } else {
867: results.put(params[i].getName(), params[i].getValue());
868: }
869: }
870: parameters = results;
871:
872: }
873:
874: /**
875: * List resource paths (recursively), and store all of them in the given
876: * Set.
877: */
878: private static void listPaths(Set set, DirContext resources,
879: String path) throws NamingException {
880:
881: Enumeration childPaths = resources.listBindings(path);
882: while (childPaths.hasMoreElements()) {
883: Binding binding = (Binding) childPaths.nextElement();
884: String name = binding.getName();
885: String childPath = path + "/" + name;
886: set.add(childPath);
887: Object object = binding.getObject();
888: if (object instanceof DirContext) {
889: listPaths(set, resources, childPath);
890: }
891: }
892:
893: }
894:
895: /**
896: * List resource paths (recursively), and store all of them in the given
897: * Set.
898: */
899: private static void listCollectionPaths(Set set,
900: DirContext resources, String path) throws NamingException {
901:
902: Enumeration childPaths = resources.listBindings(path);
903: while (childPaths.hasMoreElements()) {
904: Binding binding = (Binding) childPaths.nextElement();
905: String name = binding.getName();
906: StringBuffer childPath = new StringBuffer(path);
907: if (!"/".equals(path) && !path.endsWith("/"))
908: childPath.append("/");
909: childPath.append(name);
910: Object object = binding.getObject();
911: if (object instanceof DirContext) {
912: childPath.append("/");
913: }
914: set.add(childPath.toString());
915: }
916:
917: }
918:
919: /**
920: * Get full path, based on the host name and the context path.
921: */
922: private static String getJNDIUri(String hostName, String path) {
923: if (!path.startsWith("/"))
924: return "/" + hostName + "/" + path;
925: else
926: return "/" + hostName + path;
927: }
928:
929: }
|