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 package org.apache.naming.resources;
19
20 import java.net.URL;
21 import java.net.URLConnection;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.FileNotFoundException;
25 import java.security.Permission;
26 import java.util.Date;
27 import java.util.Enumeration;
28 import java.util.Vector;
29 import javax.naming.NamingException;
30 import javax.naming.NamingEnumeration;
31 import javax.naming.NameClassPair;
32 import javax.naming.directory.DirContext;
33 import javax.naming.directory.Attribute;
34 import javax.naming.directory.Attributes;
35 import org.apache.naming.JndiPermission;
36 import org.apache.naming.resources.Resource;
37 import org.apache.naming.resources.ResourceAttributes;
38
39 /**
40 * Connection to a JNDI directory context.
41 * <p/>
42 * Note: All the object attribute names are the WebDAV names, not the HTTP
43 * names, so this class overrides some methods from URLConnection to do the
44 * queries using the right names. Content handler is also not used; the
45 * content is directly returned.
46 *
47 * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
48 * @version $Revision: 505593 $
49 */
50 public class DirContextURLConnection
51 extends URLConnection {
52
53
54 // ----------------------------------------------------------- Constructors
55
56
57 public DirContextURLConnection(DirContext context, URL url) {
58 super(url);
59 if (context == null)
60 throw new IllegalArgumentException
61 ("Directory context can't be null");
62 if (org.apache.naming.Constants.IS_SECURITY_ENABLED) {
63 this.permission = new JndiPermission(url.toString());
64 }
65 this.context = context;
66 }
67
68
69 // ----------------------------------------------------- Instance Variables
70
71
72 /**
73 * Directory context.
74 */
75 protected DirContext context;
76
77
78 /**
79 * Associated resource.
80 */
81 protected Resource resource;
82
83
84 /**
85 * Associated DirContext.
86 */
87 protected DirContext collection;
88
89
90 /**
91 * Other unknown object.
92 */
93 protected Object object;
94
95
96 /**
97 * Attributes.
98 */
99 protected Attributes attributes;
100
101
102 /**
103 * Date.
104 */
105 protected long date;
106
107
108 /**
109 * Permission
110 */
111 protected Permission permission;
112
113
114 // ------------------------------------------------------------- Properties
115
116
117 /**
118 * Connect to the DirContext, and retrive the bound object, as well as
119 * its attributes. If no object is bound with the name specified in the
120 * URL, then an IOException is thrown.
121 *
122 * @throws IOException Object not found
123 */
124 public void connect()
125 throws IOException {
126
127 if (!connected) {
128
129 try {
130 date = System.currentTimeMillis();
131 String path = getURL().getFile();
132 if (context instanceof ProxyDirContext) {
133 ProxyDirContext proxyDirContext =
134 (ProxyDirContext) context;
135 String hostName = proxyDirContext.getHostName();
136 String contextName = proxyDirContext.getContextName();
137 if (hostName != null) {
138 if (!path.startsWith("/" + hostName + "/"))
139 return;
140 path = path.substring(hostName.length()+ 1);
141 }
142 if (contextName != null) {
143 if (!path.startsWith(contextName + "/")) {
144 return;
145 } else {
146 path = path.substring(contextName.length());
147 }
148 }
149 }
150 object = context.lookup(path);
151 attributes = context.getAttributes(path);
152 if (object instanceof Resource)
153 resource = (Resource) object;
154 if (object instanceof DirContext)
155 collection = (DirContext) object;
156 } catch (NamingException e) {
157 // Object not found
158 }
159
160 connected = true;
161
162 }
163
164 }
165
166
167 /**
168 * Return the content length value.
169 */
170 public int getContentLength() {
171 return getHeaderFieldInt(ResourceAttributes.CONTENT_LENGTH, -1);
172 }
173
174
175 /**
176 * Return the content type value.
177 */
178 public String getContentType() {
179 return getHeaderField(ResourceAttributes.CONTENT_TYPE);
180 }
181
182
183 /**
184 * Return the last modified date.
185 */
186 public long getDate() {
187 return date;
188 }
189
190
191 /**
192 * Return the last modified date.
193 */
194 public long getLastModified() {
195
196 if (!connected) {
197 // Try to connect (silently)
198 try {
199 connect();
200 } catch (IOException e) {
201 }
202 }
203
204 if (attributes == null)
205 return 0;
206
207 Attribute lastModified =
208 attributes.get(ResourceAttributes.LAST_MODIFIED);
209 if (lastModified != null) {
210 try {
211 Date lmDate = (Date) lastModified.get();
212 return lmDate.getTime();
213 } catch (Exception e) {
214 }
215 }
216
217 return 0;
218 }
219
220
221 /**
222 * Returns the name of the specified header field.
223 */
224 public String getHeaderField(String name) {
225
226 if (!connected) {
227 // Try to connect (silently)
228 try {
229 connect();
230 } catch (IOException e) {
231 }
232 }
233
234 if (attributes == null)
235 return (null);
236
237 Attribute attribute = attributes.get(name);
238 try {
239 return attribute.get().toString();
240 } catch (Exception e) {
241 // Shouldn't happen, unless the attribute has no value
242 }
243
244 return (null);
245
246 }
247
248
249 /**
250 * Get object content.
251 */
252 public Object getContent()
253 throws IOException {
254
255 if (!connected)
256 connect();
257
258 if (resource != null)
259 return getInputStream();
260 if (collection != null)
261 return collection;
262 if (object != null)
263 return object;
264
265 throw new FileNotFoundException();
266
267 }
268
269
270 /**
271 * Get object content.
272 */
273 public Object getContent(Class[] classes)
274 throws IOException {
275
276 Object object = getContent();
277
278 for (int i = 0; i < classes.length; i++) {
279 if (classes[i].isInstance(object))
280 return object;
281 }
282
283 return null;
284
285 }
286
287
288 /**
289 * Get input stream.
290 */
291 public InputStream getInputStream()
292 throws IOException {
293
294 if (!connected)
295 connect();
296
297 if (resource == null) {
298 throw new FileNotFoundException();
299 } else {
300 // Reopen resource
301 try {
302 resource = (Resource) context.lookup(getURL().getFile());
303 } catch (NamingException e) {
304 }
305 }
306
307 return (resource.streamContent());
308
309 }
310
311
312 /**
313 * Get the Permission for this URL
314 */
315 public Permission getPermission() {
316
317 return permission;
318 }
319
320
321 // --------------------------------------------------------- Public Methods
322
323
324 /**
325 * List children of this collection. The names given are relative to this
326 * URI's path. The full uri of the children is then : path + "/" + name.
327 */
328 public Enumeration list()
329 throws IOException {
330
331 if (!connected) {
332 connect();
333 }
334
335 if ((resource == null) && (collection == null)) {
336 throw new FileNotFoundException();
337 }
338
339 Vector result = new Vector();
340
341 if (collection != null) {
342 try {
343 NamingEnumeration enumeration = context.list(getURL().getFile());
344 while (enumeration.hasMoreElements()) {
345 NameClassPair ncp = (NameClassPair) enumeration.nextElement();
346 result.addElement(ncp.getName());
347 }
348 } catch (NamingException e) {
349 // Unexpected exception
350 throw new FileNotFoundException();
351 }
352 }
353
354 return result.elements();
355
356 }
357
358
359 }