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.naming.handler.jndi;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.FileNotFoundException;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.net.URL;
024: import java.net.URLConnection;
025: import java.security.Permission;
026: import java.util.Enumeration;
027: import java.util.Vector;
028:
029: import javax.naming.NameClassPair;
030: import javax.naming.NamingEnumeration;
031: import javax.naming.NamingException;
032: import javax.naming.directory.Attribute;
033: import javax.naming.directory.Attributes;
034: import javax.naming.directory.DirContext;
035:
036: import org.apache.naming.core.JndiPermission;
037: import org.apache.naming.util.AttributeHelper;
038:
039: // import org.apache.naming.resources.Resource;
040: // import org.apache.naming.resources.ResourceAttributes;
041:
042: /**
043: * Connection to a JNDI directory context.
044: * <p/>
045: * Note: All the object attribute names are the WebDAV names, not the HTTP
046: * names, so this class overrides some methods from URLConnection to do the
047: * queries using the right names. Content handler is also not used; the
048: * content is directly returned.
049: *
050: * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
051: * @author Costin Manolache
052: */
053: public class DirContextURLConnection extends URLConnection {
054:
055: // ----------------------------------------------------------- Constructors
056:
057: /**
058: * @param context The base context for the dynamic resources.
059: * For regular webapps, it should be a thread-bound context, probably
060: * a branch under java:
061: * For top-level apps, it can be either the InitialContext or a branch
062: * that is used for all content.
063: *
064: * The choice of the context affects the base of the URLs.
065: */
066: public DirContextURLConnection(DirContext context, URL url) {
067: super (url);
068: if (context == null)
069: throw new IllegalArgumentException(
070: "Directory context can't be null");
071: if (System.getSecurityManager() != null) {
072: this .permission = new JndiPermission(url.toString());
073: }
074: this .context = context;
075: }
076:
077: // ----------------------------------------------------- Instance Variables
078:
079: /**
080: * Directory context.
081: */
082: protected DirContext context;
083:
084: /**
085: * Associated resource.
086: */
087: protected Object resource;
088:
089: /**
090: * Associated DirContext.
091: */
092: protected DirContext collection;
093:
094: /**
095: * Other unknown object.
096: */
097: protected Object object;
098:
099: /**
100: * Attributes.
101: */
102: protected Attributes attributes;
103:
104: /**
105: * Date.
106: */
107: protected long date;
108:
109: /**
110: * Permission
111: */
112: protected Permission permission;
113:
114: // ------------------------------------------------------------- Properties
115:
116: /**
117: * Connect to the DirContext, and retrive the bound object, as well as
118: * its attributes. If no object is bound with the name specified in the
119: * URL, then an IOException is thrown.
120: *
121: * @throws IOException Object not found
122: */
123: public void connect() throws IOException {
124:
125: if (!connected) {
126:
127: try {
128: // TODO: What is this ??? (costin)
129: date = System.currentTimeMillis();
130: String path = getURL().getFile();
131:
132: /* This deals with a strange case, where the
133: name is prefixed by hostname and contextname.
134:
135: A webapp should never use this - all resources
136: are local ( or a different mean should be used to
137: locate external res ).
138:
139: The top-level handler must use the hostname + context to
140: locate files in a particular context.
141:
142: if (context instanceof ProxyDirContext) {
143: ProxyDirContext proxyDirContext =
144: (ProxyDirContext) context;
145: String hostName = proxyDirContext.getHostName();
146: String contextName = proxyDirContext.getContextName();
147: if (hostName != null) {
148: if (!path.startsWith("/" + hostName + "/"))
149: return;
150: path = path.substring(hostName.length()+ 1);
151: }
152: if (contextName != null) {
153: if (!path.startsWith(contextName + "/")) {
154: return;
155: } else {
156: path = path.substring(contextName.length());
157: }
158: }
159: }
160: */
161: object = context.lookup(path);
162: attributes = context.getAttributes(path);
163: // if (object instanceof Resource)
164: // resource = (Resource) object;
165: if (object instanceof DirContext)
166: collection = (DirContext) object;
167: else
168: resource = object;
169: } catch (NamingException e) {
170: // Object not found
171: }
172:
173: connected = true;
174:
175: }
176:
177: }
178:
179: /**
180: * Return the content length value.
181: */
182: public int getContentLength() {
183: if (!connected) {
184: // Try to connect (silently)
185: try {
186: connect();
187: } catch (IOException e) {
188: }
189: }
190:
191: if (attributes == null)
192: return (-1);
193:
194: return (int) AttributeHelper.getContentLength(attributes);
195: }
196:
197: /**
198: * Return the content type value.
199: */
200: public String getContentType() {
201: if (!connected) {
202: // Try to connect (silently)
203: try {
204: connect();
205: } catch (IOException e) {
206: }
207: }
208:
209: if (attributes == null)
210: return null;
211:
212: return AttributeHelper.getContentType(attributes);
213: }
214:
215: /**
216: * Return the last modified date.
217: * TODO: it's broken
218: */
219: public long getDate() {
220: return date;
221: }
222:
223: /**
224: * Return the last modified date.
225: */
226: public long getLastModified() {
227:
228: if (!connected) {
229: // Try to connect (silently)
230: try {
231: connect();
232: } catch (IOException e) {
233: }
234: }
235:
236: if (attributes == null)
237: return 0;
238:
239: return AttributeHelper.getLastModified(attributes);
240: }
241:
242: /**
243: * Returns the name of the specified header field.
244: */
245: public String getHeaderField(String name) {
246:
247: if (!connected) {
248: // Try to connect (silently)
249: try {
250: connect();
251: } catch (IOException e) {
252: }
253: }
254:
255: if (attributes == null)
256: return (null);
257:
258: Attribute attribute = attributes.get(name);
259: try {
260: return attribute.get().toString();
261: } catch (Exception e) {
262: // Shouldn't happen, unless the attribute has no value
263: }
264:
265: return (null);
266:
267: }
268:
269: /**
270: * Get object content.
271: */
272: public Object getContent() throws IOException {
273:
274: if (!connected)
275: connect();
276:
277: if (resource != null)
278: return getInputStream();
279: if (collection != null)
280: return collection;
281: if (object != null)
282: return object;
283:
284: throw new FileNotFoundException();
285:
286: }
287:
288: /**
289: * Get object content.
290: */
291: public Object getContent(Class[] classes) throws IOException {
292:
293: Object object = getContent();
294:
295: for (int i = 0; i < classes.length; i++) {
296: if (classes[i].isInstance(object))
297: return object;
298: }
299:
300: return null;
301:
302: }
303:
304: /**
305: * Get input stream.
306: */
307: public InputStream getInputStream() throws IOException {
308:
309: if (!connected)
310: connect();
311:
312: if (resource == null) {
313: throw new FileNotFoundException();
314: } else {
315: // Reopen resource
316: try {
317: resource = context.lookup(getURL().getFile());
318: } catch (NamingException e) {
319: }
320: }
321:
322: // return (resource.streamContent());
323: return getInputStream(resource);
324:
325: }
326:
327: /** Try to extract content from a resource found in the directory
328: * Code from Resource and ProxyContext.
329: */
330: public static InputStream getInputStream(Object resource) {
331: if (resource instanceof InputStream)
332: return (InputStream) resource;
333:
334: // Found in: ProxyDirContext.lookup ( strange, only in one ).
335: return new ByteArrayInputStream(resource.toString().getBytes());
336: }
337:
338: /**
339: * Get the Permission for this URL
340: */
341: public Permission getPermission() {
342:
343: return permission;
344: }
345:
346: // --------------------------------------------------------- Public Methods
347:
348: /**
349: * List children of this collection. The names given are relative to this
350: * URI's path. The full uri of the children is then : path + "/" + name.
351: */
352: public Enumeration list()
353: throws IOException {
354:
355: if (!connected) {
356: connect();
357: }
358:
359: if ((resource == null) && (collection == null)) {
360: throw new FileNotFoundException();
361: }
362:
363: Vector result = new Vector();
364:
365: if (collection != null) {
366: try {
367: NamingEnumeration enum = context.list(getURL().getFile());
368: while (enum.hasMoreElements()) {
369: NameClassPair ncp = (NameClassPair) enum.nextElement();
370: result.addElement(ncp.getName());
371: }
372: } catch (NamingException e) {
373: // Unexpected exception
374: throw new FileNotFoundException();
375: }
376: }
377:
378: return result.elements();
379:
380: }
381:
382: }
|