1 // ========================================================================
2 // Copyright (c) 1996-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 package org.eclipse.jetty.util.resource;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.io.OutputStream;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.net.URLConnection;
22 import java.security.Permission;
23
24 import org.eclipse.jetty.util.URIUtil;
25 import org.eclipse.jetty.util.log.Log;
26
27 /* ------------------------------------------------------------ */
28 /** Abstract resource class.
29 */
30 public class URLResource extends Resource
31 {
32 protected URL _url;
33 protected String _urlString;
34
35 protected URLConnection _connection;
36 protected InputStream _in=null;
37 transient boolean _useCaches = Resource.__defaultUseCaches;
38
39 /* ------------------------------------------------------------ */
40 protected URLResource(URL url, URLConnection connection)
41 {
42 _url = url;
43 _urlString=_url.toString();
44 _connection=connection;
45 }
46
47 /* ------------------------------------------------------------ */
48 protected URLResource (URL url, URLConnection connection, boolean useCaches)
49 {
50 this (url, connection);
51 _useCaches = useCaches;
52 }
53
54 /* ------------------------------------------------------------ */
55 protected synchronized boolean checkConnection()
56 {
57 if (_connection==null)
58 {
59 try{
60 _connection=_url.openConnection();
61 _connection.setUseCaches(_useCaches);
62 }
63 catch(IOException e)
64 {
65 Log.ignore(e);
66 }
67 }
68 return _connection!=null;
69 }
70
71 /* ------------------------------------------------------------ */
72 /** Release any resources held by the resource.
73 */
74 @Override
75 public synchronized void release()
76 {
77 if (_in!=null)
78 {
79 try{_in.close();}catch(IOException e){Log.ignore(e);}
80 _in=null;
81 }
82
83 if (_connection!=null)
84 _connection=null;
85 }
86
87 /* ------------------------------------------------------------ */
88 /**
89 * Returns true if the represented resource exists.
90 */
91 @Override
92 public boolean exists()
93 {
94 try
95 {
96 synchronized(this)
97 {
98 if (checkConnection() && _in==null )
99 _in = _connection.getInputStream();
100 }
101 }
102 catch (IOException e)
103 {
104 Log.ignore(e);
105 }
106 return _in!=null;
107 }
108
109 /* ------------------------------------------------------------ */
110 /**
111 * Returns true if the respresenetd resource is a container/directory.
112 * If the resource is not a file, resources ending with "/" are
113 * considered directories.
114 */
115 @Override
116 public boolean isDirectory()
117 {
118 return exists() && _url.toString().endsWith("/");
119 }
120
121
122 /* ------------------------------------------------------------ */
123 /**
124 * Returns the last modified time
125 */
126 @Override
127 public long lastModified()
128 {
129 if (checkConnection())
130 return _connection.getLastModified();
131 return -1;
132 }
133
134
135 /* ------------------------------------------------------------ */
136 /**
137 * Return the length of the resource
138 */
139 @Override
140 public long length()
141 {
142 if (checkConnection())
143 return _connection.getContentLength();
144 return -1;
145 }
146
147 /* ------------------------------------------------------------ */
148 /**
149 * Returns an URL representing the given resource
150 */
151 @Override
152 public URL getURL()
153 {
154 return _url;
155 }
156
157 /* ------------------------------------------------------------ */
158 /**
159 * Returns an File representing the given resource or NULL if this
160 * is not possible.
161 */
162 @Override
163 public File getFile()
164 throws IOException
165 {
166 // Try the permission hack
167 if (checkConnection())
168 {
169 Permission perm = _connection.getPermission();
170 if (perm instanceof java.io.FilePermission)
171 return new File(perm.getName());
172 }
173
174 // Try the URL file arg
175 try {return new File(_url.getFile());}
176 catch(Exception e) {Log.ignore(e);}
177
178 // Don't know the file
179 return null;
180 }
181
182 /* ------------------------------------------------------------ */
183 /**
184 * Returns the name of the resource
185 */
186 @Override
187 public String getName()
188 {
189 return _url.toExternalForm();
190 }
191
192 /* ------------------------------------------------------------ */
193 /**
194 * Returns an input stream to the resource
195 */
196 @Override
197 public synchronized InputStream getInputStream()
198 throws java.io.IOException
199 {
200 if (!checkConnection())
201 throw new IOException( "Invalid resource");
202
203 try
204 {
205 if( _in != null)
206 {
207 InputStream in = _in;
208 _in=null;
209 return in;
210 }
211 return _connection.getInputStream();
212 }
213 finally
214 {
215 _connection=null;
216 }
217 }
218
219
220 /* ------------------------------------------------------------ */
221 /**
222 * Returns an output stream to the resource
223 */
224 @Override
225 public OutputStream getOutputStream()
226 throws java.io.IOException, SecurityException
227 {
228 throw new IOException( "Output not supported");
229 }
230
231 /* ------------------------------------------------------------ */
232 /**
233 * Deletes the given resource
234 */
235 @Override
236 public boolean delete()
237 throws SecurityException
238 {
239 throw new SecurityException( "Delete not supported");
240 }
241
242 /* ------------------------------------------------------------ */
243 /**
244 * Rename the given resource
245 */
246 @Override
247 public boolean renameTo( Resource dest)
248 throws SecurityException
249 {
250 throw new SecurityException( "RenameTo not supported");
251 }
252
253 /* ------------------------------------------------------------ */
254 /**
255 * Returns a list of resource names contained in the given resource
256 */
257 @Override
258 public String[] list()
259 {
260 return null;
261 }
262
263 /* ------------------------------------------------------------ */
264 /**
265 * Returns the resource contained inside the current resource with the
266 * given name
267 */
268 @Override
269 public Resource addPath(String path)
270 throws IOException,MalformedURLException
271 {
272 if (path==null)
273 return null;
274
275 path = URIUtil.canonicalPath(path);
276
277 return newResource(URIUtil.addPaths(_url.toExternalForm(),path));
278 }
279
280 /* ------------------------------------------------------------ */
281 @Override
282 public String toString()
283 {
284 return _urlString;
285 }
286
287 /* ------------------------------------------------------------ */
288 @Override
289 public int hashCode()
290 {
291 return _url.hashCode();
292 }
293
294 /* ------------------------------------------------------------ */
295 @Override
296 public boolean equals( Object o)
297 {
298 return o instanceof URLResource &&
299 _url.equals(((URLResource)o)._url);
300 }
301
302 public boolean getUseCaches ()
303 {
304 return _useCaches;
305 }
306
307 @Override
308 public boolean isContainedIn (Resource containingResource) throws MalformedURLException
309 {
310 return false; //TODO gregw check this!
311 }
312 }