Map<String, Patch> load() { Map<String, Patch> patches = new HashMap<String, Patch>(); for (File file : patchDir.listFiles()) { if (file.exists() && file.getName().endsWith(".patch")) { try { Patch patch = load(file); patches.put(patch.getId(), patch); } catch (IOException e) { e.printStackTrace(); } } } return patches; }
Map<String, Result> install( final Collection<Patch> patches, boolean simulate, boolean synchronous) { try { // Compute individual patch results final Map<String, Result> results = new LinkedHashMap<String, Result>(); final Map<Bundle, String> toUpdate = new HashMap<Bundle, String>(); Map<String, BundleUpdate> allUpdates = new HashMap<String, BundleUpdate>(); for (Patch patch : patches) { String startup = readFully(new File(System.getProperty("karaf.base"), "etc/startup.properties")); String overrides = readFully(new File(System.getProperty("karaf.base"), "etc/overrides.properties")); List<BundleUpdate> updates = new ArrayList<BundleUpdate>(); Bundle[] allBundles = bundleContext.getBundles(); for (String url : patch.getBundles()) { JarInputStream jis = new JarInputStream(new URL(url).openStream()); jis.close(); Manifest manifest = jis.getManifest(); Attributes att = manifest != null ? manifest.getMainAttributes() : null; String sn = att != null ? att.getValue(Constants.BUNDLE_SYMBOLICNAME) : null; String vr = att != null ? att.getValue(Constants.BUNDLE_VERSION) : null; if (sn == null || vr == null) { continue; } Version v = VersionTable.getVersion(vr); VersionRange range = null; if (patch.getVersionRange(url) == null) { // default version range starts with x.y.0 as the lower bound Version lower = new Version(v.getMajor(), v.getMinor(), 0); // We can't really upgrade with versions such as 2.1.0 if (v.compareTo(lower) > 0) { range = new VersionRange(false, lower, v, true); } } else { range = new VersionRange(patch.getVersionRange(url)); } if (range != null) { for (Bundle bundle : allBundles) { Version oldV = bundle.getVersion(); if (bundle.getBundleId() != 0 && stripSymbolicName(sn).equals(stripSymbolicName(bundle.getSymbolicName())) && range.contains(oldV)) { String location = bundle.getLocation(); BundleUpdate update = new BundleUpdateImpl(sn, v.toString(), url, oldV.toString(), location); updates.add(update); // Merge result BundleUpdate oldUpdate = allUpdates.get(sn); if (oldUpdate != null) { Version upv = VersionTable.getVersion(oldUpdate.getNewVersion()); if (upv.compareTo(v) < 0) { allUpdates.put(sn, update); toUpdate.put(bundle, url); } } else { toUpdate.put(bundle, url); } } } } else { System.err.printf( "Skipping bundle %s - unable to process bundle without a version range configuration%n", url); } } if (!simulate) { new Offline(new File(System.getProperty("karaf.base"))) .applyConfigChanges(((PatchImpl) patch).getPatch()); } Result result = new ResultImpl( patch, simulate, System.currentTimeMillis(), updates, startup, overrides); results.put(patch.getId(), result); } // Apply results System.out.println("Bundles to update:"); for (Map.Entry<Bundle, String> e : toUpdate.entrySet()) { System.out.println( " " + e.getKey().getSymbolicName() + "/" + e.getKey().getVersion().toString() + " with " + e.getValue()); } if (simulate) { System.out.println("Running simulation only - no bundles are being updated at this time"); } else { System.out.println( "Installation will begin. The connection may be lost or the console restarted."); } System.out.flush(); if (!simulate) { Thread thread = new Thread() { public void run() { try { applyChanges(toUpdate); for (Patch patch : patches) { Result result = results.get(patch.getId()); ((PatchImpl) patch).setResult(result); saveResult(result); } } catch (Exception e) { e.printStackTrace(System.err); System.err.flush(); } } }; if (synchronous) { thread.run(); } else { thread.start(); } } return results; } catch (Exception e) { throw new PatchException(e); } }
Result install(Patch patch, boolean simulate, boolean synchronous) { Map<String, Result> results = install(Collections.singleton(patch), simulate, synchronous); return results.get(patch.getId()); }
void rollback(Patch patch, boolean force) throws PatchException { Result result = patch.getResult(); if (result == null) { throw new PatchException("Patch " + patch.getId() + " is not installed"); } Bundle[] allBundles = bundleContext.getBundles(); List<BundleUpdate> badUpdates = new ArrayList<BundleUpdate>(); for (BundleUpdate update : result.getUpdates()) { boolean found = false; Version v = Version.parseVersion(update.getNewVersion()); for (Bundle bundle : allBundles) { if (stripSymbolicName(bundle.getSymbolicName()) .equals(stripSymbolicName(update.getSymbolicName())) && bundle.getVersion().equals(v)) { found = true; break; } } if (!found) { badUpdates.add(update); } } if (!badUpdates.isEmpty() && !force) { StringBuilder sb = new StringBuilder(); sb.append("Unable to rollback patch ") .append(patch.getId()) .append(" because of the following missing bundles:\n"); for (BundleUpdate up : badUpdates) { sb.append("\t") .append(up.getSymbolicName()) .append("/") .append(up.getNewVersion()) .append("\n"); } throw new PatchException(sb.toString()); } Map<Bundle, String> toUpdate = new HashMap<Bundle, String>(); for (BundleUpdate update : result.getUpdates()) { Version v = Version.parseVersion(update.getNewVersion()); for (Bundle bundle : allBundles) { if (stripSymbolicName(bundle.getSymbolicName()) .equals(stripSymbolicName(update.getSymbolicName())) && bundle.getVersion().equals(v)) { toUpdate.put(bundle, update.getPreviousLocation()); } } } try { applyChanges(toUpdate); writeFully( new File(System.getProperty("karaf.base"), "etc/startup.properties"), ((ResultImpl) result).getStartup()); writeFully( new File(System.getProperty("karaf.base"), "etc/overrides.properties"), ((ResultImpl) result).getOverrides()); } catch (Exception e) { throw new PatchException( "Unable to rollback patch " + patch.getId() + ": " + e.getMessage(), e); } ((PatchImpl) patch).setResult(null); File file = new File(patchDir, result.getPatch().getId() + ".patch.result"); file.delete(); }
@Override public Iterable<Patch> download(URL url) { try { File file = new File(patchDir, Long.toString(System.currentTimeMillis()) + ".patch.tmp"); // Copy file InputStream is = null; OutputStream os = null; try { is = url.openStream(); os = new FileOutputStream(file); copy(is, os); } finally { close(is, os); } // Patch file List<Patch> patches = new ArrayList<Patch>(); // Try to unzip ZipFile zipFile = null; try { zipFile = new ZipFile(file); } catch (IOException e) { } if (zipFile != null) { File localRepoPath = new File(System.getProperty("karaf.base"), "system"); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if (!entry.isDirectory()) { String entryName = entry.getName(); if (entryName.startsWith("repository/")) { String fileName = entryName.substring("repository/".length()); File f = new File(localRepoPath, fileName); if (!f.isFile()) { f.getParentFile().mkdirs(); InputStream fis = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(f); try { copy(fis, fos); } finally { close(fis, fos); } } } else if (entryName.endsWith(".patch") && !entryName.contains("/")) { File f = new File(patchDir, entryName); if (!f.isFile()) { InputStream fis = zipFile.getInputStream(entry); FileOutputStream fos = new FileOutputStream(f); try { copy(fis, fos); } finally { close(fis, fos); } } Patch patch = load(f); f.renameTo(new File(patchDir, patch.getId() + ".patch")); patches.add(patch); } } } close(zipFile); file.delete(); } // If the file is not a zip/jar, assume it's a single patch file else { Patch patch = load(file); file.renameTo(new File(patchDir, patch.getId() + ".patch")); patches.add(patch); } return patches; } catch (Exception e) { throw new PatchException("Unable to download patch from url " + url, e); } }