diff options
author | Jeff McAffer | 2007-11-09 04:22:59 +0000 |
---|---|---|
committer | Jeff McAffer | 2007-11-09 04:22:59 +0000 |
commit | fcea91b2f7245eed48cd1567632b3abdeaef85c6 (patch) | |
tree | db4d3df7796765a629a0ce3721b07a22b13919a6 /bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox | |
parent | fc90971ca172753f1bbb91cedb638771fdab18fd (diff) | |
download | rt.equinox.p2-fcea91b2f7245eed48cd1567632b3abdeaef85c6.tar.gz rt.equinox.p2-fcea91b2f7245eed48cd1567632b3abdeaef85c6.tar.xz rt.equinox.p2-fcea91b2f7245eed48cd1567632b3abdeaef85c6.zip |
update the JarDelta optimizer/processors, integrate with JBdiff and add some tests
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox')
13 files changed, 436 insertions, 91 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Activator.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/Activator.java index c451de00a..cfcd1e8d9 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Activator.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/Activator.java @@ -7,14 +7,13 @@ * Contributors: IBM Corporation - initial API and implementation ******************************************************************************/ -package org.eclipse.equinox.internal.p2.artifact.optimizers.jbdiff; +package org.eclipse.equinox.internal.p2.artifact.optimizers; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { - - public static final String ID = "org.eclipse.equinox.p2.artifact.optimizer.jbdiff"; //$NON-NLS-1$ + public static final String ID = "org.eclipse.equinox.p2.artifact.optimizers"; //$NON-NLS-1$ private static BundleContext context = null; public static BundleContext getContext() { diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Activator.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Activator.java deleted file mode 100644 index e23c1354c..000000000 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Activator.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This - * program and the accompanying materials are made available under the terms of - * the Eclipse Public License v1.0 which accompanies this distribution, and is - * available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: IBM Corporation - initial API and implementation - ******************************************************************************/ - -package org.eclipse.equinox.internal.p2.artifact.optimizers.jardelta; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class Activator implements BundleActivator { - public static final String ID = "org.eclipse.equinox.p2.artifact.optimizer.jardelta"; //$NON-NLS-1$ - private static BundleContext context = null; - - public static BundleContext getContext() { - return context; - } - - public void start(BundleContext context) throws Exception { - Activator.context = context; - } - - public void stop(BundleContext context) throws Exception { - } - -} diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Application.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Application.java index 02944bf90..d16090f38 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Application.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Application.java @@ -12,19 +12,25 @@ import java.net.URL; import java.util.Map; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepository; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepositoryManager; +/** + * The optimizer <code>Application</code> for JBDiff based optimizations. + */ public class Application implements IApplication { private URL artifactRepositoryLocation; + private int width = 1; + private int depth = 1; public Object start(IApplicationContext context) throws Exception { Map args = context.getArguments(); - initializeFromArguments((String[]) args.get("application.args")); + initializeFromArguments((String[]) args.get("application.args")); //$NON-NLS-1$ IArtifactRepository repository = setupRepository(artifactRepositoryLocation); - // TODO add the processing in here. + new Optimizer(repository, width, depth).run(); return null; } @@ -37,6 +43,7 @@ public class Application implements IApplication { } public void stop() { + // nothing to do yet } public void initializeFromArguments(String[] args) throws Exception { @@ -54,8 +61,15 @@ public class Application implements IApplication { continue; String arg = args[++i]; - if (args[i - 1].equalsIgnoreCase("-artifactRepository") | args[i - 1].equalsIgnoreCase("-ar")) + if (args[i - 1].equalsIgnoreCase("-artifactRepository") || args[i - 1].equalsIgnoreCase("-ar")) //$NON-NLS-1$ //$NON-NLS-2$ artifactRepositoryLocation = new URL(arg); + + if (args[i - 1].equalsIgnoreCase("-depth")) //$NON-NLS-1$ + depth = Integer.parseInt(arg); + + if (args[i - 1].equalsIgnoreCase("-width")) //$NON-NLS-1$ + width = Integer.parseInt(arg); + } } } diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/DeltaComputer.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/DeltaComputer.java index bb101d077..a176e939a 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/DeltaComputer.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/DeltaComputer.java @@ -1,3 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ package org.eclipse.equinox.internal.p2.artifact.optimizers.jardelta; import java.io.*; @@ -34,18 +44,23 @@ public class DeltaComputer { private void writeDelta() { JarOutputStream result = null; try { - result = new JarOutputStream(new FileOutputStream(destination)); - // write out the removals. These are all the entries left in the baseEntries - // since they were not seen in the targetJar. Here just write out an empty - // entry with a name that signals the delta processor to delete. - for (Iterator i = baseEntries.iterator(); i.hasNext();) - writeEntry(result, new JarEntry(((JarEntry) i.next()).getName() + ".delete"), null); - // write out the additions. - for (Iterator i = additions.iterator(); i.hasNext();) - writeEntry(result, (JarEntry) i.next(), targetJar); - // write out the changes. - for (Iterator i = changes.iterator(); i.hasNext();) - writeEntry(result, (JarEntry) i.next(), targetJar); + try { + result = new JarOutputStream(new FileOutputStream(destination)); + // write out the removals. These are all the entries left in the baseEntries + // since they were not seen in the targetJar. Here just write out an empty + // entry with a name that signals the delta processor to delete. + for (Iterator i = baseEntries.iterator(); i.hasNext();) + writeEntry(result, new JarEntry(((String) i.next()) + ".delete"), null); + // write out the additions. + for (Iterator i = additions.iterator(); i.hasNext();) + writeEntry(result, (JarEntry) i.next(), targetJar); + // write out the changes. + for (Iterator i = changes.iterator(); i.hasNext();) + writeEntry(result, (JarEntry) i.next(), targetJar); + } finally { + if (result != null) + result.close(); + } } catch (IOException e) { e.printStackTrace(); return; @@ -95,8 +110,8 @@ public class DeltaComputer { } private void computeDelta() { - ArrayList changes = new ArrayList(); - ArrayList additions = new ArrayList(); + changes = new ArrayList(); + additions = new ArrayList(); // start out assuming that all the base entries are being removed baseEntries = getEntries(baseJar); for (Enumeration e = targetJar.entries(); e.hasMoreElements();) { @@ -145,25 +160,30 @@ public class DeltaComputer { return; } // now we know each JAR has an entry for the name, compare and see how/if they differ - boolean changed = equals(entry, baseEntry); + boolean changed = !equals(entry, baseEntry); if (changed) changes.add(entry); - baseEntries.remove(baseEntry); + baseEntries.remove(baseEntry.getName()); } // compare the two entries. We already know that they have the same name. private boolean equals(JarEntry entry, JarEntry baseEntry) { if (entry.getSize() != baseEntry.getSize()) return false; - if (entry.getTime() != baseEntry.getTime()) + // make sure the entries are of the same type + if (entry.isDirectory() != baseEntry.isDirectory()) return false; + // if the entries are files then compare the times. + if (!entry.isDirectory()) + if (entry.getTime() != baseEntry.getTime()) + return false; return true; } private Set getEntries(JarFile jar) { HashSet result = new HashSet(jar.size()); for (Enumeration e = jar.entries(); e.hasMoreElements();) - result.add(e.nextElement()); + result.add(((JarEntry) e.nextElement()).getName()); return result; } } diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/JarDeltaOptimizerStep.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/JarDeltaOptimizerStep.java new file mode 100644 index 000000000..968bb77e9 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/JarDeltaOptimizerStep.java @@ -0,0 +1,122 @@ +/******************************************************************************* +* Copyright (c) 2007 compeople AG and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* compeople AG (Stefan Liebig) - initial API and implementation +* IBM - continuing development +*******************************************************************************/ +package org.eclipse.equinox.internal.p2.artifact.optimizers.jardelta; + +import java.io.*; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; +import org.eclipse.equinox.internal.p2.artifact.optimizers.jbdiff.AbstractDeltaDiffStep; +import org.eclipse.equinox.internal.p2.core.helpers.FileUtils; +import org.eclipse.equinox.p2.artifact.repository.*; + +/** + * The Pack200Packer expects an input containing normal ".jar" data. + */ +public class JarDeltaOptimizerStep extends AbstractDeltaDiffStep { + private static final String JAR_SUFFIX = ".jar"; //$NON-NLS-1$ + + private File incoming; + private OutputStream tempStream; + + protected JarDeltaOptimizerStep(IArtifactRepository repository) { + super(repository); + } + + public void write(int b) throws IOException { + OutputStream stream = getOutputStream(); + stream.write(b); + } + + private OutputStream getOutputStream() throws IOException { + if (tempStream != null) + return tempStream; + // store input stream in temporary file + incoming = File.createTempFile("p2.jardelta.optimizer.incoming", JAR_SUFFIX); + tempStream = new BufferedOutputStream(new FileOutputStream(incoming)); + return tempStream; + } + + private void performOptimization() throws IOException { + File predecessor = null; + File resultFile = null; + try { + // get the predecessor and perform the optimization into a temp file + predecessor = fetchPredecessor(new ArtifactDescriptor(key)); + resultFile = File.createTempFile("p2.jardelta.optimizer.result", JAR_SUFFIX); + new DeltaComputer(predecessor, incoming, resultFile).run(); + + // now write the optimized content to the destination + if (resultFile.length() > 0) { + InputStream resultStream = new BufferedInputStream(new FileInputStream(resultFile)); + FileUtils.copyStream(resultStream, true, destination, false); + } else { + status = new Status(IStatus.ERROR, Activator.ID, "Empty optimized file: " + resultFile); + } + } finally { + // if we have a predecessor and it is our temp file then clean up the file + if (predecessor != null && predecessor.getAbsolutePath().indexOf("p2.jardelta.predecessor") > -1) + predecessor.delete(); + if (resultFile != null) + resultFile.delete(); + } + } + + private File fetchPredecessor(ArtifactDescriptor descriptor) { + if (repository instanceof IFileArtifactRepository) + return ((IFileArtifactRepository) repository).getArtifactFile(descriptor); + File result = null; + OutputStream resultStream = null; + try { + try { + result = File.createTempFile("p2.jardelta.predecessor", JAR_SUFFIX); + resultStream = new BufferedOutputStream(new FileOutputStream(result)); + status = repository.getArtifact(descriptor, resultStream, monitor); + return result; + } finally { + if (resultStream != null) + resultStream.close(); + } + } catch (IOException e) { + } + return null; + } + + public void close() throws IOException { + // When we go to close we must have seen all the content we are going to see. + // If no one wrote to the temp stream then there is nothing to do. Be sure to delete the + // the temporary file if any. + if (tempStream == null) { + if (incoming != null) + incoming.delete(); + return; + } + + // So there is content. Close the temporary stream and perform the optimization. + // Performing the optimization should result in the new content being written to + // the destination. Make sure we delete the temporary file if any. + try { + tempStream.close(); + performOptimization(); + } finally { + if (incoming != null) + incoming.delete(); + } + + super.close(); + // TODO need to get real status here. sometimes the optimizers do not give + // any reasonable return status + if (status == null) + status = Status.OK_STATUS; + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Optimizer.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Optimizer.java new file mode 100644 index 000000000..a321cd804 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jardelta/Optimizer.java @@ -0,0 +1,241 @@ +/******************************************************************************* +* Copyright (c) 2007 compeople AG and others. +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +* +* Contributors: +* compeople AG (Stefan Liebig) - initial API and implementation +* IBM Corporation - adaptation to JAR deltas and on-going development +*******************************************************************************/ +package org.eclipse.equinox.internal.p2.artifact.optimizers.jardelta; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.*; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.artifact.optimizers.jbdiff.ArtifactKeyDeSerializer; +import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; +import org.eclipse.equinox.p2.artifact.repository.*; +import org.eclipse.equinox.p2.artifact.repository.processing.*; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.osgi.framework.Version; + +public class Optimizer { + + private IArtifactRepository repository; + private int width; + private int depth; + + private static final String JAR_DELTA_FORMAT = "jarDelta"; //$NON-NLS-1$ + private static final String JAR_DELTA_PATCH_STEP = "org.eclipse.equinox.p2.processing.JarDeltaPatchStep"; //$NON-NLS-1$ + + private static final Comparator ARTIFACT_DESCRIPTOR_VERSION_COMPARATOR = new ArtifactDescriptorVersionComparator(); + private static final Comparator ARTIFACT_KEY_VERSION_COMPARATOR = new ArtifactKeyVersionComparator(); + + /** + * This optimizer performs delta generation based on (currently) jbdiff. + * The optimization can be controlled with the ´width´ and the ´depth´ parameter. + * ´width´ defines for how many ´related´ artifact keys a delta should be generated, + * starting from the most up-to-date. + * ´depth´ defines to how many predecessor a delta should be generated. + * + * With AK(c-v) : AK - artifact key, c - artifact id, v - artifact version + * the ´repository content´ can be viewed a two dimensional array, where the + * artifact keys for the same component are in order of their version: + * <pre><code> + * w=1 w=2 + * | | + * | +------.------------+ d=2 + * | | +----.---+ d=1 | + * | | | | | v + * [ v | | v v v + * [ AK(x,2.0) AK(x,1.5) AK(x,1.1) ] + * [ AK(y,2.0) AK(y,1.9) ] + * [ AK(z,2.0) AK(z,1.5) AK(z,1.3) AK(z,1.0) ] + * ] + * </code></pre> + * E.g: with a ´width´ of one and a ´depth´ of two the optimizer would + * create two deltas for component ´x´ from 1.5 to 2.0 and from 1.1 to 2.0. + * + * @param repository + * @param width + * @param depth + */ + public Optimizer(IArtifactRepository repository, int width, int depth) { + this.repository = repository; + this.width = width; + this.depth = depth; + } + + public void run() { + System.out.println("Starting delta (jardelta) optimizations (width=" + width + ", depth=" + depth + ")"); + IArtifactKey[][] keys = getSortedRelatedArtifactKeys(repository.getArtifactKeys()); + for (int i = 0; i < keys.length; i++) { + if (keys[i].length < 2) + // Nothing to diff here! + continue; + int minWidth = Math.min(width, keys[i].length); + for (int j = 0; j < minWidth; j++) { + IArtifactKey key = keys[i][j]; + boolean isArchive = key.getClassifier().equals("plugin"); //$NON-NLS-1$ + optimize(keys[i], key); + } + } + System.out.println("Done."); + + } + + private void optimize(IArtifactKey[] keys, IArtifactKey key) { + IArtifactDescriptor[] descriptors = repository.getArtifactDescriptors(key); + IArtifactDescriptor canonical = null; + for (int k = 0; k < descriptors.length; k++) { + IArtifactDescriptor descriptor = descriptors[k]; + boolean optimized = false; + if (isCanonical(descriptor)) + canonical = descriptor; + else + optimized |= isOptimized(descriptor); + if (!optimized) + optimize(canonical, keys); + } + } + + private IArtifactKey getVersionlessKey(IArtifactKey key) { + return new ArtifactKey(key.getNamespace(), key.getClassifier(), key.getId(), Version.emptyVersion); + } + + /** + * This method retrieves a list of list of IArtifactKeys. The artifact keys in the + * list of artifact keys are all ´strongly related´ to each other such that are + * equal but not considering the versions. This list is sorted such that the + * newer versions are first in the list.<p> + * With AK(c-v) : AK - artifact key, c - artifact id, v - artifact version + * the result is than, e.g. + * <pre><code> + * [ + * [ AK(x,2.0) AK(x,1.5) AK(x,1.1) ] + * [ AK(y,2.0) AK(y,1.9) ] + * [ AK(z,2.0) AK(z,1.5) AK(z,1.3) AK(z,1.0) ] + * ] + * </code></pre> + * @param artifactKeys + * @return the sorted artifact keys + */ + private IArtifactKey[][] getSortedRelatedArtifactKeys(IArtifactKey[] artifactKeys) { + Map map = new HashMap(); + for (int i = 0; i < artifactKeys.length; i++) { + IArtifactKey freeKey = getVersionlessKey(artifactKeys[i]); + List values = (List) map.get(freeKey); + if (values == null) { + values = new ArrayList(); + map.put(freeKey, values); + } + values.add(artifactKeys[i]); + } + IArtifactKey[][] lists = new IArtifactKey[map.size()][]; + int i = 0; + for (Iterator iterator = map.values().iterator(); iterator.hasNext();) { + List artifactKeyList = (List) iterator.next(); + IArtifactKey[] relatedArtifactKeys = (IArtifactKey[]) artifactKeyList.toArray(new IArtifactKey[artifactKeyList.size()]); + Arrays.sort(relatedArtifactKeys, ARTIFACT_KEY_VERSION_COMPARATOR); + lists[i++] = relatedArtifactKeys; + } + int candidates = 0; + for (int ii = 0; ii < lists.length; ii++) { + for (int jj = 0; jj < lists[ii].length; jj++) { + System.out.println(lists[ii][jj] + ", "); + } + System.out.println(""); + if (lists[ii].length > 1) + candidates++; + } + System.out.println("Candidates found: " + candidates); + return lists; + } + + private void optimize(IArtifactDescriptor canonical, IArtifactKey[] relatedArtifactKeys) { + System.out.println("Optimizing " + canonical); + + IArtifactDescriptor[] descriptors = getSortedCompletePredecessors(canonical.getArtifactKey(), relatedArtifactKeys); + + int minDepth = Math.min(depth, descriptors.length); + for (int i = 0; i < minDepth; i++) { + System.out.println("\t with jar delta against " + descriptors[i].getArtifactKey()); + String predecessorData = ArtifactKeyDeSerializer.serialize(descriptors[i].getArtifactKey()); + ArtifactDescriptor newDescriptor = new ArtifactDescriptor(canonical); + ProcessingStepDescriptor patchStep = new ProcessingStepDescriptor(JAR_DELTA_PATCH_STEP, predecessorData, true); + ProcessingStepDescriptor[] steps = new ProcessingStepDescriptor[] {patchStep}; + newDescriptor.setProcessingSteps(steps); + newDescriptor.setProperty(IArtifactDescriptor.FORMAT, JAR_DELTA_FORMAT); + OutputStream repositoryStream = null; + try { + repositoryStream = repository.getOutputStream(newDescriptor); + + // Add in all the processing steps needed to optimize (e.g., pack200, ...) + ProcessingStep optimizerStep = new JarDeltaOptimizerStep(repository); + optimizerStep.initialize(patchStep, newDescriptor); + ProcessingStepHandler handler = new ProcessingStepHandler(); + OutputStream destination = handler.link(new ProcessingStep[] {optimizerStep}, repositoryStream, null); + + // Do the actual work by asking the repo to get the artifact and put it in the destination. + repository.getArtifact(canonical, destination, new NullProgressMonitor()); + } finally { + if (repositoryStream != null) + try { + repositoryStream.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + private IArtifactDescriptor[] getSortedCompletePredecessors(IArtifactKey artifactKey, IArtifactKey[] relatedArtifactKeys) { + // get all artifact keys + List completeDescriptors = new ArrayList(relatedArtifactKeys.length); + for (int i = 0; i < relatedArtifactKeys.length; i++) { + // if we find ´our self´ skip + if (relatedArtifactKeys[i].equals(artifactKey)) + continue; + // look for a complete artifact descriptor of the current key + IArtifactDescriptor[] descriptors = repository.getArtifactDescriptors(relatedArtifactKeys[i]); + for (int j = 0; j < descriptors.length; j++) { + if (isCanonical(descriptors[j])) { + completeDescriptors.add(descriptors[j]); + break; + } + } + } + + IArtifactDescriptor[] completeSortedDescriptors = (IArtifactDescriptor[]) completeDescriptors.toArray(new IArtifactDescriptor[completeDescriptors.size()]); + // Sort, so to allow a depth lookup! + Arrays.sort(completeSortedDescriptors, ARTIFACT_DESCRIPTOR_VERSION_COMPARATOR); + return completeSortedDescriptors; + } + + private boolean isOptimized(IArtifactDescriptor descriptor) { + if (descriptor.getProcessingSteps().length != 1) + return false; + return JAR_DELTA_FORMAT.equals(descriptor.getProperty(IArtifactDescriptor.FORMAT)); + } + + private boolean isCanonical(IArtifactDescriptor descriptor) { + // TODO length != 0 is not necessarily an indicator for not being canonical! + return descriptor.getProcessingSteps().length == 0; + } + + static final class ArtifactDescriptorVersionComparator implements Comparator { + public int compare(Object artifactDescriptor0, Object artifactDescriptor1) { + return -1 * ((IArtifactDescriptor) artifactDescriptor0).getArtifactKey().getVersion().compareTo(((IArtifactDescriptor) artifactDescriptor1).getArtifactKey().getVersion()); + } + } + + static final class ArtifactKeyVersionComparator implements Comparator { + public int compare(Object artifactKey0, Object artifactKey1) { + return -1 * ((IArtifactKey) artifactKey0).getVersion().compareTo(((IArtifactKey) artifactKey1).getVersion()); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/AbstractDeltaDiffStep.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/AbstractDeltaDiffStep.java index acf6e24b9..0b53dfe8a 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/AbstractDeltaDiffStep.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/AbstractDeltaDiffStep.java @@ -12,6 +12,7 @@ package org.eclipse.equinox.internal.p2.artifact.optimizers.jbdiff; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; import org.eclipse.equinox.p2.artifact.repository.IArtifactDescriptor; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepository; import org.eclipse.equinox.p2.artifact.repository.processing.ProcessingStep; diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Application.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Application.java index dc657e124..1e328d9a1 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Application.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Application.java @@ -12,6 +12,7 @@ import java.net.URL; import java.util.Map; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepository; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepositoryManager; diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Optimizer.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Optimizer.java index 698346f37..224cc978c 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Optimizer.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/jbdiff/Optimizer.java @@ -96,7 +96,7 @@ public class Optimizer { IArtifactDescriptor complete = null; for (int k = 0; k < descriptors.length; k++) { IArtifactDescriptor descriptor = descriptors[k]; - if (isComplete(descriptor)) + if (isCanonical(descriptor)) complete = descriptor; else if (isOptimized(descriptor, proposedStrategy)) { proposedStrategy = null; @@ -219,7 +219,7 @@ public class Optimizer { // look for a complete artifact descriptor of the current key IArtifactDescriptor[] descriptors = repository.getArtifactDescriptors(relatedArtifactKeys[i]); for (int j = 0; j < descriptors.length; j++) { - if (isComplete(descriptors[j])) { + if (isCanonical(descriptors[j])) { completeDescriptors.add(descriptors[j]); break; } @@ -238,7 +238,7 @@ public class Optimizer { return stepId.equals(descriptor.getProcessingSteps()[0].getProcessorId()); } - private boolean isComplete(IArtifactDescriptor descriptor) { + private boolean isCanonical(IArtifactDescriptor descriptor) { // TODO length != 0 is not necessarily an indicator for not being complete! return descriptor.getProcessingSteps().length == 0; } diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Activator.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Activator.java deleted file mode 100644 index 91577f88d..000000000 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Activator.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 IBM Corporation and others. All rights reserved. This - * program and the accompanying materials are made available under the terms of - * the Eclipse Public License v1.0 which accompanies this distribution, and is - * available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: IBM Corporation - initial API and implementation - ******************************************************************************/ - -package org.eclipse.equinox.internal.p2.artifact.optimizers.pack200; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class Activator implements BundleActivator { - public static final String ID = "org.eclipse.equinox.p2.artifact.optimizer.pack200"; //$NON-NLS-1$ - private static BundleContext context = null; - - public static BundleContext getContext() { - return context; - } - - public void start(BundleContext context) throws Exception { - Activator.context = context; - } - - public void stop(BundleContext context) throws Exception { - } - -} diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Application.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Application.java index ae0e7c37f..ed5194076 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Application.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Application.java @@ -12,6 +12,7 @@ import java.net.URL; import java.util.Map; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepository; import org.eclipse.equinox.p2.artifact.repository.IArtifactRepositoryManager; diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Optimizer.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Optimizer.java index a8ab38c40..15501dcc6 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Optimizer.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Optimizer.java @@ -31,19 +31,24 @@ public class Optimizer { if (!key.getClassifier().equals("plugin")) continue; IArtifactDescriptor[] descriptors = repository.getArtifactDescriptors(key); - IArtifactDescriptor complete = null; + IArtifactDescriptor canonical = null; boolean optimized = false; for (int j = 0; j < descriptors.length; j++) { IArtifactDescriptor descriptor = descriptors[j]; - if (descriptor.getProcessingSteps().length == 0) - complete = descriptor; + if (isCanonical(descriptor)) + canonical = descriptor; optimized |= isOptimized(descriptor); } if (!optimized) - optimize(complete); + optimize(canonical); } } + private boolean isCanonical(IArtifactDescriptor descriptor) { + // TODO length != 0 is not necessarily an indicator for not being complete! + return descriptor.getProcessingSteps().length == 0; + } + private void optimize(IArtifactDescriptor descriptor) { ArtifactDescriptor newDescriptor = new ArtifactDescriptor(descriptor); ProcessingStepDescriptor[] steps = new ProcessingStepDescriptor[] {new ProcessingStepDescriptor("org.eclipse.equinox.p2.processing.Pack200Unpacker", null, true)}; diff --git a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Pack200Step.java b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Pack200Step.java index 9800352bc..cf11900c1 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Pack200Step.java +++ b/bundles/org.eclipse.equinox.p2.artifact.optimizers/src/org/eclipse/equinox/internal/p2/artifact/optimizers/pack200/Pack200Step.java @@ -14,6 +14,7 @@ package org.eclipse.equinox.internal.p2.artifact.optimizers.pack200; import java.io.*; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.p2.artifact.optimizers.Activator; import org.eclipse.equinox.internal.p2.core.helpers.FileUtils; import org.eclipse.equinox.p2.artifact.repository.processing.ProcessingStep; import org.eclipse.equinox.p2.jarprocessor.JarProcessorExecutor; |