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