diff options
author | Thomas Watson | 2012-09-20 13:12:01 +0000 |
---|---|---|
committer | Thomas Watson | 2012-09-20 14:08:04 +0000 |
commit | 0a18aee6699903748b81fadeffc92b88aee0d444 (patch) | |
tree | 0108f925dfaa58876645d9778a0b83ba85d22f80 | |
parent | b5efc532bd6588376fd61371ab42e5ea44d7991c (diff) | |
download | rt.equinox.framework-0a18aee6699903748b81fadeffc92b88aee0d444.tar.gz rt.equinox.framework-0a18aee6699903748b81fadeffc92b88aee0d444.tar.xz rt.equinox.framework-0a18aee6699903748b81fadeffc92b88aee0d444.zip |
Use fuzzy compare ~= to match and do not lower case the attribute values for native code.
10 files changed, 315 insertions, 268 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java index d94b14f64..1d388021a 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleCapability.java @@ -10,7 +10,8 @@ *******************************************************************************/ package org.eclipse.osgi.container; -import java.util.Map; +import java.util.*; +import org.eclipse.osgi.container.namespaces.EquinoxNativeEnvironmentNamespace; import org.osgi.framework.wiring.BundleCapability; /** @@ -21,12 +22,14 @@ public final class ModuleCapability implements BundleCapability { private final String namespace; private final Map<String, String> directives; private final Map<String, Object> attributes; + private final Map<String, Object> transientAttrs; private final ModuleRevision revision; ModuleCapability(String namespace, Map<String, String> directives, Map<String, Object> attributes, ModuleRevision revision) { this.namespace = namespace; this.directives = directives; this.attributes = attributes; + this.transientAttrs = EquinoxNativeEnvironmentNamespace.NATIVE_ENVIRONMENT_NAMESPACE.equals(namespace) ? new HashMap<String, Object>(0) : null; this.revision = revision; } @@ -47,9 +50,25 @@ public final class ModuleCapability implements BundleCapability { @Override public Map<String, Object> getAttributes() { + if (transientAttrs == null) + return attributes; + Map<String, Object> result = new HashMap<String, Object>(transientAttrs); + result.putAll(attributes); + return Collections.unmodifiableMap(result); + } + + Map<String, Object> getPersistentAttributes() { return attributes; } + public void setTransientAttrs(Map<String, ?> transientAttrs) { + if (transientAttrs == null) { + throw new UnsupportedOperationException(namespace + ": namespace does not support transient attributes."); //$NON-NLS-1$ + } + this.transientAttrs.clear(); + this.transientAttrs.putAll(transientAttrs); + } + @Override public ModuleRevision getResource() { return revision; diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java index 570c9fd25..988b79a43 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java @@ -28,7 +28,8 @@ import org.eclipse.osgi.internal.container.ComputeNodeOrder; import org.osgi.framework.Constants; import org.osgi.framework.Version; import org.osgi.framework.wiring.BundleRevision; -import org.osgi.resource.*; +import org.osgi.resource.Requirement; +import org.osgi.resource.Wire; import org.osgi.service.resolver.Resolver; /** @@ -1092,11 +1093,11 @@ public class ModuleDatabase { writeVersion(current.getVersion(), out); out.writeInt(current.getTypes()); - List<Capability> capabilities = current.getCapabilities(null); + List<ModuleCapability> capabilities = current.getModuleCapabilities(null); out.writeInt(capabilities.size()); - for (Capability capability : capabilities) { + for (ModuleCapability capability : capabilities) { out.writeInt(addToWriteTable(capability, objectTable)); - writeGenericInfo(capability.getNamespace(), capability.getAttributes(), capability.getDirectives(), out); + writeGenericInfo(capability.getNamespace(), capability.getPersistentAttributes(), capability.getDirectives(), out); } List<Requirement> requirements = current.getRequirements(null); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java index 90b5fa7a5..9751f40b0 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java @@ -17,7 +17,9 @@ import org.eclipse.osgi.container.ModuleRevisionBuilder; import org.eclipse.osgi.container.namespaces.*; import org.eclipse.osgi.framework.internal.core.Msg; import org.eclipse.osgi.framework.internal.core.Tokenizer; -import org.eclipse.osgi.internal.framework.*; +import org.eclipse.osgi.internal.framework.EquinoxContainer; +import org.eclipse.osgi.internal.framework.FilterImpl; +import org.eclipse.osgi.storage.Storage; import org.eclipse.osgi.util.ManifestElement; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; @@ -732,35 +734,124 @@ public final class OSGiManifestBuilderFactory { return new String[] {eeName, v1}; } + static class NativeClause implements Comparable<NativeClause> { + private final int manifestIndex; + final List<String> nativePaths; + final String filter; + private final Version highestFloor; + private final boolean hasLanguage; + + NativeClause(int manifestIndex, ManifestElement clause) throws BundleException { + this.manifestIndex = manifestIndex; + this.nativePaths = new ArrayList<String>(Arrays.asList(clause.getValueComponents())); + StringBuilder sb = new StringBuilder(); + sb.append("(&"); //$NON-NLS-1$ + addToNativeCodeFilter(sb, clause, Constants.BUNDLE_NATIVECODE_OSNAME); + addToNativeCodeFilter(sb, clause, Constants.BUNDLE_NATIVECODE_PROCESSOR); + this.highestFloor = (Version) addToNativeCodeFilter(sb, clause, Constants.BUNDLE_NATIVECODE_OSVERSION); + this.hasLanguage = ((Boolean) addToNativeCodeFilter(sb, clause, Constants.BUNDLE_NATIVECODE_LANGUAGE)).booleanValue(); + String selectionFilter = clause.getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE); + if (selectionFilter != null) { + sb.append(selectionFilter); + } + sb.append(')'); + this.filter = sb.toString(); + } + + private static Object addToNativeCodeFilter(StringBuilder filter, ManifestElement nativeCode, String attribute) throws BundleException { + Boolean hasLanguage = Boolean.FALSE; + Version highestFloor = null; + String[] attrValues = nativeCode.getAttributes(attribute); + if (attrValues != null) { + + String filterAttribute = attribute; + if (Constants.BUNDLE_NATIVECODE_OSNAME.equals(attribute)) { + filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_NAME_ATTRIBUTE; + } else if (Constants.BUNDLE_NATIVECODE_PROCESSOR.equals(attribute)) { + filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE; + } else if (Constants.BUNDLE_NATIVECODE_LANGUAGE.equals(attribute)) { + filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE; + hasLanguage = attrValues.length > 0; + } else if (Constants.BUNDLE_NATIVECODE_OSVERSION.equals(attribute)) { + filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE; + } + + if (attrValues.length > 1) { + filter.append("(|"); //$NON-NLS-1$ + } + for (String attrAlias : attrValues) { + if (EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE.equals(filterAttribute)) { + VersionRange range = new VersionRange(attrAlias); + if (highestFloor == null || highestFloor.compareTo(range.getLeft()) < 0) { + highestFloor = range.getLeft(); + } + filter.append(range.toFilterString(filterAttribute)); + } else { + try { + filter.append('(').append(filterAttribute).append("~=").append(Storage.sanitizeFilterInput(attrAlias)).append(')'); //$NON-NLS-1$ + } catch (InvalidSyntaxException e) { + throw new BundleException("Bad native attribute: " + attrAlias, e); //$NON-NLS-1$ + } + } + } + if (attrValues.length > 1) { + filter.append(')'); + } + } + return Constants.BUNDLE_NATIVECODE_LANGUAGE.equals(attribute) ? hasLanguage : highestFloor; + } + + @Override + public int compareTo(NativeClause other) { + if (this.highestFloor != null) { + if (other == null) { + return -1; + } + int compareVersions = this.highestFloor.compareTo(other.highestFloor); + if (compareVersions != 0) { + return -(compareVersions); + } + } else if (other.highestFloor != null) { + return 1; + } + if (this.hasLanguage) { + return other.hasLanguage ? other.manifestIndex - this.manifestIndex : 1; + } + return other.hasLanguage ? -1 : other.manifestIndex - this.manifestIndex; + } + } + private static void getNativeCode(ModuleRevisionBuilder builder, Map<String, String> manifest) throws BundleException { ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_NATIVECODE, manifest.get(Constants.BUNDLE_NATIVECODE)); if (elements == null) { return; } - boolean optional = elements.length > 0 && elements[elements.length - 1].getValue().equals("*"); //$NON-NLS-1$ + boolean optional = false; + + List<NativeClause> nativeClauses = new ArrayList<NativeClause>(); + for (int i = 0; i < elements.length; i++) { + if (i == elements.length - 1) { + optional = elements[i].getValue().equals("*"); //$NON-NLS-1$ + } + if (!optional) { + nativeClauses.add(new NativeClause(i, elements[i])); + } + } + Collections.sort(nativeClauses); - AliasMapper aliasMapper = new AliasMapper(); - List<List<String>> allNativePaths = new ArrayList<List<String>>(); - List<String> allSelectionFilters = new ArrayList<String>(0); + Map<String, Object> attributes = new HashMap<String, Object>(2); + int numNativePaths = nativeClauses.size(); StringBuilder allNativeFilters = new StringBuilder(); allNativeFilters.append("(|"); //$NON-NLS-1$ - for (ManifestElement nativeCode : elements) { - allNativePaths.add(new ArrayList<String>(Arrays.asList(nativeCode.getValueComponents()))); - - StringBuilder filter = new StringBuilder(); - filter.append("(&"); //$NON-NLS-1$ - addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_OSNAME, aliasMapper); - addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_PROCESSOR, aliasMapper); - addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_OSVERSION, aliasMapper); - addToNativeCodeFilter(filter, nativeCode, Constants.BUNDLE_NATIVECODE_LANGUAGE, aliasMapper); - filter.append(')'); - - allNativeFilters.append(filter.toString()); - String selectionFilter = nativeCode.getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE); - if (selectionFilter != null) { - allSelectionFilters.add(selectionFilter); + for (int i = 0; i < numNativePaths; i++) { + NativeClause nativeClause = nativeClauses.get(i); + if (numNativePaths == 1) { + attributes.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE, nativeClause.nativePaths); + } else { + attributes.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE + '.' + i, nativeClause.nativePaths); } + allNativeFilters.append(nativeClauses.get(i).filter); } allNativeFilters.append(')'); @@ -770,63 +861,6 @@ public final class OSGiManifestBuilderFactory { directives.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, EquinoxNativeEnvironmentNamespace.RESOLUTION_OPTIONAL); } - Map<String, Object> attributes = new HashMap<String, Object>(0); - int i = 0; - int numNativePaths = allNativePaths.size(); - for (List<String> nativePaths : allNativePaths) { - if (numNativePaths == 0) { - attributes.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE, nativePaths); - } else { - attributes.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_NATIVE_PATHS_ATTRIBUTE + '.' + i, nativePaths); - } - i++; - } - - if (!allSelectionFilters.isEmpty()) { - StringBuilder selectionFilter = new StringBuilder(); - selectionFilter.append("(|"); //$NON-NLS-1$ - for (String filter : allSelectionFilters) { - selectionFilter.append(filter); - } - selectionFilter.append(")"); //$NON-NLS-1$ - directives.put(EquinoxNativeEnvironmentNamespace.REQUIREMENT_SELECTION_FILTER_DIRECTIVE, selectionFilter.toString()); - } builder.addRequirement(EquinoxNativeEnvironmentNamespace.NATIVE_ENVIRONMENT_NAMESPACE, directives, attributes); } - - private static void addToNativeCodeFilter(StringBuilder filter, ManifestElement nativeCode, String attribute, AliasMapper aliasMapper) { - String[] attrValues = nativeCode.getAttributes(attribute); - Collection<String> attrAliases = new HashSet<String>(1); - if (attrValues != null) { - for (String attrValue : attrValues) { - if (Constants.BUNDLE_NATIVECODE_OSNAME.equals(attribute) || Constants.BUNDLE_NATIVECODE_PROCESSOR.equals(attribute)) { - attrValue = attrValue.toLowerCase(); - } - attrAliases.add(attrValue); - } - } - String filterAttribute = attribute; - if (Constants.BUNDLE_NATIVECODE_OSNAME.equals(attribute)) { - filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_NAME_ATTRIBUTE; - } else if (Constants.BUNDLE_NATIVECODE_PROCESSOR.equals(attribute)) { - filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE; - } else if (Constants.BUNDLE_NATIVECODE_LANGUAGE.equals(attribute)) { - filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE; - } else if (Constants.BUNDLE_NATIVECODE_OSVERSION.equals(attribute)) { - filterAttribute = EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE; - } - if (attrAliases.size() > 1) { - filter.append("(|"); //$NON-NLS-1$ - } - for (String attrAlias : attrAliases) { - if (EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE.equals(filterAttribute)) { - filter.append(new VersionRange(attrAlias).toFilterString(filterAttribute)); - } else { - filter.append('(').append(filterAttribute).append('=').append(attrAlias).append(')'); - } - } - if (attrAliases.size() > 1) { - filter.append(')'); - } - } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeEnvironmentNamespace.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeEnvironmentNamespace.java index 3219b584b..25ff8c1cd 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeEnvironmentNamespace.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/namespaces/EquinoxNativeEnvironmentNamespace.java @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.osgi.container.namespaces; -import org.osgi.framework.Constants; import org.osgi.resource.Namespace; /** @@ -69,11 +68,4 @@ public class EquinoxNativeEnvironmentNamespace extends Namespace { * The value of this attribute must be of type {@code List<String>}. */ public static final String REQUIREMENT_NATIVE_PATHS_ATTRIBUTE = "native.paths"; //$NON-NLS-1$ - - /** - * Specifies the arbitrary selection filter for the native code requirement. This filter - * is matched against the system properties. - * @see Constants#SELECTION_FILTER_ATTRIBUTE - */ - public static final String REQUIREMENT_SELECTION_FILTER_DIRECTIVE = "selection.filter"; //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java index 1cf09526c..963793757 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/AliasMapper.java @@ -12,6 +12,7 @@ package org.eclipse.osgi.internal.framework; import java.io.*; import java.util.*; +import java.util.Map.Entry; import org.eclipse.osgi.framework.internal.core.Tokenizer; import org.eclipse.osgi.internal.debug.Debug; @@ -90,7 +91,7 @@ public class AliasMapper { * @param in InputStream from which to read alias data. * @return Map of aliases. */ - protected static Map<String, Collection<String>> initAliases(InputStream in, Map<String, Collection<String>> aliasTable, Map<String, String> canonicalTable) { + private static Map<String, Collection<String>> initAliases(InputStream in, Map<String, Collection<String>> aliasTable, Map<String, String> canonicalTable) { try { BufferedReader br; try { @@ -98,6 +99,7 @@ public class AliasMapper { } catch (UnsupportedEncodingException e) { br = new BufferedReader(new InputStreamReader(in)); } + Map<String, Set<String>> multiMaster = new HashMap<String, Set<String>>(); while (true) { String line = br.readLine(); if (line == null) /* EOF */{ @@ -109,36 +111,40 @@ public class AliasMapper { String masterLower = master.toLowerCase(); canonicalTable.put(masterLower, master); Collection<String> aliasLine = new ArrayList<String>(1); - aliasLine.add(masterLower); + aliasLine.add(master); parseloop: while (true) { String alias = tokenizer.getString("# \t"); //$NON-NLS-1$ if (alias == null) { break parseloop; } + aliasLine.add(alias); String aliasLower = alias.toLowerCase(); - aliasLine.add(aliasLower); if (!canonicalTable.containsKey(aliasLower)) { canonicalTable.put(aliasLower, master); } else { // the alias has multiple masters just make its canonical name be the alias - canonicalTable.put(aliasLower, alias); - } - } - for (String alias : aliasLine) { - Collection<String> aliases = aliasTable.get(alias); - if (aliases == null) { - aliases = new ArrayList<String>(aliasLine); - aliasTable.put(alias, aliases); - } else { - for (String aliasToAdd : aliasLine) { - if (!aliases.contains(aliasToAdd)) { - aliases.add(aliasToAdd); - } + String existingMaster = canonicalTable.put(aliasLower, alias); + Set<String> masters = multiMaster.get(aliasLower); + if (masters == null) { + masters = new HashSet<String>(); + multiMaster.put(aliasLower, masters); + masters.add(existingMaster.toLowerCase()); } + masters.add(masterLower); } } + aliasTable.put(masterLower, aliasLine); + } + } + Map<String, Set<String>> multiMasterAliases = new HashMap<String, Set<String>>(multiMaster.size()); + for (Entry<String, Set<String>> entry : multiMaster.entrySet()) { + Set<String> aliases = new HashSet<String>(); + for (String master : entry.getValue()) { + aliases.addAll(aliasTable.get(master)); } + multiMasterAliases.put(entry.getKey(), aliases); } + aliasTable.putAll(multiMasterAliases); } catch (IOException e) { Debug.printStackTrace(e); } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java index 97fcc1ead..aa5088474 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java @@ -10,6 +10,17 @@ *******************************************************************************/ package org.eclipse.osgi.internal.framework; +import static org.osgi.framework.Constants.FRAMEWORK_LANGUAGE; +import static org.osgi.framework.Constants.FRAMEWORK_OS_NAME; +import static org.osgi.framework.Constants.FRAMEWORK_OS_VERSION; +import static org.osgi.framework.Constants.FRAMEWORK_PROCESSOR; +import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN; +import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT; +import static org.osgi.framework.Constants.FRAMEWORK_VENDOR; +import static org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_EXTENSION; +import static org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_FRAGMENT; +import static org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE; + import java.io.*; import java.lang.reflect.Method; import java.net.*; @@ -52,11 +63,8 @@ public class EquinoxConfiguration implements EnvironmentInfo { public static final String VARIABLE_DELIM_STRING = "$"; //$NON-NLS-1$ public static final char VARIABLE_DELIM_CHAR = '$'; + private final Map<String, String> initialConfig; private final Properties configuration; - private final String nl; - private final String os; - private final String ws; - private final String arch; private final Debug debug; private final DebugOptions debugOptions; @@ -169,9 +177,12 @@ public class EquinoxConfiguration implements EnvironmentInfo { public static final String PROP_FORCED_RESTART = "osgi.forcedRestart"; //$NON-NLS-1$ - EquinoxConfiguration(Map<String, String> initialConfig, HookRegistry hookRegistry) { + private final static Collection<String> populateInitConfig = Arrays.asList(PROP_OSGI_ARCH, PROP_OSGI_OS, PROP_OSGI_WS, PROP_OSGI_NL, FRAMEWORK_OS_NAME, FRAMEWORK_OS_VERSION, FRAMEWORK_PROCESSOR, FRAMEWORK_LANGUAGE); + + EquinoxConfiguration(Map<String, String> initialConfiguration, HookRegistry hookRegistry) { + this.initialConfig = initialConfiguration == null ? new HashMap<String, String>(0) : new HashMap<String, String>(initialConfiguration); this.hookRegistry = hookRegistry; - String useSystemPropsValue = initialConfig == null ? null : initialConfig.get(PROP_USE_SYSTEM_PROPERTIES); + String useSystemPropsValue = initialConfig.get(PROP_USE_SYSTEM_PROPERTIES); boolean useSystemProps = useSystemPropsValue == null ? false : Boolean.parseBoolean(useSystemPropsValue); this.configuration = useSystemProps ? System.getProperties() : new Properties(); if (useSystemProps) { @@ -179,91 +190,25 @@ public class EquinoxConfiguration implements EnvironmentInfo { for (Map.Entry<String, String> configEntry : initialConfig.entrySet()) { if (!this.configuration.containsKey(configEntry.getKey())) { this.configuration.put(configEntry.getKey(), configEntry.getValue()); + } else { + // override the initial config value + Object systemValue = this.configuration.get(configEntry.getKey()); + if (systemValue instanceof String) { + configEntry.setValue((String) systemValue); + } } } } else { this.configuration.putAll(initialConfig); } - initializeProperties(this.configuration, aliasMapper); - /* - * Initializes the execution context for this run of the platform. The context - * includes information about the locale, operating system and window system. - * - * NOTE: The OS, WS, and ARCH values should never be null. The executable should - * be setting these values and therefore this code path is obsolete for Eclipse - * when run from the executable. - */ - // if the user didn't set the locale with a command line argument then use the default. - String nlValue = configuration.getProperty(PROP_OSGI_NL); - if (nlValue != null) { - StringTokenizer tokenizer = new StringTokenizer(nlValue, "_"); //$NON-NLS-1$ - int segments = tokenizer.countTokens(); - try { - Locale userLocale = null; - switch (segments) { - case 1 : - // use the 2 arg constructor to maintain compatibility with 1.3.1 - userLocale = new Locale(tokenizer.nextToken(), ""); //$NON-NLS-1$ - break; - case 2 : - userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken()); - break; - case 3 : - userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken(), tokenizer.nextToken()); - break; - default : - // if the user passed us in a bogus value then log a message and use the default - System.err.println(NLS.bind(EclipseAdaptorMsg.error_badNL, nlValue)); - userLocale = Locale.getDefault(); - break; - } - Locale.setDefault(userLocale); - // TODO what the heck is this for?? why not just use osgi.nl - configuration.put(PROP_OSGI_NL_USER, nlValue); - } catch (NoSuchElementException e) { - // fall through and use the default + initializeProperties(this.configuration, aliasMapper); + for (String initialKey : populateInitConfig) { + String value = this.configuration.getProperty(initialKey); + if (value != null) { + this.initialConfig.put(initialKey, value); } } - nlValue = Locale.getDefault().toString(); - configuration.put(PROP_OSGI_NL, nlValue); - - // if the user didn't set the operating system with a command line - // argument then use the default. - String osValue = configuration.getProperty(PROP_OSGI_OS); - if (osValue == null) { - osValue = guessOS(System.getProperty(PROP_JVM_OS_NAME)); - configuration.put(PROP_OSGI_OS, osValue); - } - - // if the user didn't set the window system with a command line - // argument then use the default. - String wsValue = configuration.getProperty(PROP_OSGI_WS); - if (wsValue == null) { - wsValue = guessWS(osValue); - configuration.put(PROP_OSGI_WS, wsValue); - } - - // if the user didn't set the system architecture with a command line - // argument then use the default. - String archValue = configuration.getProperty(PROP_OSGI_ARCH); - if (archValue == null) { - String name = System.getProperty(PROP_JVM_OS_ARCH); - // Map i386 architecture to x86 - if (name.equalsIgnoreCase(INTERNAL_ARCH_I386)) - archValue = Constants.ARCH_X86; - // Map amd64 architecture to x86_64 - else if (name.equalsIgnoreCase(INTERNAL_AMD64)) - archValue = Constants.ARCH_X86_64; - else - archValue = name; - configuration.put(PROP_OSGI_ARCH, archValue); - } - - nl = nlValue; - os = osValue; - ws = wsValue; - arch = archValue; this.debugOptions = new FrameworkDebugOptions(this); this.debug = new Debug(this.debugOptions); @@ -305,8 +250,8 @@ public class EquinoxConfiguration implements EnvironmentInfo { if (libExtensions[i].length() > 0 && libExtensions[i].charAt(0) != '.') libExtensions[i] = '.' + libExtensions[i]; LIB_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(libExtensions)); - ECLIPSE_LIB_VARIANTS = buildEclipseLibraryVariants(ws, os, arch, nl); - ECLIPSE_NL_JAR_VARIANTS = buildNLJarVariants(nl); + ECLIPSE_LIB_VARIANTS = buildEclipseLibraryVariants(getWS(), getOS(), getOSArch(), getNL()); + ECLIPSE_NL_JAR_VARIANTS = buildNLJarVariants(getNL()); DEFINE_PACKAGE_ATTRIBUTES = !"noattributes".equals(configuration.getProperty(PROP_DEFINE_PACKAGES)); //$NON-NLS-1$ String bsnVersion = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_BSNVERSION); @@ -326,19 +271,8 @@ public class EquinoxConfiguration implements EnvironmentInfo { PARALLEL_CAPABLE = CLASS_LOADER_TYPE_PARALLEL.equals(getConfiguration(PROP_CLASS_LOADER_TYPE)); } - public Map<String, String> asMap() { - Map<String, String> result = new HashMap<String, String>(); - synchronized (configuration) { - for (Object key : configuration.keySet()) { - if (key instanceof String) { - Object value = configuration.get(key); - if (value instanceof String) { - result.put((String) key, (String) value); - } - } - } - } - return result; + public Map<String, String> getInitialConfig() { + return Collections.unmodifiableMap(initialConfig); } private static List<String> buildEclipseLibraryVariants(String ws, String os, String arch, String nl) { @@ -397,19 +331,19 @@ public class EquinoxConfiguration implements EnvironmentInfo { } public String getOSArch() { - return arch; + return this.configuration.getProperty(PROP_OSGI_ARCH); } public String getNL() { - return nl; + return this.configuration.getProperty(PROP_OSGI_NL); } public String getOS() { - return os; + return this.configuration.getProperty(PROP_OSGI_OS); } public String getWS() { - return ws; + return this.configuration.getProperty(PROP_OSGI_WS); } public void setAllArgs(String[] allArgs) { @@ -607,6 +541,19 @@ public class EquinoxConfiguration implements EnvironmentInfo { } } + void mergeConfiguration(Properties source) { + for (Enumeration<?> e = source.keys(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + String value = source.getProperty(key); + if (getConfiguration(key) == null) { + setProperty(key, value); + initialConfig.put(key, value); + } else { + initialConfig.put(key, getConfiguration(key)); + } + } + } + private static void initializeProperties(Properties configuration, AliasMapper aliasMapper) { // initialize some framework properties that must always be set if (configuration.get(PROP_FRAMEWORK) == null || configuration.get(EquinoxLocations.PROP_INSTALL_AREA) == null) { @@ -626,24 +573,24 @@ public class EquinoxConfiguration implements EnvironmentInfo { configuration.put(PROP_FRAMEWORK, decode(configuration.getProperty(PROP_FRAMEWORK))); configuration.put(EquinoxLocations.PROP_INSTALL_AREA, decode(configuration.getProperty(EquinoxLocations.PROP_INSTALL_AREA))); - configuration.put(org.osgi.framework.Constants.FRAMEWORK_VENDOR, ECLIPSE_FRAMEWORK_VENDOR); - String value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_PROCESSOR); + configuration.put(FRAMEWORK_VENDOR, ECLIPSE_FRAMEWORK_VENDOR); + String value = configuration.getProperty(FRAMEWORK_PROCESSOR); if (value == null) { value = System.getProperty(PROP_JVM_OS_ARCH); if (value != null) { - configuration.put(org.osgi.framework.Constants.FRAMEWORK_PROCESSOR, aliasMapper.getCanonicalProcessor(value)); + configuration.put(FRAMEWORK_PROCESSOR, aliasMapper.getCanonicalProcessor(value)); } } - value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_OS_NAME); + value = configuration.getProperty(FRAMEWORK_OS_NAME); if (value == null) { value = System.getProperty(PROP_JVM_OS_NAME); if (value != null) { - configuration.put(org.osgi.framework.Constants.FRAMEWORK_OS_NAME, aliasMapper.getCanonicalOSName(value)); + configuration.put(FRAMEWORK_OS_NAME, aliasMapper.getCanonicalOSName(value)); } } - value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_OS_VERSION); + value = configuration.getProperty(FRAMEWORK_OS_VERSION); if (value == null) { value = System.getProperty(PROP_JVM_OS_VERSION); if (value != null) { @@ -682,20 +629,96 @@ public class EquinoxConfiguration implements EnvironmentInfo { // must be an invalid qualifier; just ignore it value = new Version(major, minor, micro).toString(); } - configuration.put(org.osgi.framework.Constants.FRAMEWORK_OS_VERSION, value); + configuration.put(FRAMEWORK_OS_VERSION, value); } } - value = configuration.getProperty(org.osgi.framework.Constants.FRAMEWORK_LANGUAGE); + value = configuration.getProperty(FRAMEWORK_LANGUAGE); if (value == null) // set the value of the framework language property - configuration.put(org.osgi.framework.Constants.FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage()); + configuration.put(FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage()); // set the support properties for fragments and require-bundle (bug 173090) - configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$ - configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$ - configuration.put(org.osgi.framework.Constants.SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$ - if (org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(configuration.get(org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN))) { + configuration.put(SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$ + configuration.put(SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$ + configuration.put(SUPPORTS_FRAMEWORK_EXTENSION, "true"); //$NON-NLS-1$ + if (FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT.equals(configuration.get(FRAMEWORK_STORAGE_CLEAN))) { configuration.put(PROP_CLEAN, "true"); //$NON-NLS-1$ } + + /* + * Initializes the execution context for this run of the platform. The context + * includes information about the locale, operating system and window system. + * + * NOTE: The OS, WS, and ARCH values should never be null. The executable should + * be setting these values and therefore this code path is obsolete for Eclipse + * when run from the executable. + */ + + // if the user didn't set the locale with a command line argument then use the default. + String nlValue = configuration.getProperty(PROP_OSGI_NL); + if (nlValue != null) { + StringTokenizer tokenizer = new StringTokenizer(nlValue, "_"); //$NON-NLS-1$ + int segments = tokenizer.countTokens(); + try { + Locale userLocale = null; + switch (segments) { + case 1 : + // use the 2 arg constructor to maintain compatibility with 1.3.1 + userLocale = new Locale(tokenizer.nextToken(), ""); //$NON-NLS-1$ + break; + case 2 : + userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken()); + break; + case 3 : + userLocale = new Locale(tokenizer.nextToken(), tokenizer.nextToken(), tokenizer.nextToken()); + break; + default : + // if the user passed us in a bogus value then log a message and use the default + System.err.println(NLS.bind(EclipseAdaptorMsg.error_badNL, nlValue)); + userLocale = Locale.getDefault(); + break; + } + Locale.setDefault(userLocale); + // TODO what the heck is this for?? why not just use osgi.nl + configuration.put(PROP_OSGI_NL_USER, nlValue); + } catch (NoSuchElementException e) { + // fall through and use the default + } + } + nlValue = Locale.getDefault().toString(); + configuration.put(PROP_OSGI_NL, nlValue); + + // if the user didn't set the operating system with a command line + // argument then use the default. + String osValue = configuration.getProperty(PROP_OSGI_OS); + if (osValue == null) { + osValue = guessOS(System.getProperty(PROP_JVM_OS_NAME)); + configuration.put(PROP_OSGI_OS, osValue); + } + + // if the user didn't set the window system with a command line + // argument then use the default. + String wsValue = configuration.getProperty(PROP_OSGI_WS); + if (wsValue == null) { + wsValue = guessWS(osValue); + configuration.put(PROP_OSGI_WS, wsValue); + } + + // if the user didn't set the system architecture with a command line + // argument then use the default. + String archValue = configuration.getProperty(PROP_OSGI_ARCH); + if (archValue == null) { + String name = System.getProperty(PROP_JVM_OS_ARCH); + // Map i386 architecture to x86 + if (name.equalsIgnoreCase(INTERNAL_ARCH_I386)) + archValue = Constants.ARCH_X86; + // Map amd64 architecture to x86_64 + else if (name.equalsIgnoreCase(INTERNAL_AMD64)) + archValue = Constants.ARCH_X86_64; + else + archValue = name; + configuration.put(PROP_OSGI_ARCH, archValue); + } + } private static int parseVersionInt(String value) { diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java index 5db495da0..dfb97e596 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainer.java @@ -116,16 +116,7 @@ public class EquinoxContainer { } catch (MalformedURLException e) { // its ok. This should never happen } - mergeProperties(equinoxConfig, loadProperties(location, equinoxConfig)); - } - - private static void mergeProperties(EquinoxConfiguration equinoxConfig, Properties source) { - for (Enumeration<?> e = source.keys(); e.hasMoreElements();) { - String key = (String) e.nextElement(); - String value = source.getProperty(key); - if (equinoxConfig.getConfiguration(key) == null) - equinoxConfig.setProperty(key, value); - } + equinoxConfig.mergeConfiguration(loadProperties(location, equinoxConfig)); } private static Properties loadProperties(URL location, EquinoxConfiguration equinoxConfig) { diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java index 7c49560da..61020d4bc 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/OSGiFrameworkHooks.java @@ -15,7 +15,6 @@ import java.security.PrivilegedAction; import java.util.*; import org.eclipse.osgi.container.Module; import org.eclipse.osgi.container.ModuleCollisionHook; -import org.eclipse.osgi.container.namespaces.EquinoxNativeEnvironmentNamespace; import org.eclipse.osgi.framework.internal.core.Msg; import org.eclipse.osgi.internal.baseadaptor.ArrayMap; import org.eclipse.osgi.internal.debug.Debug; @@ -263,10 +262,6 @@ class OSGiFrameworkHooks { if (debug.DEBUG_HOOKS) { Debug.println("ResolverHook.filterMatches(" + requirement + ", " + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } - - // always filter the native code namespace - filterNativeSelectionFilter(requirement, candidates); - if (hooks.isEmpty()) return; candidates = new ShrinkableCollection<BundleCapability>(candidates); @@ -284,22 +279,6 @@ class OSGiFrameworkHooks { } } - private void filterNativeSelectionFilter(BundleRequirement requirement, Collection<BundleCapability> candidates) { - if (EquinoxNativeEnvironmentNamespace.NATIVE_ENVIRONMENT_NAMESPACE.equals(requirement.getNamespace())) { - String filterSpec = requirement.getDirectives().get(EquinoxNativeEnvironmentNamespace.REQUIREMENT_SELECTION_FILTER_DIRECTIVE); - if (filterSpec != null) { - try { - Filter f = FilterImpl.newInstance(filterSpec); - if (!f.matches(container.getConfiguration().asMap())) { - candidates.clear(); - } - } catch (InvalidSyntaxException e) { - candidates.clear(); - } - } - } - } - public void end() { if (debug.DEBUG_HOOKS) { Debug.println("ResolverHook.end"); //$NON-NLS-1$ diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java index 03ace286f..75851b874 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java @@ -209,6 +209,12 @@ public class Storage { throw new IllegalStateException("Could not create a builder for the system bundle.", e); //$NON-NLS-1$ } } + ModuleRevision currentRevision = systemModule.getCurrentRevision(); + List<ModuleCapability> nativeEnvironments = currentRevision.getModuleCapabilities(EquinoxNativeEnvironmentNamespace.NATIVE_ENVIRONMENT_NAMESPACE); + Map<String, String> configMap = equinoxContainer.getConfiguration().getInitialConfig(); + for (ModuleCapability nativeEnvironment : nativeEnvironments) { + nativeEnvironment.setTransientAttrs(configMap); + } } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; @@ -512,16 +518,14 @@ public class Storage { result.append(EquinoxNativeEnvironmentNamespace.NATIVE_ENVIRONMENT_NAMESPACE).append("; "); //$NON-NLS-1$ if (osName != null) { osName = getAliasList(equinoxConfig.getAliasMapper().getOSNameAliases(osName)); - result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_NAME_ATTRIBUTE).append(":List<String>=").append(osName).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_NAME_ATTRIBUTE).append(":List<String>=").append(osName).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ } if (processor != null) { processor = getAliasList(equinoxConfig.getAliasMapper().getProcessorAliases(processor)); result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE).append(":List<String>=").append(processor).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ } - result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE).append(":Version").append("=").append(osVersion).append("; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE).append("=").append(language); //$NON-NLS-1$ - // TODO need a way to configure in arbitrary native code matching attributes - + result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_OS_VERSION_ATTRIBUTE).append(":Version").append("=\"").append(osVersion).append("\"; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + result.append(EquinoxNativeEnvironmentNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE).append("=\"").append(language).append('\"'); //$NON-NLS-1$ return result.toString(); } @@ -1418,7 +1422,7 @@ public class Storage { return pathList; } - private static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException { + public static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException { StringBuffer buffer = null; boolean foundEscape = false; for (int i = 0; i < filePattern.length(); i++) { diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Tokenizer.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Tokenizer.java index 2cbf602d9..33310209a 100644 --- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Tokenizer.java +++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/framework/internal/core/Tokenizer.java @@ -110,7 +110,6 @@ public class Tokenizer { StringBuffer sb = new StringBuffer(); cur++; /* skip quote */ char c = '\0'; - int begin = cur; for (; cur < max; cur++) { c = val[cur]; // this is an escaped char @@ -126,19 +125,18 @@ public class Tokenizer { } sb.append(c); } - int count = cur - begin; + if (c == '\"') { cur++; - } + } // TODO else error; no closing quote? + cursor = cur; - if (count > 0) { - skipWhiteSpace(); - return sb.toString(); - } - } else /* not a quoted string; same as token */ - { - return getToken(terminals); + skipWhiteSpace(); + return sb.toString(); + } + /* not a quoted string; same as token */ + return getToken(terminals); } return (null); } |