1 11 package org.eclipse.core.internal.boot; 12 13 import java.io.*; 14 import java.net.URL ; 15 import java.net.URLConnection ; 16 import java.util.Enumeration ; 17 import java.util.Properties ; 18 import org.eclipse.core.internal.runtime.Activator; 19 import org.eclipse.core.internal.runtime.CommonMessages; 20 import org.eclipse.osgi.service.debug.DebugOptions; 21 import org.eclipse.osgi.util.NLS; 22 import org.osgi.framework.Version; 23 24 27 public abstract class PlatformURLConnection extends URLConnection { 28 29 private boolean isInCache = false; 31 private boolean isJar = false; 32 33 private URL resolvedURL = null; private URL cachedURL = null; 37 private URLConnection connection = null; 39 private static Properties cacheIndex = new Properties (); 41 private static String cacheLocation; 42 private static String indexName; 43 private static String filePrefix; 44 45 private static final int BUF_SIZE = 32768; 47 private static final Object NOT_FOUND = new Object (); private static final String CACHE_PROP = ".cache.properties"; private static final String CACHE_LOCATION_PROP = "location"; private static final String CACHE_INDEX_PROP = "index"; private static final String CACHE_PREFIX_PROP = "prefix"; private static final String CACHE_INDEX = ".index.properties"; private static final String CACHE_DIR = ".eclipse-" + PlatformURLHandler.PROTOCOL + File.separator; 55 private static final String OPTION_DEBUG = "org.eclipse.core.runtime/url/debug"; private static final String OPTION_DEBUG_CONNECT = OPTION_DEBUG + "/connect"; private static final String OPTION_DEBUG_CACHE_LOOKUP = OPTION_DEBUG + "/cachelookup"; private static final String OPTION_DEBUG_CACHE_COPY = OPTION_DEBUG + "/cachecopy"; 61 public final static boolean DEBUG; 62 public final static boolean DEBUG_CONNECT; 63 public final static boolean DEBUG_CACHE_LOOKUP; 64 public final static boolean DEBUG_CACHE_COPY; 65 66 static { 67 Activator activator = Activator.getDefault(); 68 if (activator == null) { 69 DEBUG = DEBUG_CONNECT = DEBUG_CACHE_LOOKUP = DEBUG_CACHE_COPY = false; 70 } else { 71 DebugOptions debugOptions = activator.getDebugOptions(); 72 if (debugOptions != null) { 73 DEBUG = debugOptions.getBooleanOption(OPTION_DEBUG, false); 74 DEBUG_CONNECT = debugOptions.getBooleanOption(OPTION_DEBUG_CONNECT, true); 75 DEBUG_CACHE_LOOKUP = debugOptions.getBooleanOption(OPTION_DEBUG_CACHE_LOOKUP, true); 76 DEBUG_CACHE_COPY = debugOptions.getBooleanOption(OPTION_DEBUG_CACHE_COPY, true); 77 } else 78 DEBUG = DEBUG_CONNECT = DEBUG_CACHE_LOOKUP = DEBUG_CACHE_COPY = false; 79 } 80 } 81 82 protected PlatformURLConnection(URL url) { 83 super(url); 84 } 85 86 protected boolean allowCaching() { 87 return false; 88 } 89 90 public void connect() throws IOException { 91 connect(false); 92 } 93 94 private synchronized void connect(boolean asLocal) throws IOException { 95 if (connected) 96 return; 97 98 if (shouldCache(asLocal)) { 99 try { 100 URL inCache = getURLInCache(); 101 if (inCache != null) 102 connection = inCache.openConnection(); 103 } catch (IOException e) { 104 } 106 } 107 108 if (connection == null) 110 connection = resolvedURL.openConnection(); 111 connected = true; 112 if (DEBUG && DEBUG_CONNECT) 113 debug("Connected as " + connection.getURL()); } 115 116 private void copyToCache() throws IOException { 119 120 if (isInCache | cachedURL == null) 121 return; 122 String tmp; 123 int ix; 124 125 String key; 127 if (isJar) { 128 tmp = url.getFile(); 129 ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR); 130 if (ix != -1) 131 tmp = tmp.substring(0, ix); 132 key = tmp; 133 } else 134 key = url.getFile(); 135 136 URL src; 138 if (isJar) { 139 tmp = resolvedURL.getFile(); 140 ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR); 141 if (ix != -1) 142 tmp = tmp.substring(0, ix); 143 src = new URL (tmp); 144 } else 145 src = resolvedURL; 146 InputStream srcis = null; 147 148 String tgt; 150 if (isJar) { 151 tmp = cachedURL.getFile(); 152 ix = tmp.indexOf(PlatformURLHandler.PROTOCOL_SEPARATOR); 153 if (ix != -1) 154 tmp = tmp.substring(ix + 1); 155 ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR); 156 if (ix != -1) 157 tmp = tmp.substring(0, ix); 158 tgt = tmp; 159 } else 160 tgt = cachedURL.getFile(); 161 File tgtFile = null; 162 FileOutputStream tgtos = null; 163 164 boolean error = false; 165 long total = 0; 166 167 try { 168 if (DEBUG && DEBUG_CACHE_COPY) { 169 if (isJar) 170 debug("Caching jar as " + tgt); else 172 debug("Caching as " + tgt); } 174 175 srcis = src.openStream(); 176 byte[] buf = new byte[BUF_SIZE]; 177 int count = srcis.read(buf); 178 179 tgtFile = new File(tgt); 180 tgtos = new FileOutputStream(tgtFile); 181 182 while (count != -1) { 183 total += count; 184 tgtos.write(buf, 0, count); 185 count = srcis.read(buf); 186 } 187 188 srcis.close(); 189 srcis = null; 190 tgtos.flush(); 191 tgtos.getFD().sync(); 192 tgtos.close(); 193 tgtos = null; 194 195 cacheIndex.put(key, tgt); 197 isInCache = true; 198 } catch (IOException e) { 199 error = true; 200 cacheIndex.put(key, NOT_FOUND); 201 if (DEBUG && DEBUG_CACHE_COPY) 203 debug("Failed to cache due to " + e); throw e; 205 } finally { 206 if (!error && DEBUG && DEBUG_CACHE_COPY) 207 debug(total + " bytes copied"); if (srcis != null) 209 srcis.close(); 210 if (tgtos != null) 211 tgtos.close(); 212 } 213 } 214 215 protected void debug(String s) { 216 System.out.println("URL " + getURL().toString() + "^" + Integer.toHexString(Thread.currentThread().hashCode()) + " " + s); } 218 219 private static void debugStartup(String s) { 220 System.out.println("URL " + s); } 222 223 public URL [] getAuxillaryURLs() throws IOException { 224 return null; 225 } 226 227 public synchronized InputStream getInputStream() throws IOException { 228 if (!connected) 229 connect(); 230 return connection.getInputStream(); 231 } 232 233 public URL getResolvedURL() { 234 return resolvedURL; 235 } 236 237 public URL getURLAsLocal() throws IOException { 238 connect(true); URL u = connection.getURL(); 240 String up = u.getProtocol(); 241 if (!up.equals(PlatformURLHandler.FILE) && !up.equals(PlatformURLHandler.JAR) && !up.startsWith(PlatformURLHandler.BUNDLE)) 242 throw new IOException(NLS.bind(CommonMessages.url_noaccess, up)); 243 return u; 244 } 245 246 private URL getURLInCache() throws IOException { 248 249 if (!allowCaching()) 250 return null; 252 if (isInCache) 253 return cachedURL; 254 255 if (cacheLocation == null | cacheIndex == null) 256 return null; 258 String file = ""; String jarEntry = null; 261 if (isJar) { 262 file = url.getFile(); 263 int ix = file.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR); 264 if (ix != -1) { 265 jarEntry = file.substring(ix + PlatformURLHandler.JAR_SEPARATOR.length()); 266 file = file.substring(0, ix); 267 } 268 } else { 269 file = url.getFile(); 270 } 271 272 String tmp = (String ) cacheIndex.get(file); 274 275 if (tmp != null && tmp == NOT_FOUND) 277 throw new IOException(); 278 279 if (tmp != null && !(new File(tmp)).exists()) { 281 tmp = null; 282 cacheIndex.remove(url.getFile()); 283 } 284 285 if (tmp != null) { 287 if (isJar) { 288 if (DEBUG && DEBUG_CACHE_LOOKUP) 289 debug("Jar located in cache as " + tmp); tmp = PlatformURLHandler.FILE + PlatformURLHandler.PROTOCOL_SEPARATOR + tmp + PlatformURLHandler.JAR_SEPARATOR + jarEntry; 291 cachedURL = new URL (PlatformURLHandler.JAR, null, -1, tmp); 292 } else { 293 if (DEBUG && DEBUG_CACHE_LOOKUP) 294 debug("Located in cache as " + tmp); cachedURL = new URL (PlatformURLHandler.FILE, null, -1, tmp); 296 } 297 isInCache = true; 298 } else { 299 int ix = file.lastIndexOf("/"); tmp = file.substring(ix + 1); 302 tmp = cacheLocation + filePrefix + Long.toString((new java.util.Date ()).getTime()) + "_" + tmp; tmp = tmp.replace(File.separatorChar, '/'); 304 if (isJar) { 305 tmp = PlatformURLHandler.FILE + PlatformURLHandler.PROTOCOL_SEPARATOR + tmp + PlatformURLHandler.JAR_SEPARATOR + jarEntry; 306 cachedURL = new URL (PlatformURLHandler.JAR, null, -1, tmp); 307 } else 308 cachedURL = new URL (PlatformURLHandler.FILE, null, -1, tmp); 309 copyToCache(); 310 } 311 312 return cachedURL; 313 } 314 315 319 protected URL resolve() throws IOException { 320 throw new IOException(); 322 } 323 324 protected String getId(String spec) { 325 String id = (String ) parse(spec)[0]; 326 return id == null ? spec : id; 327 } 328 329 protected String getVersion(String spec) { 330 Version version = (Version) parse(spec)[1]; 331 return version == null ? "" : version.toString(); } 333 334 private Object [] parse(String spec) { 335 String bsn = null; 336 Version version = null; 337 int underScore = spec.indexOf('_'); 338 while (underScore >= 0) { 339 bsn = spec.substring(0, underScore); 340 try { 341 version = Version.parseVersion(spec.substring(underScore + 1)); 342 } catch (IllegalArgumentException iae) { 343 underScore = spec.indexOf('_', underScore + 1); 345 continue; 346 } 347 break; 348 } 349 return new Object [] {bsn, version}; 350 } 351 352 void setResolvedURL(URL url) throws IOException { 353 if (url == null) 354 throw new IOException(); 355 if (resolvedURL != null) 356 return; 357 int ix = url.getFile().lastIndexOf(PlatformURLHandler.JAR_SEPARATOR); 358 isJar = -1 != ix; 359 if (isJar && !url.getProtocol().equals(PlatformURLHandler.JAR)) 362 url = new URL (PlatformURLHandler.JAR, "", -1, url.toExternalForm()); resolvedURL = url; 364 } 365 366 private boolean shouldCache(boolean asLocal) { 367 368 String rp = resolvedURL.getProtocol(); 370 String rf = resolvedURL.getFile(); 371 if (rp.equals(PlatformURLHandler.FILE)) 372 return false; 373 if (rp.equals(PlatformURLHandler.JAR) && (rf.startsWith(PlatformURLHandler.FILE))) 374 return false; 375 376 if (asLocal) 378 return true; 379 380 return true; 383 } 384 385 static void shutdown() { 386 if (indexName != null && cacheLocation != null) { 387 Enumeration keys = cacheIndex.keys(); 389 String key; 390 Object value; 391 while (keys.hasMoreElements()) { 392 key = (String ) keys.nextElement(); 393 value = cacheIndex.get(key); 394 if (value == NOT_FOUND) 395 cacheIndex.remove(key); 396 } 397 if (cacheIndex.size() == 0) 399 return; 400 try { 401 FileOutputStream fos = null; 403 fos = new FileOutputStream(cacheLocation + indexName); 404 try { 405 cacheIndex.store(fos, null); 406 fos.flush(); 407 fos.getFD().sync(); 408 } finally { 409 fos.close(); 410 } 411 } catch (IOException e) { 412 } 414 } 415 } 416 417 static void startup(String location, String os, String ws, String nl) { 419 verifyLocation(location); String cacheProps = location.trim(); 421 if (!cacheProps.endsWith(File.separator)) 422 cacheProps += File.separator; 423 cacheProps += CACHE_PROP; 424 File cachePropFile = new File(cacheProps); 425 Properties props = null; 426 FileInputStream fis; 427 428 if (cachePropFile.exists()) { 429 try { 431 props = new Properties (); 432 fis = new FileInputStream(cachePropFile); 433 try { 434 props.load(fis); 435 } finally { 436 fis.close(); 437 } 438 } catch (IOException e) { 439 props = null; 440 } 441 } 442 443 if (props == null) { 444 props = new Properties (); 446 447 String tmp = System.getProperty("user.home"); if (!tmp.endsWith(File.separator)) 449 tmp += File.separator; 450 tmp += CACHE_DIR; 451 props.put(CACHE_LOCATION_PROP, tmp); 452 453 tmp = Long.toString((new java.util.Date ()).getTime()); 454 props.put(CACHE_PREFIX_PROP, tmp); 455 456 tmp += CACHE_INDEX; 457 props.put(CACHE_INDEX_PROP, tmp); 458 459 FileOutputStream fos = null; 461 try { 462 fos = new FileOutputStream(cachePropFile); 463 try { 464 props.store(fos, null); 465 fos.flush(); 466 fos.getFD().sync(); 467 } finally { 468 fos.close(); 469 } 470 } catch (IOException e) { 471 } 473 } 474 475 filePrefix = (String ) props.get(CACHE_PREFIX_PROP); 477 indexName = (String ) props.get(CACHE_INDEX_PROP); 478 cacheLocation = (String ) props.get(CACHE_LOCATION_PROP); 479 480 if (DEBUG) { 481 debugStartup("Cache location: " + cacheLocation); debugStartup("Cache index: " + indexName); debugStartup("Cache file prefix: " + filePrefix); } 485 486 if (!verifyLocation(cacheLocation)) { 488 indexName = null; 489 cacheLocation = null; 490 if (DEBUG) 491 debugStartup("Failed to create cache directory structure. Caching suspended"); return; 493 } 494 495 if (cacheLocation != null && indexName != null) { 497 try { 498 fis = new FileInputStream(cacheLocation + indexName); 499 try { 500 cacheIndex.load(fis); 501 } finally { 502 fis.close(); 503 } 504 } catch (IOException e) { 505 if (DEBUG) 506 debugStartup("Failed to initialize cache"); } 508 } 509 } 510 511 private static boolean verifyLocation(String location) { 512 File cacheDir = new File(location); 514 if (cacheDir.exists()) 515 return true; 516 return cacheDir.mkdirs(); 517 } 518 } 519 | Popular Tags |