diff options
8 files changed, 496 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/.classpath b/bundles/org.eclipse.equinox.p2.tests.verifier/.classpath new file mode 100644 index 000000000..2fbb7a23e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/.project b/bundles/org.eclipse.equinox.p2.tests.verifier/.project new file mode 100644 index 000000000..26f02410c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.p2.tests.verifier</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.p2.tests.verifier/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..016a2a221 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,69 @@ +#Thu Sep 10 14:51:49 EDT 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.source=1.3 diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests.verifier/META-INF/MANIFEST.MF new file mode 100644 index 000000000..a7619a631 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Test Install Verifier +Bundle-SymbolicName: org.eclipse.equinox.p2.tests.verifier;singleton:=true +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.equinox.internal.p2.tests.verifier.Activator +Require-Bundle: org.eclipse.core.runtime +Bundle-ActivationPolicy: lazy +Import-Package: org.eclipse.equinox.internal.p2.core.helpers, + org.eclipse.equinox.internal.provisional.p2.engine, + org.eclipse.equinox.internal.provisional.p2.metadata.query, + org.eclipse.equinox.internal.provisional.p2.query +Bundle-RequiredExecutionEnvironment: J2SE-1.4 diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/build.properties b/bundles/org.eclipse.equinox.p2.tests.verifier/build.properties new file mode 100644 index 000000000..e9863e281 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/plugin.xml b/bundles/org.eclipse.equinox.p2.tests.verifier/plugin.xml new file mode 100644 index 000000000..27d6c0c8a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/plugin.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + <extension id="application" point="org.eclipse.core.runtime.applications"> + <application cardinality="singleton-global" thread="main" visible="true"> + <run class="org.eclipse.equinox.internal.p2.tests.verifier.VerifierApplication"/> + </application> + </extension> +</plugin> diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/Activator.java b/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/Activator.java new file mode 100644 index 000000000..d2a6fd2f6 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/Activator.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2009 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.tests.verifier; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator implements BundleActivator { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.equinox.p2.tests.verifier"; //$NON-NLS-1$ + private static BundleContext bundleContext; + + /** + * The constructor + */ + public Activator() { + // nothing interesting to do + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + bundleContext = context; + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + bundleContext = null; + } + + /* + * Return the bundle context or <code>null</code>. + */ + public static BundleContext getBundleContext() { + return bundleContext; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/VerifierApplication.java b/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/VerifierApplication.java new file mode 100644 index 000000000..8472d6e66 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests.verifier/src/org/eclipse/equinox/internal/p2/tests/verifier/VerifierApplication.java @@ -0,0 +1,310 @@ +/******************************************************************************* + * Copyright (c) 2009 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.tests.verifier; + +import java.io.*; +import java.util.*; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMsg; +import org.eclipse.core.runtime.internal.adaptor.MessageHelper; +import org.eclipse.equinox.app.IApplication; +import org.eclipse.equinox.app.IApplicationContext; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.provisional.p2.engine.IProfile; +import org.eclipse.equinox.internal.provisional.p2.engine.IProfileRegistry; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery; +import org.eclipse.equinox.internal.provisional.p2.query.Collector; +import org.eclipse.osgi.framework.internal.core.Constants; +import org.eclipse.osgi.service.resolver.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; +import org.osgi.service.packageadmin.PackageAdmin; + +/** + * Application which verifies an install. + * + * @since 1.0 + */ +public class VerifierApplication implements IApplication { + + private static final File DEFAULT_PROPERTIES_FILE = new File("verifier.properties"); //$NON-NLS-1$ + private static final String ARG_PROPERTIES = "-verifier.properties"; //$NON-NLS-1$ + private Properties properties = null; + private List ignoreResolved = null; + + /* + * Create and return an error status with the given message. + */ + private static IStatus createError(String message) { + return new Status(IStatus.ERROR, Activator.PLUGIN_ID, message); + } + + /* + * Return the bundle with the given symbolic name, or <code>null</code> if it does not exist. + */ + public static Bundle getBundle(String symbolicName) { + PackageAdmin packageAdmin = (PackageAdmin) ServiceHelper.getService(Activator.getBundleContext(), PackageAdmin.class.getName()); + if (packageAdmin == null) + return null; + Bundle[] bundles = packageAdmin.getBundles(symbolicName, null); + if (bundles == null) + return null; + // Return the first bundle that is not installed or uninstalled + for (int i = 0; i < bundles.length; i++) { + if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) { + return bundles[i]; + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext) + */ + public Object start(IApplicationContext context) throws Exception { + // start this bundle to registry a bunch of things we need + getBundle("org.eclipse.equinox.p2.exemplarysetup").start(Bundle.START_TRANSIENT); //$NON-NLS-1$ + String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS); + processArguments(args); + return verify(); + } + + /* + * Go through the command-line args and pull out interesting ones + * for later consumption. + */ + private void processArguments(String[] args) { + if (args == null) + return; + + for (int i = 1; i < args.length; i++) { + if (ARG_PROPERTIES.equals(args[i - 1])) { + String filename = args[i]; + if (filename.startsWith("-")) + continue; + try { + properties = readProperties(new File(filename)); + } catch (IOException e) { + // TODO + e.printStackTrace(); + // fall through to load default + } + continue; + } + } + + // problems loading properties file or none specified so look for a default + if (properties == null) { + try { + if (DEFAULT_PROPERTIES_FILE.exists()) + properties = readProperties(DEFAULT_PROPERTIES_FILE); + } catch (IOException e) { + // TODO + e.printStackTrace(); + } + } + if (properties == null) + properties = new Properties(); + } + + /* + * Read and return a properties file at the given location. + */ + private Properties readProperties(File file) throws IOException { + Properties result = new Properties(); + InputStream input = null; + try { + input = new BufferedInputStream(new FileInputStream(file)); + result.load(input); + return result; + } finally { + if (input != null) + try { + input.close(); + } catch (IOException e) { + // ignore + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.equinox.app.IApplication#stop() + */ + public void stop() { + // nothing to do + } + + /* + * Return a boolean value indicating whether or not the bundle with the given symbolic name + * should be considered when looking at bundles which are not resolved in the system. + */ + private boolean shouldCheckResolved(String bundle) { + if (ignoreResolved == null) { + ignoreResolved = new ArrayList(); + String list = properties.getProperty("ignore.unresolved"); + if (list == null) + return true; + for (StringTokenizer tokenizer = new StringTokenizer(list, ","); tokenizer.hasMoreTokens();) + ignoreResolved.add(tokenizer.nextToken().trim()); + } + for (Iterator iter = ignoreResolved.iterator(); iter.hasNext();) { + if (bundle.equals(iter.next())) + return false; + } + return true; + } + + private List getAllBundles() { + PlatformAdmin platformAdmin = (PlatformAdmin) ServiceHelper.getService(Activator.getBundleContext(), PlatformAdmin.class.getName()); + PackageAdmin packageAdmin = (PackageAdmin) ServiceHelper.getService(Activator.getBundleContext(), PackageAdmin.class.getName()); + State state = platformAdmin.getState(false); + List result = new ArrayList(); + + BundleDescription[] bundles = state.getBundles(); + for (int i = 0; i < bundles.length; i++) { + BundleDescription bundle = bundles[i]; + Bundle[] versions = packageAdmin.getBundles(bundle.getSymbolicName(), bundle.getVersion().toString()); + for (int j = 0; j < versions.length; j++) + result.add(versions[j]); + } + return result; + } + + /* + * Check to ensure all of the bundles in the system are resolved. + * + * Copied and modified from EclipseStarter#logUnresolvedBundles. + * This method prints out all the reasons while asking the resolver directly + * will only print out the first reason. + */ + private IStatus checkResolved() { + List allProblems = new ArrayList(); + PlatformAdmin platformAdmin = (PlatformAdmin) ServiceHelper.getService(Activator.getBundleContext(), PlatformAdmin.class.getName()); + State state = platformAdmin.getState(false); + StateHelper stateHelper = platformAdmin.getStateHelper(); + + // first lets look for missing leaf constraints (bug 114120) + VersionConstraint[] leafConstraints = stateHelper.getUnsatisfiedLeaves(state.getBundles()); + // hash the missing leaf constraints by the declaring bundles + Map missing = new HashMap(); + for (int i = 0; i < leafConstraints.length; i++) { + // only include non-optional and non-dynamic constraint leafs + if (leafConstraints[i] instanceof BundleSpecification && ((BundleSpecification) leafConstraints[i]).isOptional()) + continue; + if (leafConstraints[i] instanceof ImportPackageSpecification) { + if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE))) + continue; + if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE))) + continue; + } + BundleDescription bundleDesc = leafConstraints[i].getBundle(); + ArrayList constraints = (ArrayList) missing.get(bundleDesc); + if (constraints == null) { + constraints = new ArrayList(); + missing.put(bundleDesc, constraints); + } + constraints.add(leafConstraints[i]); + } + + // found some bundles with missing leaf constraints; log them first + if (missing.size() > 0) { + int rootIndex = 0; + for (Iterator iter = missing.keySet().iterator(); iter.hasNext(); rootIndex++) { + BundleDescription description = (BundleDescription) iter.next(); + String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, description.getLocation()); + ArrayList constraints = (ArrayList) missing.get(description); + for (Iterator inner = constraints.iterator(); inner.hasNext();) { + String message = generalMessage + " Reason: " + MessageHelper.getResolutionFailureMessage((VersionConstraint) inner.next()); + allProblems.add(createError(message)); + } + } + } + + // There may be some bundles unresolved for other reasons, causing the system to be unresolved + // log all unresolved constraints now + List allBundles = getAllBundles(); + for (Iterator i = allBundles.iterator(); i.hasNext();) { + Bundle bundle = (Bundle) i.next(); + if (bundle.getState() == Bundle.INSTALLED) { + String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundle); + BundleDescription description = state.getBundle(bundle.getBundleId()); + // for some reason, the state does not know about that bundle + if (description == null) + continue; + VersionConstraint[] unsatisfied = stateHelper.getUnsatisfiedConstraints(description); + if (unsatisfied.length > 0) { + // the bundle wasn't resolved due to some of its constraints were unsatisfiable + for (int j = 0; j < unsatisfied.length; j++) + allProblems.add(createError(generalMessage + " Reason: " + MessageHelper.getResolutionFailureMessage(unsatisfied[j]))); + } else { + ResolverError[] resolverErrors = state.getResolverErrors(description); + for (int j = 0; j < resolverErrors.length; j++) { + if (shouldAdd(resolverErrors[j])) { + allProblems.add(createError(generalMessage + " Reason: " + resolverErrors[j].toString())); + } + } + } + } + } + MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, "Problems checking resolved bundles.", null); + for (Iterator iter = allProblems.iterator(); iter.hasNext();) + result.add((IStatus) iter.next()); + return result; + } + + /* + * Return a boolean value indicating whether or not the given resolver error should be + * added to our results. + */ + private boolean shouldAdd(ResolverError error) { + // ignore EE problems? + if (ResolverError.MISSING_EXECUTION_ENVIRONMENT == error.getType() && Boolean.valueOf(properties.getProperty("ignore.ee")).booleanValue()) + return false; + return true; + } + + /* + * Ensure we have a profile registry and can access the SELF profile. + */ + private IStatus checkProfileRegistry() { + IProfileRegistry registry = (IProfileRegistry) ServiceHelper.getService(Activator.getBundleContext(), IProfileRegistry.class.getName()); + if (registry == null) + return createError("Profile registry service not available."); + IProfile profile = registry.getProfile(IProfileRegistry.SELF); + if (profile == null) + return createError("SELF profile not available in profile registry."); + Collector results = profile.query(new InstallableUnitQuery(Activator.PLUGIN_ID), new Collector(), null); + if (results.isEmpty()) + return createError(NLS.bind("IU for {0} not found in SELF profile.", Activator.PLUGIN_ID)); + return Status.OK_STATUS; + } + + /* + * Perform all of the verification checks. + */ + public IStatus verify() { + String message = "Problems occurred during verification."; + MultiStatus result = new MultiStatus(Activator.PLUGIN_ID, IStatus.OK, message, null); + + // ensure all the bundles are resolved + IStatus temp = checkResolved(); + if (!temp.isOK()) + result.merge(temp); + + // ensure we have a profile registry + temp = checkProfileRegistry(); + if (!temp.isOK()) + result.merge(temp); + + return result; + } + +} |