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