1 19 package org.java.plugin.tools; 20 21 import java.io.BufferedInputStream ; 22 import java.io.BufferedOutputStream ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.ObjectInputStream ; 28 import java.io.ObjectOutputStream ; 29 import java.io.OutputStream ; 30 import java.io.Serializable ; 31 import java.net.URL ; 32 import java.util.Collection ; 33 import java.util.HashMap ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.zip.ZipEntry ; 39 import java.util.zip.ZipInputStream ; 40 import java.util.zip.ZipOutputStream ; 41 42 import org.java.plugin.ObjectFactory; 43 import org.java.plugin.PathResolver; 44 import org.java.plugin.registry.ManifestProcessingException; 45 import org.java.plugin.registry.PluginDescriptor; 46 import org.java.plugin.registry.PluginFragment; 47 import org.java.plugin.registry.PluginRegistry; 48 import org.java.plugin.registry.Version; 49 import org.java.plugin.util.IoUtil; 50 51 55 public final class PluginArchiver { 56 private static final String DESCRIPTOR_ENTRY_NAME = "JPF-DESCRIPTOR"; 58 66 public static void pack(final PluginDescriptor descr, 67 final PathResolver pathResolver, final File destFile) 68 throws IOException { 69 pack(pathResolver.resolvePath(descr, "/"), "JPF plug-in "+ descr.getId() + " of version " + descr.getVersion(), destFile); } 73 74 82 public static void pack(final PluginFragment fragment, 83 final PathResolver pathResolver, final File destFile) 84 throws IOException { 85 pack(pathResolver.resolvePath(fragment, "/"), "JPF plug-in fragment "+ fragment.getId() + " of version " + fragment.getVersion(), destFile); } 89 90 private static void pack(final URL url, final String comment, 91 final File destFile) throws IOException { 92 ZipOutputStream zipStrm = new ZipOutputStream ( 93 new BufferedOutputStream (new FileOutputStream ( 94 destFile, false))); 95 try { 96 zipStrm.setComment(comment); 97 File file = IoUtil.url2file(url); 98 if (file == null) { 99 throw new IOException ("resolved URL " + url + " is not local file system location pointer"); } 102 File [] files = file.listFiles(); 103 for (int i = 0; i < files.length; i++) { 104 packEntry(zipStrm, null, files[i]); 105 } 106 } finally { 107 zipStrm.close(); 108 } 109 } 110 111 119 public static Collection pack(final PluginRegistry registry, 120 final PathResolver pathResolver, final File destFile) 121 throws IOException { 122 return pack(registry, pathResolver, destFile, new Filter() { 123 public boolean accept(final String id, final Version version, 124 final boolean isFragment) { 125 return true; 126 } 127 }); 128 } 129 130 140 public static Collection pack(final PluginRegistry registry, 141 final PathResolver pathResolver, final File destFile, 142 final Filter filter) throws IOException { 143 Set result; 144 ZipOutputStream zipStrm = new ZipOutputStream ( 145 new BufferedOutputStream (new FileOutputStream ( 146 destFile, false))); 147 try { 148 zipStrm.setComment("JPF plug-ins archive"); ZipEntry entry = new ZipEntry (DESCRIPTOR_ENTRY_NAME); 150 entry.setComment("JPF plug-ins archive descriptor"); zipStrm.putNextEntry(entry); 152 result = writeDescripor(registry, filter, 153 new ObjectOutputStream (zipStrm)); 154 zipStrm.closeEntry(); 155 for (Iterator it = registry.getPluginDescriptors().iterator(); 156 it.hasNext();) { 157 PluginDescriptor descr = (PluginDescriptor) it.next(); 158 if (!result.contains(descr.getUniqueId())) { 159 continue; 160 } 161 URL url = pathResolver.resolvePath(descr, "/"); File file = IoUtil.url2file(url); 163 if (file == null) { 164 throw new IOException ("resolved URL " + url + " is not local file system location pointer"); } 167 entry = new ZipEntry (descr.getUniqueId() + "/"); entry.setComment("Content for JPF plug-in " + descr.getId() + " version " + descr.getVersion()); entry.setTime(file.lastModified()); 171 zipStrm.putNextEntry(entry); 172 File [] files = file.listFiles(); 173 for (int i = 0; i < files.length; i++) { 174 packEntry(zipStrm, entry, files[i]); 175 } 176 } 177 for (Iterator it = registry.getPluginFragments().iterator(); 178 it.hasNext();) { 179 PluginFragment fragment = (PluginFragment) it.next(); 180 if (!result.contains(fragment.getUniqueId())) { 181 continue; 182 } 183 URL url = pathResolver.resolvePath(fragment, "/"); File file = IoUtil.url2file(url); 185 if (file == null) { 186 throw new IOException ("resolved URL " + url + " is not local file system location pointer"); } 189 entry = new ZipEntry (fragment.getUniqueId() + "/"); entry.setComment("Content for JPF plug-in fragment " + fragment.getId() + " version " + fragment.getVersion()); 193 entry.setTime(file.lastModified()); 194 zipStrm.putNextEntry(entry); 195 File [] files = file.listFiles(); 196 for (int i = 0; i < files.length; i++) { 197 packEntry(zipStrm, entry, files[i]); 198 } 199 } 200 } finally { 201 zipStrm.close(); 202 } 203 return result; 204 } 205 206 private static void packEntry(final ZipOutputStream zipStrm, 207 final ZipEntry parentEntry, final File file) throws IOException { 208 String parentEntryName = (parentEntry == null) ? "" : parentEntry.getName(); 210 if (file.isFile()) { 211 ZipEntry entry = new ZipEntry (parentEntryName + file.getName()); 212 entry.setTime(file.lastModified()); 213 zipStrm.putNextEntry(entry); 214 BufferedInputStream fileStrm = new BufferedInputStream ( 215 new FileInputStream (file)); 216 try { 217 IoUtil.copyStream(fileStrm, zipStrm, 1024); 218 } finally { 219 fileStrm.close(); 220 } 221 return; 222 } 223 ZipEntry entry = new ZipEntry (parentEntryName + file.getName() 224 + "/"); entry.setTime(file.lastModified()); 226 zipStrm.putNextEntry(entry); 227 File [] files = file.listFiles(); 228 for (int i = 0; i < files.length; i++) { 229 packEntry(zipStrm, entry, files[i]); 230 } 231 } 232 233 247 public static Collection unpack(final URL archiveFile, 248 final PluginRegistry registry, final File destFolder) 249 throws ManifestProcessingException, IOException , 250 ClassNotFoundException { 251 return unpack(archiveFile, registry, destFolder, new Filter() { 252 public boolean accept(final String id, final Version version, 253 final boolean isFragment) { 254 return true; 255 } 256 }); 257 } 258 259 260 281 public static Collection unpack(final URL archiveFile, 282 final PluginRegistry registry, final File destFolder, 283 final Filter filter) throws IOException , 284 ManifestProcessingException, ClassNotFoundException { 285 Set result; 286 int count = 0; 287 ZipInputStream zipStrm = new ZipInputStream (new BufferedInputStream ( 288 archiveFile.openStream())); 289 try { 290 ZipEntry entry = zipStrm.getNextEntry(); 291 if (entry == null) { 293 throw new IOException ( 294 "invalid plug-ins archive, no entries found"); } 296 if (!DESCRIPTOR_ENTRY_NAME.equals(entry.getName())) { 297 throw new IOException ("invalid plug-ins archive " + archiveFile + ", entry " + DESCRIPTOR_ENTRY_NAME + " not found as first ZIP entry in the archive file"); } 301 ObjectInputStream strm = new ObjectInputStream (zipStrm); 302 result = readDescriptor(strm, registry, destFolder, filter); 303 entry = zipStrm.getNextEntry(); 304 while (entry != null) { 305 String name = entry.getName(); 306 if (name.endsWith("/") && (name.lastIndexOf('/', name.length() - 2) == -1)) { 308 String uid = name.substring(0, name.length() - 1); 309 if (!result.contains(uid)) { 310 entry = zipStrm.getNextEntry(); 311 continue; 312 } 313 count++; 314 } else { 315 int p = name.indexOf('/'); 316 if ((p == -1) || (p == 0) 317 || !result.contains(name.substring(0, p))) { 318 entry = zipStrm.getNextEntry(); 319 continue; 320 } 321 } 322 unpackEntry(zipStrm, entry, destFolder); 323 entry = zipStrm.getNextEntry(); 324 } 325 } finally { 326 zipStrm.close(); 327 } 328 if (result.size() != count) { 329 throw new IOException ("invalid plug-ins number (" + count + ") found in the archive, expected number according to " + "the archive descriptor is " + result.size()); } 333 return result; 334 } 335 336 353 public static Collection unpack(final URL archiveFile, 354 final File destFolder) throws ManifestProcessingException, 355 IOException , ClassNotFoundException { 356 return unpack(archiveFile, ObjectFactory.newInstance().createRegistry(), 357 destFolder); 358 } 359 360 376 public static Collection unpack(final URL archiveFile, 377 final File destFolder, final Filter filter) 378 throws ManifestProcessingException, IOException , 379 ClassNotFoundException { 380 return unpack(archiveFile, ObjectFactory.newInstance().createRegistry(), 381 destFolder, filter); 382 } 383 384 private static void unpackEntry(final ZipInputStream zipStrm, 385 final ZipEntry entry, final File destFolder) throws IOException { 386 String name = entry.getName(); 387 if (name.endsWith("/")) { File folder = new File (destFolder.getCanonicalPath() + "/" + name); if (!folder.exists() && !folder.mkdirs()) { 390 throw new IOException ("can't create folder " + folder); } 392 folder.setLastModified(entry.getTime()); 393 return; 394 } 395 File file = new File (destFolder.getCanonicalPath() + "/" + name); File folder = file.getParentFile(); 397 if (!folder.exists() && !folder.mkdirs()) { 398 throw new IOException ("can't create folder " + folder); } 400 OutputStream strm = new BufferedOutputStream ( 401 new FileOutputStream (file, false)); 402 try { 403 IoUtil.copyStream(zipStrm, strm, 1024); 404 } finally { 405 strm.close(); 406 } 407 file.setLastModified(entry.getTime()); 408 } 409 410 424 public static Collection readDescriptor(final URL archiveFile, 425 final PluginRegistry registry) 426 throws IOException , ClassNotFoundException , 427 ManifestProcessingException { 428 return readDescriptor(archiveFile, registry, new Filter() { 429 public boolean accept(final String id, final Version version, 430 final boolean isFragment) { 431 return true; 432 } 433 }); 434 } 435 436 457 public static Collection readDescriptor(final URL archiveFile, 458 final PluginRegistry registry, final Filter filter) 459 throws IOException , ClassNotFoundException , 460 ManifestProcessingException { 461 ZipInputStream zipStrm = new ZipInputStream (new BufferedInputStream ( 462 archiveFile.openStream())); 463 try { 464 ZipEntry entry = zipStrm.getNextEntry(); 465 if (entry == null) { 467 throw new IOException ( 468 "invalid plug-ins archive, no entries found"); } 470 if (!DESCRIPTOR_ENTRY_NAME.equals(entry.getName())) { 471 throw new IOException ("invalid plug-ins archive " + archiveFile + ", entry " + DESCRIPTOR_ENTRY_NAME + " not found as first ZIP entry in the archive file"); } 475 ObjectInputStream strm = new ObjectInputStream (zipStrm); 476 return readDescriptor(strm, registry, Util.getTempFolder(), filter); 477 } finally { 478 zipStrm.close(); 479 } 480 } 481 482 private static Set writeDescripor(final PluginRegistry registry, 483 final Filter filter, final ObjectOutputStream strm) 484 throws IOException { 485 Map result = new HashMap (); 486 for (Iterator it = registry.getPluginDescriptors().iterator(); 487 it.hasNext();) { 488 PluginDescriptor descr = (PluginDescriptor) it.next(); 489 if (!filter.accept(descr.getId(), descr.getVersion(), false)) { 490 continue; 491 } 492 result.put(descr.getUniqueId(), 493 new ArchiveDescriptorEntry(descr.getId(), 494 descr.getVersion(), false, 495 Util.readUrlContent(descr.getLocation()))); 496 } 497 for (Iterator it = registry.getPluginFragments().iterator(); 498 it.hasNext();) { 499 PluginFragment fragment = (PluginFragment) it.next(); 500 if (!filter.accept(fragment.getId(), fragment.getVersion(), true)) { 501 continue; 502 } 503 result.put(fragment.getUniqueId(), 504 new ArchiveDescriptorEntry(fragment.getId(), 505 fragment.getVersion(), true, 506 Util.readUrlContent(fragment.getLocation()))); 507 } 508 strm.writeObject(result.values().toArray( 509 new ArchiveDescriptorEntry[result.size()])); 510 return result.keySet(); 511 } 512 513 private static Set readDescriptor(final ObjectInputStream strm, 514 final PluginRegistry registry, final File tempFolder, 515 final Filter filter) throws IOException , ClassNotFoundException , 516 ManifestProcessingException { 517 ArchiveDescriptorEntry[] data = 518 (ArchiveDescriptorEntry[]) strm.readObject(); 519 Set urls = new HashSet (); 523 Set files = new HashSet (); 524 for (int i = 0; i < data.length; i++) { 525 if (!filter.accept(data[i].getId(), data[i].getVersion(), 526 data[i].isFragment())) { 527 continue; 528 } 529 File file = File.createTempFile("manifest.", null, tempFolder); file.deleteOnExit(); 531 OutputStream fileStrm = new BufferedOutputStream ( 532 new FileOutputStream (file, false)); 533 try { 534 fileStrm.write(data[i].getData()); 535 } finally { 536 fileStrm.close(); 537 } 538 files.add(file); 539 urls.add(IoUtil.file2url(file)); 540 } 541 Set result = new HashSet (); 542 try { 543 for (Iterator it = registry.register((URL []) urls.toArray( 544 new URL [urls.size()])).values().iterator(); it.hasNext();) { 545 Object obj = it.next(); 546 if (obj instanceof PluginDescriptor) { 547 result.add(((PluginDescriptor) obj).getUniqueId()); 548 } else if (obj instanceof PluginFragment) { 549 result.add(((PluginFragment) obj).getUniqueId()); 550 } else { 551 } 553 } 554 } finally { 555 for (Iterator it = files.iterator(); it.hasNext();) { 556 ((File ) it.next()).delete(); 557 } 558 } 559 return result; 560 } 561 562 private PluginArchiver() { 563 } 565 566 570 public static interface Filter { 571 579 boolean accept(String id, Version version, boolean isFragment); 580 } 581 582 private static class ArchiveDescriptorEntry implements Serializable { 583 private static final long serialVersionUID = 8749937247555974932L; 584 585 private final String id; 586 private final Version version; 587 private final boolean isFragment; 588 private final byte[] data; 589 590 protected ArchiveDescriptorEntry(final String anId, 591 final Version aVersion, final boolean fragment, 592 final byte[] aData) { 593 id = anId; 594 version = aVersion; 595 isFragment = fragment; 596 data = aData; 597 } 598 599 protected String getId() { 600 return id; 601 } 602 603 protected Version getVersion() { 604 return version; 605 } 606 607 protected boolean isFragment() { 608 return isFragment; 609 } 610 611 protected byte[] getData() { 612 return data; 613 } 614 } 615 } 616 | Popular Tags |