KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > internal > resolver > StateBuilder


1 /*******************************************************************************
2  * Copyright (c) 2003, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.osgi.internal.resolver;
12
13 import java.lang.reflect.Constructor JavaDoc;
14 import java.util.*;
15 import org.eclipse.osgi.framework.internal.core.Constants;
16 import org.eclipse.osgi.service.resolver.*;
17 import org.eclipse.osgi.util.ManifestElement;
18 import org.eclipse.osgi.util.NLS;
19 import org.osgi.framework.*;
20
21 /**
22  * This class builds bundle description objects from manifests
23  */

24 class StateBuilder {
25     static final String JavaDoc[] DEFINED_MATCHING_ATTRS = {Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.PACKAGE_SPECIFICATION_VERSION, Constants.VERSION_ATTRIBUTE};
26     static final String JavaDoc[] DEFINED_OSGI_VALIDATE_HEADERS = {Constants.IMPORT_PACKAGE, Constants.DYNAMICIMPORT_PACKAGE, Constants.EXPORT_PACKAGE, Constants.FRAGMENT_HOST, Constants.BUNDLE_SYMBOLICNAME, Constants.REEXPORT_PACKAGE, Constants.REQUIRE_BUNDLE};
27     static final String JavaDoc GENERIC_REQUIRE = "Eclipse-GenericRequire"; //$NON-NLS-1$
28
static final String JavaDoc GENERIC_CAPABILITY = "Eclipse-GenericCapability"; //$NON-NLS-1$
29

30     private static final String JavaDoc ATTR_TYPE_STRING = "string"; //$NON-NLS-1$
31
private static final String JavaDoc ATTR_TYPE_VERSION = "version"; //$NON-NLS-1$
32
private static final String JavaDoc ATTR_TYPE_URI = "uri"; //$NON-NLS-1$
33
private static final String JavaDoc ATTR_TYPE_LONG = "long"; //$NON-NLS-1$
34
private static final String JavaDoc ATTR_TYPE_DOUBLE = "double"; //$NON-NLS-1$
35
private static final String JavaDoc ATTR_TYPE_SET = "set"; //$NON-NLS-1$
36
private static final String JavaDoc OPTIONAL_ATTR = "optional"; //$NON-NLS-1$
37
private static final String JavaDoc MULTIPLE_ATTR = "multiple"; //$NON-NLS-1$
38
private static final String JavaDoc TRUE = "true"; //$NON-NLS-1$
39

40     static BundleDescription createBundleDescription(StateImpl state, Dictionary manifest, String JavaDoc location) throws BundleException {
41         BundleDescriptionImpl result = new BundleDescriptionImpl();
42         String JavaDoc manifestVersionHeader = (String JavaDoc) manifest.get(Constants.BUNDLE_MANIFESTVERSION);
43         boolean jreBundle = "true".equals(manifest.get(Constants.Eclipse_JREBUNDLE)); //$NON-NLS-1$
44
int manifestVersion = 1;
45         if (manifestVersionHeader != null)
46             manifestVersion = Integer.parseInt(manifestVersionHeader);
47         if (manifestVersion >= 2)
48             validateHeaders(manifest, jreBundle);
49
50         // retrieve the symbolic-name and the singleton status
51
String JavaDoc symbolicNameHeader = (String JavaDoc) manifest.get(Constants.BUNDLE_SYMBOLICNAME);
52         if (symbolicNameHeader != null) {
53             ManifestElement[] symbolicNameElements = ManifestElement.parseHeader(Constants.BUNDLE_SYMBOLICNAME, symbolicNameHeader);
54             if (symbolicNameElements.length > 0) {
55                 result.setSymbolicName(symbolicNameElements[0].getValue());
56                 String JavaDoc singleton = symbolicNameElements[0].getDirective(Constants.SINGLETON_DIRECTIVE);
57                 if (singleton == null) // TODO this is for backward compatibility; need to check manifest version < 2 to allow this after everyone has converted to new syntax
58
singleton = symbolicNameElements[0].getAttribute(Constants.SINGLETON_DIRECTIVE);
59                 result.setStateBit(BundleDescriptionImpl.SINGLETON, "true".equals(singleton)); //$NON-NLS-1$
60
String JavaDoc fragmentAttachment = symbolicNameElements[0].getDirective(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
61                 if (fragmentAttachment != null) {
62                     if (fragmentAttachment.equals(Constants.FRAGMENT_ATTACHMENT_RESOLVETIME)) {
63                         result.setStateBit(BundleDescriptionImpl.ATTACH_FRAGMENTS, true);
64                         result.setStateBit(BundleDescriptionImpl.DYNAMIC_FRAGMENTS, false);
65                     } else if (fragmentAttachment.equals(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
66                         result.setStateBit(BundleDescriptionImpl.ATTACH_FRAGMENTS, false);
67                         result.setStateBit(BundleDescriptionImpl.DYNAMIC_FRAGMENTS, false);
68                     }
69                 }
70             }
71         }
72         // retrieve other headers
73
String JavaDoc version = (String JavaDoc) manifest.get(Constants.BUNDLE_VERSION);
74         try {
75             result.setVersion((version != null) ? Version.parseVersion(version) : Version.emptyVersion);
76         } catch (IllegalArgumentException JavaDoc ex) {
77             if (manifestVersion >= 2)
78                 throw new BundleException(ex.getMessage());
79             // prior to R4 the Bundle-Version header was not interpreted by the Framework;
80
// must not fail for old R3 style bundles
81
}
82         result.setLocation(location);
83         result.setPlatformFilter((String JavaDoc) manifest.get(Constants.ECLIPSE_PLATFORMFILTER));
84         result.setExecutionEnvironments(ManifestElement.getArrayFromList((String JavaDoc) manifest.get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT)));
85         ManifestElement[] host = ManifestElement.parseHeader(Constants.FRAGMENT_HOST, (String JavaDoc) manifest.get(Constants.FRAGMENT_HOST));
86         if (host != null)
87             result.setHost(createHostSpecification(host[0]));
88         ManifestElement[] exports = ManifestElement.parseHeader(Constants.EXPORT_PACKAGE, (String JavaDoc) manifest.get(Constants.EXPORT_PACKAGE));
89         ManifestElement[] reexports = ManifestElement.parseHeader(Constants.REEXPORT_PACKAGE, (String JavaDoc) manifest.get(Constants.REEXPORT_PACKAGE));
90         ManifestElement[] provides = ManifestElement.parseHeader(Constants.PROVIDE_PACKAGE, (String JavaDoc) manifest.get(Constants.PROVIDE_PACKAGE)); // TODO this is null for now until the framwork is updated to handle the new re-export semantics
91
boolean strict = state != null && state.inStrictMode();
92         ArrayList providedExports = new ArrayList(provides == null ? 0 : provides.length);
93         result.setExportPackages(createExportPackages(exports, reexports, provides, providedExports, manifestVersion, strict));
94         ManifestElement[] imports = ManifestElement.parseHeader(Constants.IMPORT_PACKAGE, (String JavaDoc) manifest.get(Constants.IMPORT_PACKAGE));
95         ManifestElement[] dynamicImports = ManifestElement.parseHeader(Constants.DYNAMICIMPORT_PACKAGE, (String JavaDoc) manifest.get(Constants.DYNAMICIMPORT_PACKAGE));
96         result.setImportPackages(createImportPackages(result.getExportPackages(), providedExports, imports, dynamicImports, manifestVersion));
97         ManifestElement[] requires = ManifestElement.parseHeader(Constants.REQUIRE_BUNDLE, (String JavaDoc) manifest.get(Constants.REQUIRE_BUNDLE));
98         result.setRequiredBundles(createRequiredBundles(requires));
99         String JavaDoc[][] genericAliases = getGenericAliases(state);
100         ManifestElement[] genericRequires = getGenericRequires(manifest, genericAliases);
101         result.setGenericRequires(createGenericRequires(genericRequires));
102         ManifestElement[] genericCapabilities = getGenericCapabilities(manifest, genericAliases);
103         result.setGenericCapabilities(createGenericCapabilities(genericCapabilities));
104         return result;
105     }
106
107     private static ManifestElement[] getGenericRequires(Dictionary manifest, String JavaDoc[][] genericAliases) throws BundleException {
108         ManifestElement[] genericRequires = ManifestElement.parseHeader(GENERIC_REQUIRE, (String JavaDoc) manifest.get(GENERIC_REQUIRE));
109         ArrayList aliasList = null;
110         if (genericAliases.length > 0) {
111             aliasList = new ArrayList(genericRequires == null ? 0 : genericRequires.length);
112             for (int i = 0; i < genericAliases.length; i++) {
113                 ManifestElement[] aliasReqs = ManifestElement.parseHeader(genericAliases[i][1], (String JavaDoc) manifest.get(genericAliases[i][1]));
114                 if (aliasReqs == null)
115                     continue;
116                 for (int j = 0; j < aliasReqs.length; j++) {
117                     StringBuffer JavaDoc strBuf = new StringBuffer JavaDoc();
118                     strBuf.append(aliasReqs[j].getValue()).append(':').append(genericAliases[i][2]);
119                     String JavaDoc filter = aliasReqs[j].getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE);
120                     if (filter != null)
121                         strBuf.append("; ").append(Constants.SELECTION_FILTER_ATTRIBUTE).append(filter).append("=\"").append(filter).append("\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
122
ManifestElement[] withType = ManifestElement.parseHeader(genericAliases[i][1], strBuf.toString());
123                     aliasList.add(withType[0]);
124                 }
125             }
126         }
127         if (aliasList == null || aliasList.size() == 0)
128             return genericRequires;
129         if (genericRequires != null)
130             for (int i = 0; i < genericRequires.length; i++)
131                 aliasList.add(genericRequires[i]);
132         return (ManifestElement[]) aliasList.toArray(new ManifestElement[aliasList.size()]);
133     }
134
135     private static ManifestElement[] getGenericCapabilities(Dictionary manifest, String JavaDoc[][] genericAliases) throws BundleException {
136         ManifestElement[] genericCapabilities = ManifestElement.parseHeader(GENERIC_CAPABILITY, (String JavaDoc) manifest.get(GENERIC_CAPABILITY));
137         ArrayList aliasList = null;
138         if (genericAliases.length > 0) {
139             aliasList = new ArrayList(genericCapabilities == null ? 0 : genericCapabilities.length);
140             for (int i = 0; i < genericAliases.length; i++) {
141                 ManifestElement[] aliasCapabilities = ManifestElement.parseHeader(genericAliases[i][0], (String JavaDoc) manifest.get(genericAliases[i][0]));
142                 if (aliasCapabilities == null)
143                     continue;
144                 for (int j = 0; j < aliasCapabilities.length; j++) {
145                     StringBuffer JavaDoc strBuf = new StringBuffer JavaDoc();
146                     strBuf.append(aliasCapabilities[j].getValue()).append(':').append(genericAliases[i][2]);
147                     for (Enumeration keys = aliasCapabilities[j].getKeys(); keys != null && keys.hasMoreElements();) {
148                         String JavaDoc key = (String JavaDoc) keys.nextElement();
149                         strBuf.append("; ").append(key).append("=\"").append(aliasCapabilities[j].getAttribute(key)).append("\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
150
}
151                     ManifestElement[] withTypes = ManifestElement.parseHeader(genericAliases[i][0], strBuf.toString());
152                     aliasList.add(withTypes[0]);
153                 }
154             }
155         }
156         if (aliasList == null || aliasList.size() == 0)
157             return genericCapabilities;
158         if (genericCapabilities != null)
159             for (int i = 0; i < genericCapabilities.length; i++)
160                 aliasList.add(genericCapabilities[i]);
161         return (ManifestElement[]) aliasList.toArray(new ManifestElement[aliasList.size()]);
162     }
163
164     private static String JavaDoc[][] getGenericAliases(StateImpl state) {
165         Dictionary[] platformProps = state == null ? null : state.getPlatformProperties();
166         String JavaDoc genericAliasesProp = platformProps == null || platformProps.length == 0 ? null : (String JavaDoc) platformProps[0].get("osgi.genericAliases"); //$NON-NLS-1$
167
if (genericAliasesProp == null)
168             return new String JavaDoc[0][0];
169         String JavaDoc[] aliases = ManifestElement.getArrayFromList(genericAliasesProp, ","); //$NON-NLS-1$
170
String JavaDoc[][] result = new String JavaDoc[aliases.length][];
171         for (int i = 0; i < aliases.length; i++)
172             result[i] = ManifestElement.getArrayFromList(aliases[i], ":"); //$NON-NLS-1$
173
return result;
174     }
175
176     private static void validateHeaders(Dictionary manifest, boolean jreBundle) throws BundleException {
177         for (int i = 0; i < DEFINED_OSGI_VALIDATE_HEADERS.length; i++) {
178             String JavaDoc header = (String JavaDoc) manifest.get(DEFINED_OSGI_VALIDATE_HEADERS[i]);
179             if (header != null) {
180                 ManifestElement[] elements = ManifestElement.parseHeader(DEFINED_OSGI_VALIDATE_HEADERS[i], header);
181                 checkForDuplicateDirectives(elements);
182                 if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.REEXPORT_PACKAGE)
183                     checkForUsesDirective(elements);
184                 if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.IMPORT_PACKAGE)
185                     checkImportExportSyntax(elements, false, false, jreBundle);
186                 if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.DYNAMICIMPORT_PACKAGE)
187                     checkImportExportSyntax(elements, false, true, jreBundle);
188                 if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.EXPORT_PACKAGE)
189                     checkImportExportSyntax(elements, true, false, jreBundle);
190                 if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.FRAGMENT_HOST)
191                     checkExtensionBundle(elements);
192             } else if (DEFINED_OSGI_VALIDATE_HEADERS[i] == Constants.BUNDLE_SYMBOLICNAME) {
193                 throw new BundleException(NLS.bind(StateMsg.HEADER_REQUIRED, Constants.BUNDLE_SYMBOLICNAME));
194             }
195         }
196     }
197
198     private static BundleSpecification[] createRequiredBundles(ManifestElement[] specs) {
199         if (specs == null)
200             return null;
201         BundleSpecification[] result = new BundleSpecification[specs.length];
202         for (int i = 0; i < specs.length; i++)
203             result[i] = createRequiredBundle(specs[i]);
204         return result;
205     }
206
207     private static BundleSpecification createRequiredBundle(ManifestElement spec) {
208         BundleSpecificationImpl result = new BundleSpecificationImpl();
209         result.setName(spec.getValue());
210         result.setVersionRange(getVersionRange(spec.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)));
211         result.setExported(Constants.VISIBILITY_REEXPORT.equals(spec.getDirective(Constants.VISIBILITY_DIRECTIVE)) || "true".equals(spec.getAttribute(Constants.REPROVIDE_ATTRIBUTE))); //$NON-NLS-1$
212
result.setOptional(Constants.RESOLUTION_OPTIONAL.equals(spec.getDirective(Constants.RESOLUTION_DIRECTIVE)) || "true".equals(spec.getAttribute(Constants.OPTIONAL_ATTRIBUTE))); //$NON-NLS-1$
213
return result;
214     }
215
216     private static ImportPackageSpecification[] createImportPackages(ExportPackageDescription[] exported, ArrayList providedExports, ManifestElement[] imported, ManifestElement[] dynamicImported, int manifestVersion) throws BundleException {
217         ArrayList allImports = null;
218         if (manifestVersion < 2) {
219             // add implicit imports for each exported package if manifest verions is less than 2.
220
if (exported.length == 0 && imported == null && dynamicImported == null)
221                 return null;
222             allImports = new ArrayList(exported.length + (imported == null ? 0 : imported.length));
223             for (int i = 0; i < exported.length; i++) {
224                 if (providedExports.contains(exported[i].getName()))
225                     continue;
226                 ImportPackageSpecificationImpl result = new ImportPackageSpecificationImpl();
227                 result.setName(exported[i].getName());
228                 result.setVersionRange(getVersionRange(exported[i].getVersion().toString()));
229                 result.setDirective(Constants.RESOLUTION_DIRECTIVE, ImportPackageSpecification.RESOLUTION_STATIC);
230                 allImports.add(result);
231             }
232         } else {
233             allImports = new ArrayList(imported == null ? 0 : imported.length);
234         }
235
236         // add dynamics first so they will get overriden by static imports if
237
// the same package is dyanamically imported and statically imported.
238
if (dynamicImported != null)
239             for (int i = 0; i < dynamicImported.length; i++)
240                 addImportPackages(dynamicImported[i], allImports, manifestVersion, true);
241         if (imported != null)
242             for (int i = 0; i < imported.length; i++)
243                 addImportPackages(imported[i], allImports, manifestVersion, false);
244         return (ImportPackageSpecification[]) allImports.toArray(new ImportPackageSpecification[allImports.size()]);
245     }
246
247     private static void addImportPackages(ManifestElement importPackage, ArrayList allImports, int manifestVersion, boolean dynamic) throws BundleException {
248         String JavaDoc[] importNames = importPackage.getValueComponents();
249         for (int i = 0; i < importNames.length; i++) {
250             // do not allow for multiple imports of same package of manifest version < 2
251
if (manifestVersion < 2) {
252                 Iterator iter = allImports.iterator();
253                 while (iter.hasNext())
254                     if (importNames[i].equals(((ImportPackageSpecification) iter.next()).getName()))
255                         iter.remove();
256             }
257
258             ImportPackageSpecificationImpl result = new ImportPackageSpecificationImpl();
259             result.setName(importNames[i]);
260             // set common attributes for both dynamic and static imports
261
String JavaDoc versionString = importPackage.getAttribute(Constants.VERSION_ATTRIBUTE);
262             if (versionString == null) // specification-version aliases to version
263
versionString = importPackage.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
264             result.setVersionRange(getVersionRange(versionString));
265             result.setBundleSymbolicName(importPackage.getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE));
266             result.setBundleVersionRange(getVersionRange(importPackage.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)));
267             // only set the matching attributes if manfest version >= 2
268
if (manifestVersion >= 2)
269                 result.setAttributes(getAttributes(importPackage, DEFINED_MATCHING_ATTRS));
270
271             if (dynamic)
272                 result.setDirective(Constants.RESOLUTION_DIRECTIVE, ImportPackageSpecification.RESOLUTION_DYNAMIC);
273             else
274                 result.setDirective(Constants.RESOLUTION_DIRECTIVE, getResolution(importPackage.getDirective(Constants.RESOLUTION_DIRECTIVE)));
275
276             allImports.add(result);
277         }
278     }
279
280     private static String JavaDoc getResolution(String JavaDoc resolution) {
281         String JavaDoc result = ImportPackageSpecification.RESOLUTION_STATIC;
282         if (Constants.RESOLUTION_OPTIONAL.equals(resolution))
283             result = ImportPackageSpecification.RESOLUTION_OPTIONAL;
284         return result;
285     }
286
287     static ExportPackageDescription[] createExportPackages(ManifestElement[] exported, ManifestElement[] reexported, ManifestElement[] provides, ArrayList providedExports, int manifestVersion, boolean strict) throws BundleException {
288         int numExports = (exported == null ? 0 : exported.length) + (reexported == null ? 0 : reexported.length) + (provides == null ? 0 : provides.length);
289         if (numExports == 0)
290             return null;
291         ArrayList allExports = new ArrayList(numExports);
292         if (exported != null)
293             for (int i = 0; i < exported.length; i++)
294                 addExportPackages(exported[i], allExports, manifestVersion, false, strict);
295         if (reexported != null)
296             for (int i = 0; i < reexported.length; i++)
297                 addExportPackages(reexported[i], allExports, manifestVersion, true, strict);
298         if (provides != null)
299             addProvidePackages(provides, allExports, providedExports);
300         return (ExportPackageDescription[]) allExports.toArray(new ExportPackageDescription[allExports.size()]);
301     }
302
303     private static void addExportPackages(ManifestElement exportPackage, ArrayList allExports, int manifestVersion, boolean reexported, boolean strict) throws BundleException {
304         String JavaDoc[] exportNames = exportPackage.getValueComponents();
305         for (int i = 0; i < exportNames.length; i++) {
306             // if we are in strict mode and the package is marked as internal, skip it.
307
if (strict && "true".equals(exportPackage.getDirective(Constants.INTERNAL_DIRECTIVE))) //$NON-NLS-1$
308
continue;
309             ExportPackageDescriptionImpl result = new ExportPackageDescriptionImpl();
310             result.setName(exportNames[i]);
311             String JavaDoc versionString = exportPackage.getAttribute(Constants.VERSION_ATTRIBUTE);
312             if (versionString == null) // specification-version aliases to version
313
versionString = exportPackage.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
314             if (versionString != null)
315                 result.setVersion(Version.parseVersion(versionString));
316             result.setDirective(Constants.USES_DIRECTIVE, ManifestElement.getArrayFromList(exportPackage.getDirective(Constants.USES_DIRECTIVE)));
317             result.setDirective(Constants.INCLUDE_DIRECTIVE, exportPackage.getDirective(Constants.INCLUDE_DIRECTIVE));
318             result.setDirective(Constants.EXCLUDE_DIRECTIVE, exportPackage.getDirective(Constants.EXCLUDE_DIRECTIVE));
319             result.setDirective(Constants.FRIENDS_DIRECTIVE, ManifestElement.getArrayFromList(exportPackage.getDirective(Constants.FRIENDS_DIRECTIVE)));
320             result.setDirective(Constants.INTERNAL_DIRECTIVE, Boolean.valueOf(exportPackage.getDirective(Constants.INTERNAL_DIRECTIVE)));
321             result.setDirective(Constants.MANDATORY_DIRECTIVE, ManifestElement.getArrayFromList(exportPackage.getDirective(Constants.MANDATORY_DIRECTIVE)));
322             result.setAttributes(getAttributes(exportPackage, DEFINED_MATCHING_ATTRS));
323             result.setRoot(!reexported);
324             allExports.add(result);
325         }
326     }
327
328     private static void addProvidePackages(ManifestElement[] provides, ArrayList allExports, ArrayList providedExports) throws BundleException {
329         ExportPackageDescription[] currentExports = (ExportPackageDescription[]) allExports.toArray(new ExportPackageDescription[allExports.size()]);
330         for (int i = 0; i < provides.length; i++) {
331             boolean duplicate = false;
332             for (int j = 0; j < currentExports.length; j++)
333                 if (provides[i].getValue().equals(currentExports[j].getName())) {
334                     duplicate = true;
335                     break;
336                 }
337             if (!duplicate) {
338                 ExportPackageDescriptionImpl result = new ExportPackageDescriptionImpl();
339                 result.setName(provides[i].getValue());
340                 result.setRoot(true);
341                 allExports.add(result);
342             }
343             providedExports.add(provides[i].getValue());
344         }
345     }
346
347     private static Map getAttributes(ManifestElement exportPackage, String JavaDoc[] definedAttrs) {
348         Enumeration keys = exportPackage.getKeys();
349         Map arbitraryAttrs = null;
350         if (keys == null)
351             return null;
352         while (keys.hasMoreElements()) {
353             boolean definedAttr = false;
354             String JavaDoc key = (String JavaDoc) keys.nextElement();
355             for (int i = 0; i < definedAttrs.length; i++) {
356                 if (definedAttrs[i].equals(key)) {
357                     definedAttr = true;
358                     break;
359                 }
360             }
361             String JavaDoc value = exportPackage.getAttribute(key);
362             int colonIndex = key.indexOf(':');
363             String JavaDoc type = ATTR_TYPE_STRING;
364             if (colonIndex > 0) {
365                 type = key.substring(colonIndex + 1);
366                 key = key.substring(0, colonIndex);
367             }
368             if (!definedAttr) {
369                 if (arbitraryAttrs == null)
370                     arbitraryAttrs = new HashMap();
371                 Object JavaDoc putValue = value;
372                 if (ATTR_TYPE_STRING.equals(type))
373                     putValue = value;
374                 else if (ATTR_TYPE_DOUBLE.equals(type))
375                     putValue = new Double JavaDoc(value);
376                 else if (ATTR_TYPE_LONG.equals(type))
377                     putValue = new Long JavaDoc(value);
378                 else if (ATTR_TYPE_URI.equals(type))
379                     try {
380                         Class JavaDoc uriClazz = Class.forName("java.net.URI"); //$NON-NLS-1$
381
Constructor JavaDoc constructor = uriClazz.getConstructor(new Class JavaDoc[] {String JavaDoc.class});
382                         putValue = constructor.newInstance(new Object JavaDoc[] {value});
383                     } catch (ClassNotFoundException JavaDoc e) {
384                         // oh well cannot support; just use string
385
putValue = value;
386                     } catch (Exception JavaDoc e) { // got some reflection exception
387
if (e instanceof RuntimeException JavaDoc)
388                             throw (RuntimeException JavaDoc) e;
389                         throw new RuntimeException JavaDoc(e.getMessage());
390                     }
391                 else if (ATTR_TYPE_VERSION.equals(type))
392                     putValue = new Version(value);
393                 else if (ATTR_TYPE_SET.equals(type))
394                     putValue = ManifestElement.getArrayFromList(value, ","); //$NON-NLS-1$
395
arbitraryAttrs.put(key, putValue);
396             }
397         }
398         return arbitraryAttrs;
399     }
400
401     private static HostSpecification createHostSpecification(ManifestElement spec) {
402         if (spec == null)
403             return null;
404         HostSpecificationImpl result = new HostSpecificationImpl();
405         result.setName(spec.getValue());
406         result.setVersionRange(getVersionRange(spec.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)));
407         result.setIsMultiHost("true".equals(spec.getDirective("multiple-hosts"))); //$NON-NLS-1$ //$NON-NLS-2$
408
return result;
409     }
410
411     private static GenericSpecification[] createGenericRequires(ManifestElement[] genericRequires) throws BundleException {
412         if (genericRequires == null)
413             return null;
414         ArrayList results = new ArrayList(genericRequires.length);
415         for (int i = 0; i < genericRequires.length; i++) {
416             String JavaDoc[] genericNames = genericRequires[i].getValueComponents();
417             for (int j = 0; j < genericNames.length; j++) {
418                 GenericSpecificationImpl spec = new GenericSpecificationImpl();
419                 int colonIdx = genericNames[j].indexOf(':');
420                 if (colonIdx > 0) {
421                     spec.setName(genericNames[j].substring(0, colonIdx));
422                     spec.setType(genericNames[j].substring(colonIdx + 1));
423                 } else
424                     spec.setName(genericNames[j]);
425                 try {
426                     spec.setMatchingFilter(genericRequires[i].getAttribute(Constants.SELECTION_FILTER_ATTRIBUTE));
427                 } catch (InvalidSyntaxException e) {
428                     throw new BundleException(Constants.SELECTION_FILTER_ATTRIBUTE, e);
429                 }
430                 String JavaDoc optional = genericRequires[i].getAttribute(OPTIONAL_ATTR);
431                 String JavaDoc multiple = genericRequires[i].getAttribute(MULTIPLE_ATTR);
432                 int resolution = 0;
433                 if (TRUE.equals(optional))
434                     resolution |= GenericSpecification.RESOLUTION_OPTIONAL;
435                 if (TRUE.equals(multiple))
436                     resolution |= GenericSpecification.RESOLUTION_MULTIPLE;
437                 spec.setResolution(resolution);
438                 results.add(spec);
439             }
440         }
441         return (GenericSpecification[]) results.toArray(new GenericSpecification[results.size()]);
442     }
443
444     private static GenericDescription[] createGenericCapabilities(ManifestElement[] genericCapabilities) {
445         if (genericCapabilities == null)
446             return null;
447         ArrayList results = new ArrayList(genericCapabilities.length);
448         for (int i = 0; i < genericCapabilities.length; i++) {
449             String JavaDoc[] genericNames = genericCapabilities[i].getValueComponents();
450             for (int j = 0; j < genericNames.length; j++) {
451                 GenericDescriptionImpl desc = new GenericDescriptionImpl();
452                 int colonIdx = genericNames[j].indexOf(':');
453                 if (colonIdx > 0) {
454                     desc.setName(genericNames[j].substring(0, colonIdx));
455                     desc.setType(genericNames[j].substring(colonIdx + 1));
456                 } else
457                     desc.setName(genericNames[j]);
458                 String JavaDoc versionString = genericCapabilities[i].getAttribute(Constants.VERSION_ATTRIBUTE);
459                 if (versionString != null)
460                     desc.setVersion(Version.parseVersion(versionString));
461                 Map mapAttrs = getAttributes(genericCapabilities[i], new String JavaDoc[] {Constants.VERSION_ATTRIBUTE});
462                 Object JavaDoc version = mapAttrs == null ? null : mapAttrs.remove(Constants.VERSION_ATTRIBUTE);
463                 if (version instanceof Version) // this is just incase someone uses version:version as a key
464
desc.setVersion((Version) version);
465                 Dictionary attrs = new Hashtable();
466                 if (mapAttrs != null) {
467                     for (Iterator keys = mapAttrs.keySet().iterator(); keys.hasNext();) {
468                         Object JavaDoc key = keys.next();
469                         attrs.put(key, mapAttrs.get(key));
470                     }
471                 }
472                 desc.setAttributes(attrs);
473                 results.add(desc);
474             }
475         }
476         return (GenericDescription[]) results.toArray(new GenericDescription[results.size()]);
477     }
478
479     private static VersionRange getVersionRange(String JavaDoc versionRange) {
480         if (versionRange == null)
481             return null;
482         return new VersionRange(versionRange);
483     }
484
485     private static void checkImportExportSyntax(ManifestElement[] elements, boolean export, boolean dynamic, boolean jreBundle) throws BundleException {
486         if (elements == null)
487             return;
488         int length = elements.length;
489         Set packages = new HashSet(length);
490         for (int i = 0; i < length; i++) {
491             // check for duplicate imports
492
String JavaDoc[] packageNames = elements[i].getValueComponents();
493             for (int j = 0; j < packageNames.length; j++) {
494                 if (!export && !dynamic && packages.contains(packageNames[j]))
495                     throw new BundleException(NLS.bind(StateMsg.HEADER_PACKAGE_DUPLICATES, packageNames[j]));
496                 // check for java.*
497
if (!jreBundle && packageNames[j].startsWith("java.")) //$NON-NLS-1$
498
throw new BundleException(NLS.bind(StateMsg.HEADER_PACKAGE_JAVA, packageNames[j]));
499                 packages.add(packageNames[j]);
500             }
501             // check for version/specification version mismatch
502
String JavaDoc version = elements[i].getAttribute(Constants.VERSION_ATTRIBUTE);
503             if (version != null) {
504                 String JavaDoc specVersion = elements[i].getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
505                 if (specVersion != null && !specVersion.equals(version))
506                     throw new BundleException(NLS.bind(StateMsg.HEADER_VERSION_ERROR, Constants.VERSION_ATTRIBUTE, Constants.PACKAGE_SPECIFICATION_VERSION));
507             }
508             // check for bundle-symbolic-name and bundle-verion attibures
509
// (failure)
510
if (export) {
511                 if (elements[i].getAttribute(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE) != null)
512                     throw new BundleException(NLS.bind(StateMsg.HEADER_EXPORT_ATTR_ERROR, Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, Constants.EXPORT_PACKAGE));
513                 if (elements[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE) != null)
514                     throw new BundleException(NLS.bind(StateMsg.HEADER_EXPORT_ATTR_ERROR, Constants.BUNDLE_VERSION_ATTRIBUTE, Constants.EXPORT_PACKAGE));
515             }
516         }
517     }
518
519     private static void checkForDuplicateDirectives(ManifestElement[] elements) throws BundleException {
520         // check for duplicate directives
521
for (int i = 0; i < elements.length; i++) {
522             Enumeration keys = elements[i].getDirectiveKeys();
523             if (keys != null) {
524                 while (keys.hasMoreElements()) {
525                     String JavaDoc key = (String JavaDoc) keys.nextElement();
526                     String JavaDoc[] directives = elements[i].getDirectives(key);
527                     if (directives.length > 1)
528                         throw new BundleException(NLS.bind(StateMsg.HEADER_DIRECTIVE_DUPLICATES, key));
529                 }
530             }
531         }
532     }
533
534     private static void checkForUsesDirective(ManifestElement[] elements) throws BundleException {
535         for (int i = 0; i < elements.length; i++)
536             if (elements[i].getDirective(Constants.USES_DIRECTIVE) != null)
537                 throw new BundleException(NLS.bind(StateMsg.HEADER_REEXPORT_USES, Constants.USES_DIRECTIVE, Constants.REEXPORT_PACKAGE));
538     }
539
540     private static void checkExtensionBundle(ManifestElement[] elements) throws BundleException {
541         if (elements.length == 0 || elements[0].getDirective(Constants.EXTENSION_DIRECTIVE) == null)
542             return;
543         String JavaDoc hostName = elements[0].getValue();
544         if (!hostName.equals(Constants.SYSTEM_BUNDLE_SYMBOLICNAME) && !hostName.equals(Constants.getInternalSymbolicName()))
545             throw new BundleException(NLS.bind(StateMsg.HEADER_EXTENSION_ERROR, hostName));
546     }
547 }
548
Popular Tags