diff options
author | Thomas Watson | 2007-09-05 18:28:58 +0000 |
---|---|---|
committer | Thomas Watson | 2007-09-05 18:28:58 +0000 |
commit | dd53c9a33ca09f6e6383173891f190cfef2ed5f7 (patch) | |
tree | 4d2c131f2ea8ac4d587b2dd26867e2f9116e9796 /bundles/org.eclipse.osgi/resolver | |
parent | 01a1e8cdf381f2cb19e3d19100d5c5550d7d2ec9 (diff) | |
download | rt.equinox.framework-dd53c9a33ca09f6e6383173891f190cfef2ed5f7.tar.gz rt.equinox.framework-dd53c9a33ca09f6e6383173891f190cfef2ed5f7.tar.xz rt.equinox.framework-dd53c9a33ca09f6e6383173891f190cfef2ed5f7.zip |
Bug 165964 Process Bundle-NativeCode at resolve time
Diffstat (limited to 'bundles/org.eclipse.osgi/resolver')
13 files changed, 648 insertions, 16 deletions
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java index 5badacb6a..d84d1421e 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java @@ -265,6 +265,28 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver return false; } + // check the native code specification + NativeCodeSpecification nativeCode = bundle.getNativeCodeSpecification(); + if (nativeCode != null) { + NativeCodeDescription[] nativeCodeSuppliers = nativeCode.getPossibleSuppliers(); + NativeCodeDescription highestRanked = null; + for (int i = 0; i < nativeCodeSuppliers.length; i++) + if (nativeCode.isSatisfiedBy(nativeCodeSuppliers[i]) && (highestRanked == null || highestRanked.compareTo(nativeCodeSuppliers[i]) < 0)) + highestRanked = nativeCodeSuppliers[i]; + if (highestRanked == null) { + if (!nativeCode.isOptional()) { + state.addResolverError(bundle, ResolverError.NO_NATIVECODE_MATCH, nativeCode.toString(), nativeCode); + return false; + } + } else { + if (highestRanked.hasInvalidNativePaths()) { + state.addResolverError(bundle, ResolverError.INVALID_NATIVECODE_PATHS, highestRanked.toString(), nativeCode); + return false; + } + } + state.resolveConstraint(nativeCode, highestRanked); + } + // check the platform filter String platformFilter = bundle.getPlatformFilter(); if (platformFilter == null) diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java index 1ae157cbb..1f0987f5e 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2006 IBM Corporation and others. + * Copyright (c) 2003, 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 @@ -113,6 +113,11 @@ public class BundleDescriptionImpl extends BaseDescriptionImpl implements Bundle return lazyData.genericCapabilities; } + public NativeCodeSpecification getNativeCodeSpecification() { + fullyLoad(); + return lazyData.nativeCode; + } + public ExportPackageDescription[] getExportPackages() { fullyLoad(); return lazyData.exportPackages == null ? EMPTY_EXPORTS : lazyData.exportPackages; @@ -251,6 +256,19 @@ public class BundleDescriptionImpl extends BaseDescriptionImpl implements Bundle ((VersionConstraintImpl) genericRequires[i]).setBundle(this); } + protected void setNativeCodeSpecification(NativeCodeSpecification nativeCode) { + checkLazyData(); + lazyData.nativeCode = nativeCode; + if (nativeCode != null) { + ((NativeCodeSpecificationImpl) nativeCode).setBundle(this); + NativeCodeDescription[] suppliers = nativeCode.getPossibleSuppliers(); + if (suppliers != null) + for (int i = 0; i < suppliers.length; i++) + ((NativeCodeDescriptionImpl) suppliers[i]).setSupplier(this); + } + + } + protected int getStateBits() { return stateBits; } @@ -450,7 +468,7 @@ public class BundleDescriptionImpl extends BaseDescriptionImpl implements Bundle synchronized (reader) { if (isFullyLoaded()) { reader.setAccessedFlag(true); // set reader accessed flag - return; + return; } try { reader.fullyLoad(this); @@ -543,6 +561,7 @@ public class BundleDescriptionImpl extends BaseDescriptionImpl implements Bundle ImportPackageSpecification[] importPackages; GenericDescription[] genericCapabilities; GenericSpecification[] genericRequires; + NativeCodeSpecification nativeCode; ExportPackageDescription[] selectedExports; BundleDescription[] resolvedRequires; diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java new file mode 100644 index 000000000..75ae9cc8b --- /dev/null +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeDescriptionImpl.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * 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.osgi.internal.resolver; + +import java.util.Dictionary; +import org.eclipse.osgi.framework.internal.core.Constants; +import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.*; + +public class NativeCodeDescriptionImpl extends BaseDescriptionImpl implements NativeCodeDescription { + private static final VersionRange[] EMPTY_VERSIONRANGES = new VersionRange[0]; + + private Filter filter; + private String[] languages; + private String[] nativePaths; + private String[] osNames; + private VersionRange[] osVersions; + private String[] processors; + private BundleDescription supplier; + private boolean invalidNativePaths = false; + + public Filter getFilter() { + return filter; + } + + public String[] getLanguages() { + if (languages == null) + return BundleDescriptionImpl.EMPTY_STRING; + return languages; + } + + public String[] getNativePaths() { + if (nativePaths == null) + return BundleDescriptionImpl.EMPTY_STRING; + return nativePaths; + } + + public String[] getOSNames() { + if (osNames == null) + return BundleDescriptionImpl.EMPTY_STRING; + return osNames; + } + + public VersionRange[] getOSVersions() { + if (osVersions == null) + return EMPTY_VERSIONRANGES; + return osVersions; + } + + public String[] getProcessors() { + if (processors == null) + return BundleDescriptionImpl.EMPTY_STRING; + return processors; + } + + public BundleDescription getSupplier() { + return supplier; + } + + public int compareTo(Object other) { + if (!(other instanceof NativeCodeDescription)) + return 1; + State containingState = getSupplier().getContainingState(); + if (containingState == null) + return 0; + Dictionary[] platformProps = containingState.getPlatformProperties(); + Version osversion; + try { + osversion = Version.parseVersion((String) platformProps[0].get(Constants.FRAMEWORK_OS_VERSION)); + } catch (Exception e) { + osversion = Version.emptyVersion; + } + NativeCodeDescription otherDesc = (NativeCodeDescription) other; + VersionRange[] thisRanges = getOSVersions(); + VersionRange[] otherRanges = otherDesc.getOSVersions(); + Version thisHighest = getHighestVersionMatch(osversion, thisRanges); + Version otherHighest = getHighestVersionMatch(osversion, otherRanges); + if (thisHighest.compareTo(otherHighest) < 0) + return -1; + return (getLanguages().length == 0 ? 0 : 1) - (otherDesc.getLanguages().length == 0 ? 0 : 1); + } + + public boolean hasInvalidNativePaths() { + return invalidNativePaths; + } + + private Version getHighestVersionMatch(Version version, VersionRange[] ranges) { + Version highest = Version.emptyVersion; + for (int i = 0; i < ranges.length; i++) { + if (ranges[i].isIncluded(version) && highest.compareTo(ranges[i].getMinimum()) < 0) + highest = ranges[i].getMinimum(); + } + return highest; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + + String[] paths = getNativePaths(); + for (int i = 0; i < paths.length; i++) { + if (i > 0) { + sb.append("; "); //$NON-NLS-1$ + } + sb.append(paths[i]); + } + + String[] procs = getProcessors(); + for (int i = 0; i < procs.length; i++) { + sb.append("; "); //$NON-NLS-1$ + sb.append(Constants.BUNDLE_NATIVECODE_PROCESSOR); + sb.append('='); + sb.append(procs[i]); + } + + String[] oses = getOSNames(); + for (int i = 0; i < oses.length; i++) { + sb.append("; "); //$NON-NLS-1$ + sb.append(Constants.BUNDLE_NATIVECODE_OSNAME); + sb.append('='); + sb.append(oses[i]); + } + + VersionRange[] osRanges = getOSVersions(); + for (int i = 0; i < osRanges.length; i++) { + sb.append("; "); //$NON-NLS-1$ + sb.append(Constants.BUNDLE_NATIVECODE_OSVERSION); + sb.append("=\""); //$NON-NLS-1$ + sb.append(osRanges[i].toString()); + sb.append('"'); + } + + String[] langs = getLanguages(); + for (int i = 0; i < langs.length; i++) { + sb.append("; "); //$NON-NLS-1$ + sb.append(Constants.BUNDLE_NATIVECODE_LANGUAGE); + sb.append('='); + sb.append(langs[i]); + } + + Filter f = getFilter(); + if (f != null) { + sb.append("; "); //$NON-NLS-1$ + sb.append(Constants.SELECTION_FILTER_ATTRIBUTE); + sb.append("=\""); //$NON-NLS-1$ + sb.append(f.toString()); + sb.append('"'); + } + return (sb.toString()); + } + + void setInvalidNativePaths(boolean invalidNativePaths) { + this.invalidNativePaths = invalidNativePaths; + } + + void setOSNames(String[] osNames) { + this.osNames = osNames; + } + + void setOSVersions(VersionRange[] osVersions) { + this.osVersions = osVersions; + } + + void setFilter(String filter) throws InvalidSyntaxException { + this.filter = filter == null ? null : FrameworkUtil.createFilter(filter); + } + + void setLanguages(String[] languages) { + this.languages = languages; + } + + void setNativePaths(String[] nativePaths) { + this.nativePaths = nativePaths; + } + + void setProcessors(String[] processors) { + this.processors = processors; + } + + void setSupplier(BundleDescription supplier) { + this.supplier = supplier; + } +} diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java new file mode 100644 index 000000000..578b401e9 --- /dev/null +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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.osgi.internal.resolver; + +import java.util.Collection; +import java.util.Dictionary; +import org.eclipse.osgi.framework.internal.core.AliasMapper; +import org.eclipse.osgi.framework.internal.core.Constants; +import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.Filter; +import org.osgi.framework.Version; + +public class NativeCodeSpecificationImpl extends VersionConstraintImpl implements NativeCodeSpecification { + private static final NativeCodeDescription[] EMPTY_NATIVECODEDESCRIPTIONS = new NativeCodeDescription[0]; + private static AliasMapper aliasMapper = new AliasMapper(); + private NativeCodeDescription[] possibleSuppliers; + private boolean optional; + + public NativeCodeDescription[] getPossibleSuppliers() { + if (possibleSuppliers == null) + return EMPTY_NATIVECODEDESCRIPTIONS; + return possibleSuppliers; + } + + void setPossibleSuppliers(NativeCodeDescription[] possibleSuppliers) { + this.possibleSuppliers = possibleSuppliers; + } + + public boolean isOptional() { + return optional; + } + + void setOptional(boolean optional) { + this.optional = optional; + } + + public boolean isSatisfiedBy(BaseDescription supplier) { + if (!(supplier instanceof NativeCodeDescription)) + return false; + State containingState = getBundle().getContainingState(); + if (containingState == null) + return false; + Dictionary[] platformProps = containingState.getPlatformProperties(); + NativeCodeDescription nativeSupplier = (NativeCodeDescription) supplier; + Filter filter = nativeSupplier.getFilter(); + boolean match = false; + for (int i = 0; i < platformProps.length && !match; i++) { + if (filter != null && !filter.matchCase(platformProps[i])) + continue; + String[] osNames = nativeSupplier.getOSNames(); + if (osNames.length == 0) + match = true; + else { + String platformOS = (String) platformProps[i].get(Constants.FRAMEWORK_OS_NAME); + for (int j = 0; j < osNames.length && !match; j++) { + Object aliasedName = aliasMapper.aliasOSName(osNames[j]); + if (aliasedName instanceof String) { + if (aliasedName.equals(platformOS)) + match = true; + } else if (platformOS != null && ((Collection) aliasedName).contains(platformOS)) { + match = true; + } + } + } + if (!match) + continue; + match = false; + + String[] processors = nativeSupplier.getProcessors(); + if (processors.length == 0) + match = true; + else { + String platformProcessor = (String) platformProps[i].get(Constants.FRAMEWORK_PROCESSOR); + for (int j = 0; j < processors.length && !match; j++) { + String aliasedProcessor = aliasMapper.aliasProcessor(processors[j]); + if (aliasedProcessor.equals(platformProcessor)) + match = true; + } + } + if (!match) + return false; + match = false; + + String[] languages = nativeSupplier.getLanguages(); + if (languages.length == 0l) + match = true; + else { + String platformLanguage = (String) platformProps[i].get(Constants.FRAMEWORK_LANGUAGE); + for (int j = 0; j < languages.length && !match; j++) { + if (languages[j].equalsIgnoreCase(platformLanguage)) + match = true; + } + } + if (!match) + return false; + match = false; + + VersionRange[] osVersions = nativeSupplier.getOSVersions(); + if (osVersions.length == 0) + match = true; + else { + Version osversion; + try { + osversion = Version.parseVersion((String) platformProps[i].get(Constants.FRAMEWORK_OS_VERSION)); + } catch (Exception e) { + osversion = Version.emptyVersion; + } + for (int j = 0; j < osVersions.length && !match; j++) { + if (osVersions[j].isIncluded(osversion)) + match = true; + } + } + } + return match; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + NativeCodeDescription[] suppliers = getPossibleSuppliers(); + for (int i = 0; i < suppliers.length; i++) { + if (i > 0) + sb.append(", "); //$NON-NLS-1$ + sb.append(suppliers[i].toString()); + } + + return sb.toString(); + } +} diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java index 46dcd7950..c3988e1f3 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java @@ -170,4 +170,9 @@ public class ReadOnlyState implements State { public long getHighestBundleId() { return target.getHighestBundleId(); } + + public void setNativePathsInvalid(NativeCodeDescription nativeCodeDescription, boolean hasInvalidPaths) { + throw new UnsupportedOperationException(); + } + } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ResolverErrorImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ResolverErrorImpl.java index 69b6dadf2..95c04c138 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ResolverErrorImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ResolverErrorImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 IBM Corporation and others. + * Copyright (c) 2006, 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 @@ -18,6 +18,7 @@ public class ResolverErrorImpl implements ResolverError { private int type; private String data; private VersionConstraint unsatisfied; + public ResolverErrorImpl(BundleDescriptionImpl bundle, int type, String data, VersionConstraint unsatisfied) { this.bundle = bundle; this.data = data; @@ -65,6 +66,10 @@ public class ResolverErrorImpl implements ResolverError { return NLS.bind(StateMsg.RES_ERROR_SINGLETON_CONFLICT, getData()); case ResolverError.PLATFORM_FILTER : return NLS.bind(StateMsg.RES_ERROR_PLATFORM_FILTER, getData()); + case ResolverError.NO_NATIVECODE_MATCH : + return NLS.bind(StateMsg.RES_ERROR_NO_NATIVECODE_MATCH, getData()); + case ResolverError.INVALID_NATIVECODE_PATHS : + return NLS.bind(StateMsg.RES_ERROR_NATIVECODE_PATH_INVALID, getData()); default : return StateMsg.RES_ERROR_UNKNOWN; } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java index 25ddf3dfe..6ccaaaf91 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateBuilder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2006 IBM Corporation and others. + * Copyright (c) 2003, 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 @@ -101,6 +101,8 @@ class StateBuilder { result.setGenericRequires(createGenericRequires(genericRequires)); ManifestElement[] genericCapabilities = getGenericCapabilities(manifest, genericAliases); result.setGenericCapabilities(createGenericCapabilities(genericCapabilities)); + ManifestElement[] nativeCode = ManifestElement.parseHeader(Constants.BUNDLE_NATIVECODE, (String) manifest.get(Constants.BUNDLE_NATIVECODE)); + result.setNativeCodeSpecification(createNativeCode(nativeCode)); return result; } @@ -476,6 +478,50 @@ class StateBuilder { return (GenericDescription[]) results.toArray(new GenericDescription[results.size()]); } + private static NativeCodeSpecification createNativeCode(ManifestElement[] nativeCode) throws BundleException { + if (nativeCode == null) + return null; + NativeCodeSpecificationImpl result = new NativeCodeSpecificationImpl(); + result.setName(Constants.BUNDLE_NATIVECODE); + int length = nativeCode.length; + boolean optional = false; + if (length > 0 && nativeCode[length - 1].getValue().equals("*")) { //$NON-NLS-1$ + result.setOptional(true); + length--; + } + NativeCodeDescriptionImpl[] suppliers = new NativeCodeDescriptionImpl[length]; + for (int i = 0; i < length; i++) { + suppliers[i] = createNativeCodeDescription(nativeCode[i]); + } + result.setPossibleSuppliers(suppliers); + return result; + } + + private static NativeCodeDescriptionImpl createNativeCodeDescription(ManifestElement manifestElement) throws BundleException { + NativeCodeDescriptionImpl result = new NativeCodeDescriptionImpl(); + result.setName(Constants.BUNDLE_NATIVECODE); + result.setNativePaths(manifestElement.getValueComponents()); + result.setOSNames(manifestElement.getAttributes(Constants.BUNDLE_NATIVECODE_OSNAME)); + result.setProcessors(manifestElement.getAttributes(Constants.BUNDLE_NATIVECODE_PROCESSOR)); + result.setOSVersions(createVersionRanges(manifestElement.getAttributes(Constants.BUNDLE_NATIVECODE_OSVERSION))); + result.setLanguages(manifestElement.getAttributes(Constants.BUNDLE_NATIVECODE_LANGUAGE)); + try { + result.setFilter(manifestElement.getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE)); + } catch (InvalidSyntaxException e) { + throw new BundleException(Constants.SELECTION_FILTER_ATTRIBUTE, e); + } + return result; + } + + private static VersionRange[] createVersionRanges(String[] ranges) { + if (ranges == null) + return null; + VersionRange[] result = new VersionRange[ranges.length]; + for (int i = 0; i < result.length; i++) + result[i] = new VersionRange(ranges[i]); + return result; + } + private static VersionRange getVersionRange(String versionRange) { if (versionRange == null) return null; diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java index c5f7007cf..86e5743c1 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java @@ -23,7 +23,7 @@ import org.eclipse.osgi.util.ManifestElement; import org.osgi.framework.*; public abstract class StateImpl implements State { - public static final String[] PROPS = {"osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES, Constants.OSGI_RESOLVER_MODE, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, "osgi.resolveOptional", "osgi.genericAliases"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + public static final String[] PROPS = {"osgi.os", "osgi.ws", "osgi.nl", "osgi.arch", Constants.OSGI_FRAMEWORK_SYSTEM_PACKAGES, Constants.OSGI_RESOLVER_MODE, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, "osgi.resolveOptional", "osgi.genericAliases", Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION, Constants.FRAMEWORK_PROCESSOR, Constants.FRAMEWORK_LANGUAGE}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ transient private Resolver resolver; transient private StateDeltaImpl changes; transient private boolean resolving = false; @@ -63,6 +63,15 @@ public abstract class StateImpl implements State { // ignore this is handled in another place } } + NativeCodeSpecification nativeCode = description.getNativeCodeSpecification(); + if (nativeCode != null) { + NativeCodeDescription[] suppliers = nativeCode.getPossibleSuppliers(); + for (int i = 0; i < suppliers.length; i++) { + FilterImpl filter = (FilterImpl) suppliers[i].getFilter(); + if (filter != null) + addPlatformPropertyKeys(filter.getAttributes()); + } + } resolved = false; getDelta().recordBundleAdded((BundleDescriptionImpl) description); if (Constants.getInternalSymbolicName().equals(description.getSymbolicName())) @@ -548,29 +557,37 @@ public abstract class StateImpl implements State { synchronized boolean setPlatformProperties(Dictionary[] platformProperties, boolean resetSystemExports) { if (platformProperties.length == 0) throw new IllegalArgumentException(); - // copy the properties for our use internally + // copy the properties for our use internally; + // only copy String and String[] values Dictionary[] newPlatformProperties = new Dictionary[platformProperties.length]; for (int i = 0; i < platformProperties.length; i++) { newPlatformProperties[i] = new Hashtable(platformProperties[i].size()); synchronized (platformProperties[i]) { for (Enumeration keys = platformProperties[i].keys(); keys.hasMoreElements();) { Object key = keys.nextElement(); - newPlatformProperties[i].put(key, platformProperties[i].get(key)); + Object value = platformProperties[i].get(key); + if (value instanceof String || value instanceof String[]) + newPlatformProperties[i].put(key, value); } } } boolean result = false; + boolean performResetSystemExports = false; if (this.platformProperties.length != newPlatformProperties.length) { result = true; + performResetSystemExports = true; } else { // we need to see if any of the existing filter prop keys have changed String[] keys = getPlatformPropertyKeys(); - for (int i = 0; i < newPlatformProperties.length && !result; i++) + for (int i = 0; i < newPlatformProperties.length && !result; i++) { result |= changedProps(this.platformProperties[i], newPlatformProperties[i], keys); + if (resetSystemExports) + performResetSystemExports |= checkProp(this.platformProperties[i].get(Constants.FRAMEWORK_SYSTEMPACKAGES), newPlatformProperties[i].get(Constants.FRAMEWORK_SYSTEMPACKAGES)); + } } // always do a complete replacement of the properties in case new bundles are added that uses new filter props this.platformProperties = newPlatformProperties; - if (resetSystemExports && result) + if (performResetSystemExports) resetSystemExports(); return result; } @@ -775,4 +792,7 @@ public abstract class StateImpl implements State { return highestBundleId; } + public void setNativePathsInvalid(NativeCodeDescription nativeCodeDescription, boolean hasInvalidNativePaths) { + ((NativeCodeDescriptionImpl) nativeCodeDescription).setInvalidNativePaths(hasInvalidNativePaths); + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMessages.properties b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMessages.properties index 6a68499f6..b61289c04 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMessages.properties +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2004, 2005 IBM Corporation and others. +# Copyright (c) 2004, 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 @@ -27,4 +27,6 @@ RES_ERROR_FRAGMENT_CONFLICT=Constraints from the fragment conflict with the host RES_ERROR_USES_CONFLICT=Package uses conflict: {0} RES_ERROR_SINGLETON_CONFLICT=Another singleton version selected: {0} RES_ERROR_PLATFORM_FILTER=Platform filter did not match: {0} +RES_ERROR_NO_NATIVECODE_MATCH=No match found for native code: {0} +RES_ERROR_NATIVECODE_PATH_INVALID=The native code paths cannot be found: {0} RES_ERROR_UNKNOWN=Unknown resolution error diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMsg.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMsg.java index b67b81286..5223f5fc8 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMsg.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateMsg.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 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 @@ -31,6 +31,8 @@ public class StateMsg extends NLS { public static String RES_ERROR_USES_CONFLICT; public static String RES_ERROR_SINGLETON_CONFLICT; public static String RES_ERROR_PLATFORM_FILTER; + public static String RES_ERROR_NO_NATIVECODE_MATCH; + public static String RES_ERROR_NATIVECODE_PATH_INVALID; public static String RES_ERROR_UNKNOWN; static { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java index 0ccf63e6a..c15239491 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateObjectFactoryImpl.java @@ -21,6 +21,9 @@ import org.osgi.framework.*; public class StateObjectFactoryImpl implements StateObjectFactory { + /** + * @deprecated + */ public BundleDescription createBundleDescription(Dictionary manifest, String location, long id) throws BundleException { return createBundleDescription(null, manifest, location, id); } @@ -31,16 +34,26 @@ public class StateObjectFactoryImpl implements StateObjectFactory { return result; } + /** + * @deprecated + */ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, String[] providedPackages, boolean singleton) { return createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, providedPackages, singleton, true, true, null, null, null, null); } + /** + * @deprecated + */ public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, String[] providedPackages, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String executionEnvironment, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities) { // bug 154137 we need to parse the executionEnvironment param; no need to check for null, ManifestElement does that for us. return createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, singleton, attachFragments, dynamicFragments, platformFilter, ManifestElement.getArrayFromList(executionEnvironment), genericRequires, genericCapabilities); } public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String[] executionEnvironments, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities) { + return createBundleDescription(id, symbolicName, version, location, required, host, imports, exports, singleton, attachFragments, dynamicFragments, platformFilter, executionEnvironments, genericRequires, genericCapabilities, null); + } + + public BundleDescription createBundleDescription(long id, String symbolicName, Version version, String location, BundleSpecification[] required, HostSpecification host, ImportPackageSpecification[] imports, ExportPackageDescription[] exports, boolean singleton, boolean attachFragments, boolean dynamicFragments, String platformFilter, String[] executionEnvironments, GenericSpecification[] genericRequires, GenericDescription[] genericCapabilities, NativeCodeSpecification nativeCode) { BundleDescriptionImpl bundle = new BundleDescriptionImpl(); bundle.setBundleId(id); bundle.setSymbolicName(symbolicName); @@ -57,6 +70,7 @@ public class StateObjectFactoryImpl implements StateObjectFactory { bundle.setExecutionEnvironments(executionEnvironments); bundle.setGenericRequires(genericRequires); bundle.setGenericCapabilities(genericCapabilities); + bundle.setNativeCodeSpecification(nativeCode); return bundle; } @@ -91,9 +105,36 @@ public class StateObjectFactoryImpl implements StateObjectFactory { bundle.setExecutionEnvironments(original.getExecutionEnvironments()); bundle.setGenericCapabilities(createGenericCapabilities(original.getGenericCapabilities())); bundle.setGenericRequires(createGenericRequires(original.getGenericRequires())); + bundle.setNativeCodeSpecification(createNativeCodeSpecification(original.getNativeCodeSpecification())); return bundle; } + private NativeCodeSpecification createNativeCodeSpecification(NativeCodeSpecification original) { + if (original == null) + return null; + NativeCodeSpecificationImpl result = new NativeCodeSpecificationImpl(); + result.setName(original.getName()); + result.setOptional(original.isOptional()); + NativeCodeDescription[] originalDescriptions = original.getPossibleSuppliers(); + NativeCodeDescriptionImpl[] newDescriptions = new NativeCodeDescriptionImpl[originalDescriptions.length]; + for (int i = 0; i < originalDescriptions.length; i++) { + newDescriptions[i] = new NativeCodeDescriptionImpl(); + newDescriptions[i].setName(originalDescriptions[i].getName()); + newDescriptions[i].setNativePaths(originalDescriptions[i].getNativePaths()); + newDescriptions[i].setProcessors(originalDescriptions[i].getProcessors()); + newDescriptions[i].setOSNames(originalDescriptions[i].getOSNames()); + newDescriptions[i].setOSVersions(originalDescriptions[i].getOSVersions()); + newDescriptions[i].setLanguages(originalDescriptions[i].getLanguages()); + try { + newDescriptions[i].setFilter(originalDescriptions[i].getFilter().toString()); + } catch (InvalidSyntaxException e) { + // this is already tested from the orginal filter + } + } + result.setPossibleSuppliers(newDescriptions); + return result; + } + private GenericDescription[] createGenericCapabilities(GenericDescription[] genericCapabilities) { if (genericCapabilities == null || genericCapabilities.length == 0) return null; @@ -227,12 +268,35 @@ public class StateObjectFactoryImpl implements StateObjectFactory { return result; } + public NativeCodeDescription createNativeCodeDescription(String[] nativePaths, String[] processors, String[] osNames, VersionRange[] osVersions, String[] languages, String filter) throws InvalidSyntaxException { + NativeCodeDescriptionImpl result = new NativeCodeDescriptionImpl(); + result.setName(Constants.BUNDLE_NATIVECODE); + result.setNativePaths(nativePaths); + result.setProcessors(processors); + result.setOSNames(osNames); + result.setOSVersions(osVersions); + result.setLanguages(languages); + result.setFilter(filter); + return result; + } + + public NativeCodeSpecification createNativeCodeSpecification(NativeCodeDescription[] nativeCodeDescriptions, boolean optional) { + NativeCodeSpecificationImpl result = new NativeCodeSpecificationImpl(); + result.setName(Constants.BUNDLE_NATIVECODE); + result.setOptional(optional); + result.setPossibleSuppliers(nativeCodeDescriptions); + return result; + } + public SystemState createSystemState() { SystemState state = new SystemState(); state.setFactory(this); return state; } + /** + * @deprecated + */ public State createState() { return internalCreateState(); } @@ -271,10 +335,16 @@ public class StateObjectFactoryImpl implements StateObjectFactory { return restoredState; } + /** + * @deprecated + */ public State readState(InputStream stream) throws IOException { return internalReadStateDeprecated(internalCreateState(), new DataInputStream(stream), -1); } + /** + * @deprecated + */ public State readState(DataInputStream stream) throws IOException { return internalReadStateDeprecated(internalCreateState(), stream, -1); } @@ -315,6 +385,9 @@ public class StateObjectFactoryImpl implements StateObjectFactory { return toRestore; } + /** + * @deprecated + */ public void writeState(State state, DataOutputStream stream) throws IOException { internalWriteStateDeprecated(state, stream); } @@ -328,6 +401,9 @@ public class StateObjectFactoryImpl implements StateObjectFactory { writer.saveState((StateImpl) state, stateFile, lazyFile); } + /** + * @deprecated + */ public void writeState(State state, OutputStream stream) throws IOException { internalWriteStateDeprecated(state, new DataOutputStream(stream)); } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java index 089a84673..86a43a2b5 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2006 IBM Corporation and others. + * Copyright (c) 2003, 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 @@ -40,7 +40,7 @@ class StateReader { private int numBundles; private boolean accessedFlag = false; - public static final byte STATE_CACHE_VERSION = 26; + public static final byte STATE_CACHE_VERSION = 27; public static final byte NULL = 0; public static final byte OBJECT = 1; public static final byte INDEX = 2; @@ -330,6 +330,8 @@ class StateReader { result.setGenericRequires(reqs); } + result.setNativeCodeSpecification(readNativeCode(in)); + result.setFullyLoaded(true); // set fully loaded before setting the dependencies // No need to add bundle dependencies for hosts, imports or requires; // This is done by readBundleDescription @@ -356,6 +358,7 @@ class StateReader { addToObjectTable(exportPackageDesc, tableIndex); exportPackageDesc.setTableIndex(tableIndex); readBaseDescription(exportPackageDesc, in); + exportPackageDesc.setExporter(readBundleDescription(in)); exportPackageDesc.setRoot(in.readBoolean()); exportPackageDesc.setAttributes(readMap(in)); exportPackageDesc.setDirectives(readMap(in)); @@ -456,6 +459,7 @@ class StateReader { GenericDescriptionImpl result = new GenericDescriptionImpl(); addToObjectTable(result, tableIndex); readBaseDescription(result, in); + result.setSupplier(readBundleDescription(in)); result.setType(readString(in, false)); Map mapAttrs = readMap(in); Dictionary attrs = new Hashtable(); @@ -487,6 +491,60 @@ class StateReader { return result; } + private NativeCodeSpecification readNativeCode(DataInputStream in) throws IOException { + if (!in.readBoolean()) + return null; + NativeCodeSpecificationImpl result = new NativeCodeSpecificationImpl(); + result.setOptional(in.readBoolean()); + int numNativeDesc = in.readInt(); + NativeCodeDescriptionImpl[] nativeDescs = new NativeCodeDescriptionImpl[numNativeDesc]; + for (int i = 0; i < numNativeDesc; i++) + nativeDescs[i] = readNativeCodeDescription(in); + result.setPossibleSuppliers(nativeDescs); + int supplierIndex = in.readInt(); + if (supplierIndex >= 0) + result.setSupplier(nativeDescs[supplierIndex]); + return result; + } + + private NativeCodeDescriptionImpl readNativeCodeDescription(DataInputStream in) throws IOException { + NativeCodeDescriptionImpl result = new NativeCodeDescriptionImpl(); + readBaseDescription(result, in); + result.setSupplier(readBundleDescription(in)); + try { + result.setFilter(readString(in, false)); + } catch (InvalidSyntaxException e) { + // do nothing, this filter was tested before + } + result.setLanguages(readStringArray(in)); + result.setNativePaths(readStringArray(in)); + result.setOSNames(readStringArray(in)); + result.setOSVersions(readVersionRanges(in)); + result.setProcessors(readStringArray(in)); + result.setInvalidNativePaths(in.readBoolean()); + return result; + } + + private VersionRange[] readVersionRanges(DataInputStream in) throws IOException { + int num = in.readInt(); + if (num == 0) + return null; + VersionRange[] result = new VersionRange[num]; + for (int i = 0; i < num; i++) + result[i] = readVersionRange(in); + return result; + } + + private String[] readStringArray(DataInputStream in) throws IOException { + int num = in.readInt(); + if (num == 0) + return null; + String[] result = new String[num]; + for (int i = 0; i < num; i++) + result[i] = readString(in, false); + return result; + } + // called by readers for VersionConstraintImpl subclasses private void readVersionConstraint(VersionConstraintImpl version, DataInputStream in) throws IOException { version.setName(readString(in, false)); diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java index f5178d5ea..bc9273c5a 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2006 IBM Corporation and others. + * Copyright (c) 2003, 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 @@ -13,8 +13,7 @@ package org.eclipse.osgi.internal.resolver; import java.io.*; import java.util.*; import org.eclipse.osgi.service.resolver.*; -import org.osgi.framework.Constants; -import org.osgi.framework.Version; +import org.osgi.framework.*; class StateWriter { @@ -297,6 +296,8 @@ class StateWriter { writeGenericSpecification(genericRequires[i], out); } + writeNativeCode(bundle.getNativeCodeSpecification(), out); + // save the size of the lazy data ((BundleDescriptionImpl) bundle).setLazyDataSize(out.size() - dataStart); } @@ -312,6 +313,7 @@ class StateWriter { if (writePrefix(exportPackageDesc, out)) return; writeBaseDescription(exportPackageDesc, out); + writeBundleDescription(exportPackageDesc.getExporter(), out, false); out.writeBoolean(exportPackageDesc.isRoot()); writeMap(out, exportPackageDesc.getAttributes()); writeMap(out, exportPackageDesc.getDirectives()); @@ -321,6 +323,7 @@ class StateWriter { if (writePrefix(description, out)) return; writeBaseDescription(description, out); + writeBundleDescription(description.getSupplier(), out, false); writeStringOrNull(description.getType() == GenericDescription.DEFAULT_TYPE ? null : description.getType(), out); Dictionary attrs = description.getAttributes(); Map mapAttrs = new HashMap(attrs.size()); @@ -344,6 +347,54 @@ class StateWriter { writeStringOrNull(specification.getMatchingFilter(), out); } + private void writeNativeCode(NativeCodeSpecification nativeCodeSpecification, DataOutputStream out) throws IOException { + if (nativeCodeSpecification == null) { + out.writeBoolean(false); + return; + } + out.writeBoolean(true); + out.writeBoolean(nativeCodeSpecification.isOptional()); + NativeCodeDescription[] nativeDescs = nativeCodeSpecification.getPossibleSuppliers(); + int numDescs = nativeDescs == null ? 0 : nativeDescs.length; + out.writeInt(numDescs); + int supplierIndex = -1; + for (int i = 0; i < numDescs; i++) { + if (nativeDescs[i] == nativeCodeSpecification.getSupplier()) + supplierIndex = i; + writeNativeCodeDescription(nativeDescs[i], out); + } + out.writeInt(supplierIndex); + } + + private void writeNativeCodeDescription(NativeCodeDescription nativeCodeDescription, DataOutputStream out) throws IOException { + writeBaseDescription(nativeCodeDescription, out); + writeBundleDescription(nativeCodeDescription.getSupplier(), out, false); + Filter filter = nativeCodeDescription.getFilter(); + writeStringOrNull(filter == null ? null : filter.toString(), out); + writeStringArray(nativeCodeDescription.getLanguages(), out); + writeStringArray(nativeCodeDescription.getNativePaths(), out); + writeStringArray(nativeCodeDescription.getOSNames(), out); + writeVersionRanges(nativeCodeDescription.getOSVersions(), out); + writeStringArray(nativeCodeDescription.getProcessors(), out); + out.writeBoolean(nativeCodeDescription.hasInvalidNativePaths()); + } + + private void writeVersionRanges(VersionRange[] ranges, DataOutputStream out) throws IOException { + out.writeInt(ranges == null ? 0 : ranges.length); + if (ranges == null) + return; + for (int i = 0; i < ranges.length; i++) + writeVersionRange(ranges[i], out); + } + + private void writeStringArray(String[] strings, DataOutputStream out) throws IOException { + out.writeInt(strings == null ? 0 : strings.length); + if (strings == null) + return; + for (int i = 0; i < strings.length; i++) + writeStringOrNull(strings[i], out); + } + private void writeMap(DataOutputStream out, Map source) throws IOException { if (source == null) { out.writeInt(0); |