1 // ========================================================================
2 // Copyright 1996-2005 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 // ========================================================================
14 package org.mortbay.resource;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20 import java.net.MalformedURLException;
21 import java.net.URL;
22 import java.net.URLConnection;
23 import java.security.Permission;
24
25 import org.mortbay.log.Log;
26 import org.mortbay.util.URIUtil;
27
28 /* ------------------------------------------------------------ */
29 /** Abstract resource class.
30 *
31 * @author Nuno Pregui�a
32 * @author Greg Wilkins (gregw)
33 */
34 public class URLResource extends Resource
35 {
36
37
38 protected URL _url;
39 protected String _urlString;
40 protected transient URLConnection _connection;
41 protected transient InputStream _in=null;
42 transient boolean _useCaches = Resource.__defaultUseCaches;
43
44 /* ------------------------------------------------------------ */
45 protected URLResource(URL url, URLConnection connection)
46 {
47 _url = url;
48 _urlString=_url.toString();
49 _connection=connection;
50 }
51
52 protected URLResource (URL url, URLConnection connection, boolean useCaches)
53 {
54 this (url, connection);
55 _useCaches = useCaches;
56 }
57
58 /* ------------------------------------------------------------ */
59 protected synchronized boolean checkConnection()
60 {
61 if (_connection==null)
62 {
63 try{
64 _connection=_url.openConnection();
65 _connection.setUseCaches(_useCaches);
66 }
67 catch(IOException e)
68 {
69 Log.ignore(e);
70 }
71 }
72 return _connection!=null;
73 }
74
75 /* ------------------------------------------------------------ */
76 /** Release any resources held by the resource.
77 */
78 public synchronized void release()
79 {
80 if (_in!=null)
81 {
82 try{_in.close();}catch(IOException e){Log.ignore(e);}
83 _in=null;
84 }
85
86 if (_connection!=null)
87 _connection=null;
88 }
89
90 /* ------------------------------------------------------------ */
91 /**
92 * Returns true if the respresened resource exists.
93 */
94 public boolean exists()
95 {
96 try
97 {
98 synchronized(this)
99 {
100 if (checkConnection() && _in==null )
101 _in = _connection.getInputStream();
102 }
103 }
104 catch (IOException e)
105 {
106 Log.ignore(e);
107 }
108 return _in!=null;
109 }
110
111 /* ------------------------------------------------------------ */
112 /**
113 * Returns true if the respresenetd resource is a container/directory.
114 * If the resource is not a file, resources ending with "/" are
115 * considered directories.
116 */
117 public boolean isDirectory()
118 {
119 return exists() && _url.toString().endsWith("/");
120 }
121
122
123 /* ------------------------------------------------------------ */
124 /**
125 * Returns the last modified time
126 */
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 public long length()
140 {
141 if (checkConnection())
142 return _connection.getContentLength();
143 return -1;
144 }
145
146 /* ------------------------------------------------------------ */
147 /**
148 * Returns an URL representing the given resource
149 */
150 public URL getURL()
151 {
152 return _url;
153 }
154
155 /* ------------------------------------------------------------ */
156 /**
157 * Returns an File representing the given resource or NULL if this
158 * is not possible.
159 */
160 public File getFile()
161 throws IOException
162 {
163 // Try the permission hack
164 if (checkConnection())
165 {
166 Permission perm = _connection.getPermission();
167 if (perm instanceof java.io.FilePermission)
168 return new File(perm.getName());
169 }
170
171 // Try the URL file arg
172 try {return new File(_url.getFile());}
173 catch(Exception e) {Log.ignore(e);}
174
175 // Don't know the file
176 return null;
177 }
178
179 /* ------------------------------------------------------------ */
180 /**
181 * Returns the name of the resource
182 */
183 public String getName()
184 {
185 return _url.toExternalForm();
186 }
187
188 /* ------------------------------------------------------------ */
189 /**
190 * Returns an input stream to the resource
191 */
192 public synchronized InputStream getInputStream()
193 throws java.io.IOException
194 {
195 if (!checkConnection())
196 throw new IOException( "Invalid resource");
197
198 try
199 {
200 if( _in != null)
201 {
202 InputStream in = _in;
203 _in=null;
204 return in;
205 }
206 return _connection.getInputStream();
207 }
208 finally
209 {
210 _connection=null;
211 }
212 }
213
214
215 /* ------------------------------------------------------------ */
216 /**
217 * Returns an output stream to the resource
218 */
219 public OutputStream getOutputStream()
220 throws java.io.IOException, SecurityException
221 {
222 throw new IOException( "Output not supported");
223 }
224
225 /* ------------------------------------------------------------ */
226 /**
227 * Deletes the given resource
228 */
229 public boolean delete()
230 throws SecurityException
231 {
232 throw new SecurityException( "Delete not supported");
233 }
234
235 /* ------------------------------------------------------------ */
236 /**
237 * Rename the given resource
238 */
239 public boolean renameTo( Resource dest)
240 throws SecurityException
241 {
242 throw new SecurityException( "RenameTo not supported");
243 }
244
245 /* ------------------------------------------------------------ */
246 /**
247 * Returns a list of resource names contained in the given resource
248 */
249 public String[] list()
250 {
251 return null;
252 }
253
254 /* ------------------------------------------------------------ */
255 /**
256 * Returns the resource contained inside the current resource with the
257 * given name
258 */
259 public Resource addPath(String path)
260 throws IOException,MalformedURLException
261 {
262 if (path==null)
263 return null;
264
265 path = URIUtil.canonicalPath(path);
266
267 return newResource(URIUtil.addPaths(_url.toExternalForm(),path));
268 }
269
270 /* ------------------------------------------------------------ */
271 public String toString()
272 {
273 return _urlString;
274 }
275
276 /* ------------------------------------------------------------ */
277 public int hashCode()
278 {
279 return _url.hashCode();
280 }
281
282 /* ------------------------------------------------------------ */
283 public boolean equals( Object o)
284 {
285 return o instanceof URLResource &&
286 _url.equals(((URLResource)o)._url);
287 }
288
289 public boolean getUseCaches ()
290 {
291 return _useCaches;
292 }
293 }