1 17 package org.eclipse.emf.common.archive; 18 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.FileOutputStream ; 22 import java.io.FilterInputStream ; 23 import java.io.FilterOutputStream ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.io.OutputStream ; 27 import java.net.MalformedURLException ; 28 import java.net.URL ; 29 import java.net.URLConnection ; 30 import java.util.zip.ZipEntry ; 31 import java.util.zip.ZipFile ; 32 import java.util.zip.ZipInputStream ; 33 import java.util.zip.ZipOutputStream ; 34 35 72 public class ArchiveURLConnection extends URLConnection 73 { 74 77 protected String urlString; 78 79 83 public ArchiveURLConnection(URL url) 84 { 85 super(url); 86 urlString = url.toString(); 87 } 88 89 97 protected ArchiveURLConnection(String url) 98 { 99 super(null); 100 urlString = url; 101 } 102 103 120 protected boolean emulateArchiveScheme() 121 { 122 return false; 123 } 124 125 133 protected boolean useZipFile() 134 { 135 return false; 136 } 137 138 141 public void connect() throws IOException 142 { 143 connected = true; 144 } 145 146 150 public InputStream getInputStream() throws IOException 151 { 152 int archiveSeparator = urlString.indexOf("!/"); 155 if (archiveSeparator < 0) 156 { 157 throw new MalformedURLException ("missing archive separators " + urlString); 158 } 159 160 int start = urlString.indexOf(':') + 1; 163 if (start > urlString.length() || urlString.charAt(start) == '/') 164 { 165 throw 166 new IllegalArgumentException 167 ("archive protocol must be immediately followed by another URL protocol " + urlString); 168 } 169 170 for (int i = start, end = urlString.indexOf("/") - 1; (i = urlString.indexOf(":", i)) < end; ) 173 { 174 if (emulateArchiveScheme()) 175 { 176 start = ++i; 179 } 180 else 181 { 182 archiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 185 if (archiveSeparator < 0) 186 { 187 throw new MalformedURLException ("too few archive separators " + urlString); 188 } 189 ++i; 190 } 191 } 192 193 195 String nestedURL = urlString.substring(start, archiveSeparator); 198 199 int nextArchiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 202 203 InputStream inputStream; 206 if (!useZipFile() || !nestedURL.startsWith("file:")) 207 { 208 inputStream = createInputStream(nestedURL); 211 } 212 else 213 { 214 String entry = 217 nextArchiveSeparator < 0 ? 218 urlString.substring(archiveSeparator + 2) : 219 urlString.substring(archiveSeparator + 2, nextArchiveSeparator); 220 221 archiveSeparator = nextArchiveSeparator; 224 nextArchiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 225 226 final ZipFile zipFile = new ZipFile (nestedURL.substring(5)); 231 ZipEntry zipEntry = zipFile.getEntry(entry); 232 if (zipEntry == null) 233 { 234 throw new IOException ("archive entry not found " + entry); 235 } 236 inputStream = 237 new FilterInputStream (zipFile.getInputStream(zipEntry)) 238 { 239 public void close() throws IOException 240 { 241 super.close(); 242 zipFile.close(); 243 } 244 }; 245 } 246 247 LOOP: 250 while (archiveSeparator > 0) 251 { 252 String entry = 255 nextArchiveSeparator < 0 ? 256 urlString.substring(archiveSeparator + 2) : 257 urlString.substring(archiveSeparator + 2, nextArchiveSeparator); 258 259 ZipInputStream zipInputStream = new ZipInputStream (inputStream); 262 while (zipInputStream.available() >= 0) 263 { 264 ZipEntry zipEntry = zipInputStream.getNextEntry(); 265 if (zipEntry == null) 266 { 267 break; 268 } 269 else if (entry.equals(zipEntry.getName())) 270 { 271 inputStream = zipInputStream; 272 273 archiveSeparator = nextArchiveSeparator; 276 nextArchiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 277 continue LOOP; 278 } 279 } 280 281 break; 284 } 285 286 return inputStream; 287 } 288 289 294 protected InputStream createInputStream(String nestedURL) throws IOException 295 { 296 return new URL (nestedURL).openStream(); 297 } 298 299 303 public OutputStream getOutputStream() throws IOException 304 { 305 int archiveSeparator = urlString.indexOf("!/"); 308 if (archiveSeparator < 0) 309 { 310 throw new MalformedURLException ("missing archive separator in " + urlString); 311 } 312 313 int start = urlString.indexOf(':') + 1; 316 if (start > urlString.length() || urlString.charAt(start) == '/') 317 { 318 throw 319 new IllegalArgumentException 320 ("archive protocol must be immediately followed by another URL protocol " + urlString); 321 } 322 323 for (int i = start, end = urlString.indexOf("/") - 1; (i = urlString.indexOf(":", i)) < end; ) 326 { 327 if (emulateArchiveScheme()) 328 { 329 start = ++i; 332 } 333 else 334 { 335 archiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 338 if (archiveSeparator < 0) 339 { 340 throw new MalformedURLException ("too few archive separators in " + urlString); 341 } 342 ++i; 343 } 344 } 345 346 348 final String nestedURL = urlString.substring(start, archiveSeparator); 351 352 final File tempFile = File.createTempFile("Archive", "zip"); 356 357 InputStream sourceInputStream = null; 360 OutputStream tempOutputStream = null; 361 try 362 { 363 tempOutputStream = new FileOutputStream (tempFile); 366 sourceInputStream = createInputStream(nestedURL); 367 368 OutputStream outputStream = tempOutputStream; 371 InputStream inputStream = sourceInputStream; 372 373 int nextArchiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 376 377 ZipOutputStream zipOutputStream; 380 381 final byte [] bytes = new byte [4096]; 384 385 LOOP: 388 do 389 { 390 String entry = 393 nextArchiveSeparator < 0 ? 394 urlString.substring(archiveSeparator + 2) : 395 urlString.substring(archiveSeparator + 2, nextArchiveSeparator); 396 397 zipOutputStream = new ZipOutputStream (outputStream); 400 outputStream = zipOutputStream; 401 402 ZipInputStream zipInputStream = new ZipInputStream (inputStream); 405 inputStream = zipInputStream; 406 407 while (zipInputStream.available() >= 0) 410 { 411 ZipEntry zipEntry = zipInputStream.getNextEntry(); 415 if (zipEntry == null) 416 { 417 break; 418 } 419 else if (!entry.equals(zipEntry.getName())) 420 { 421 zipOutputStream.putNextEntry(zipEntry); 424 for (int size; (size = zipInputStream.read(bytes, 0, bytes.length)) > -1; ) 425 { 426 zipOutputStream.write(bytes, 0, size); 427 } 428 } 429 } 430 431 zipOutputStream.putNextEntry(new ZipEntry (entry)); 434 435 archiveSeparator = nextArchiveSeparator; 438 nextArchiveSeparator = urlString.indexOf("!/", archiveSeparator + 2); 439 } 440 while (archiveSeparator > 0); 441 442 tempOutputStream = null; 445 446 return 449 new FilterOutputStream (zipOutputStream) 450 { 451 protected boolean isClosed; 452 453 public void close() throws IOException 454 { 455 if (!isClosed) 458 { 459 isClosed = true; 460 461 super.close(); 464 465 if (nestedURL.startsWith("file:")) 469 { 470 File targetFile = new File (nestedURL.substring(5)); 471 if (!targetFile.delete()) 472 { 473 throw new IOException ("cannot delete " + targetFile.getPath()); 474 } 475 else if (!tempFile.renameTo(targetFile)) 476 { 477 throw new IOException ("cannot rename " + tempFile.getPath() + " to " + targetFile.getPath()); 478 } 479 } 480 else 481 { 482 InputStream inputStream = null; 486 OutputStream outputStream = null; 487 try 488 { 489 inputStream = new FileInputStream (tempFile); 490 outputStream = createOutputStream(nestedURL); 491 for (int size; (size = inputStream.read(bytes, 0, bytes.length)) > -1; ) 492 { 493 outputStream.write(bytes, 0, size); 494 } 495 } 496 finally 497 { 498 if (inputStream != null) 501 { 502 inputStream.close(); 503 } 504 if (outputStream != null) 505 { 506 outputStream.close(); 507 } 508 } 509 } 510 } 511 } 512 }; 513 } 514 finally 515 { 516 if (tempOutputStream != null) 519 { 520 tempOutputStream.close(); 521 } 522 523 if (sourceInputStream != null) 526 { 527 sourceInputStream.close(); 528 } 529 } 530 } 531 532 537 protected OutputStream createOutputStream(String nestedURL) throws IOException 538 { 539 URL url = new URL (nestedURL.toString()); 540 URLConnection urlConnection = url.openConnection(); 541 urlConnection.setDoOutput(true); 542 return urlConnection.getOutputStream(); 543 } 544 } 545 | Popular Tags |