001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.xbean.osgi.bundle.util;
020
021 import java.util.ArrayList;
022 import java.util.Dictionary;
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.jar.Attributes;
027 import java.util.jar.Manifest;
028
029 import org.apache.xbean.osgi.bundle.util.HeaderParser.HeaderElement;
030 import org.osgi.framework.Constants;
031 import org.osgi.framework.Version;
032
033 /**
034 * @version $Rev: 937957 $, $Date: 2010-04-26 16:00:08 +0800 (Mon, 26 Apr 2010) $
035 */
036 public class BundleDescription {
037
038 private Map headers;
039
040 public BundleDescription(Manifest manifest) {
041 this.headers = manifestToMap(manifest);
042 }
043
044 public BundleDescription(Dictionary dictionary) {
045 this.headers = new DictionaryMap(dictionary);
046 }
047
048 public BundleDescription(Map headers) {
049 this.headers = headers;
050 }
051
052 /**
053 * Returns a list of packages that are listed in <i>Import-Package</i> header.
054 */
055 public List<ImportPackage> getImportPackage() {
056 String headerValue = (String) headers.get(Constants.IMPORT_PACKAGE);
057 List<ImportPackage> imports = new ArrayList<ImportPackage>();
058 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
059 for (HeaderElement element : elements) {
060 ImportPackage p = new ImportPackage(element.getName(), element.getAttributes(), element.getDirectives());
061 imports.add(p);
062 }
063 return imports;
064 }
065
066 /**
067 * Returns a list of packages that are listed in <i>Export-Package</i> header.
068 */
069 public List<ExportPackage> getExportPackage() {
070 String headerValue = (String) headers.get(Constants.EXPORT_PACKAGE);
071 List<ExportPackage> exports = new ArrayList<ExportPackage>();
072 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
073 for (HeaderElement element : elements) {
074 ExportPackage p = new ExportPackage(element.getName(), element.getAttributes(), element.getDirectives());
075 exports.add(p);
076 }
077 return exports;
078 }
079
080 /**
081 * Returns a list of packages that are listed in <i>Import-Package</i> header
082 * and are <b>not</b> listed in <i>Export-Package</i> header.
083 */
084 public List<ImportPackage> getExternalImports() {
085 List<ImportPackage> imports = getImportPackage();
086 List<ExportPackage> exports = getExportPackage();
087 List<ImportPackage> realImports = new ArrayList<ImportPackage>();
088 for (ImportPackage p : imports) {
089 if (!isExported(exports, p)) {
090 realImports.add(p);
091 }
092 }
093 return realImports;
094 }
095
096 private static boolean isExported(List<ExportPackage> exports, ImportPackage p) {
097 for (ExportPackage export : exports) {
098 if (export.getName().equals(p.getName())) {
099 return true;
100 }
101 }
102 return false;
103 }
104
105 /**
106 * Returns a list of bundle names that are listed in <i>Require-Bundle</i> header.
107 */
108 public List<RequireBundle> getRequireBundle() {
109 String headerValue = (String) headers.get(Constants.REQUIRE_BUNDLE);
110 List<RequireBundle> requireBundles = new ArrayList<RequireBundle>();
111 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
112 for (HeaderElement element : elements) {
113 RequireBundle p = new RequireBundle(element.getName(), element.getAttributes(), element.getDirectives());
114 requireBundles.add(p);
115 }
116 return requireBundles;
117 }
118
119 /**
120 * Returns <i>Fragment-Host</i> header.
121 */
122 public FragmentHost getFragmentHost() {
123 String headerValue = (String) headers.get(Constants.FRAGMENT_HOST);
124 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
125 if (elements.size() == 1) {
126 HeaderElement element = elements.get(0);
127 return new FragmentHost(element.getName(), element.getAttributes(), element.getDirectives());
128 }
129 return null;
130 }
131
132 /**
133 * Returns a list of packages that are listed in <i>DynamicImport-Package</i> header.
134 */
135 public List<HeaderEntry> getDynamicImportPackage() {
136 String headerValue = (String) headers.get(Constants.DYNAMICIMPORT_PACKAGE);
137 return parseStandardHeader(headerValue);
138 }
139
140 /**
141 * Returns a list of paths that are listed in <i>Bundle-ClassPath</i> header.
142 */
143 public List<HeaderEntry> getBundleClassPath() {
144 String headerValue = (String) headers.get(Constants.BUNDLE_CLASSPATH);
145 return parseStandardHeader(headerValue);
146 }
147
148 public SymbolicName getSymbolicName() {
149 String headerValue = (String) headers.get(Constants.BUNDLE_SYMBOLICNAME);
150 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
151 if (elements.size() == 1) {
152 HeaderElement element = elements.get(0);
153 return new SymbolicName(element.getName(), element.getAttributes(), element.getDirectives());
154 }
155 return null;
156 }
157
158 public Version getVersion() {
159 String headerValue = (String) headers.get(Constants.BUNDLE_VERSION);
160 return getVersionRange(headerValue).getLow();
161 }
162
163 public Map getHeaders() {
164 return headers;
165 }
166
167 private List<HeaderEntry> parseStandardHeader(String headerValue) {
168 List<HeaderEntry> imports = new ArrayList<HeaderEntry>();
169 List<HeaderElement> elements = HeaderParser.parseHeader(headerValue);
170 for (HeaderElement element : elements) {
171 HeaderEntry p = new HeaderEntry(element.getName(), element.getAttributes(), element.getDirectives());
172 imports.add(p);
173 }
174 return imports;
175 }
176
177 private static Map<String, String> manifestToMap(Manifest manifest) {
178 Attributes attributes = manifest.getMainAttributes();
179 Map<String, String> headers = new HashMap<String, String>();
180 for (Map.Entry<Object, Object> entry : attributes.entrySet()) {
181 String key = entry.getKey().toString();
182 String value = entry.getValue().toString();
183 headers.put(key, value);
184 }
185 return headers;
186 }
187
188 private static VersionRange getVersionRange(String version) {
189 if (version == null) {
190 version = "0.0.0";
191 }
192 return VersionRange.parse(version);
193 }
194
195 public static class HeaderEntry {
196
197 private String name;
198 private Map<String, String> attributes;
199 private Map<String, String> directives;
200
201 public HeaderEntry(String name,
202 Map<String, String> attributes,
203 Map<String, String> directives) {
204 this.name = name;
205 this.attributes = attributes;
206 this.directives = directives;
207 }
208
209 public String getName() {
210 return name;
211 }
212
213 public Map<String, String> getAttributes() {
214 return attributes;
215 }
216
217 public Map<String, String> getDirectives() {
218 return directives;
219 }
220
221 public String toString() {
222 StringBuilder builder = new StringBuilder();
223 builder.append("Name: ").append(name);
224 builder.append(", Attributes: ").append(attributes);
225 builder.append(", Directives: ").append(directives);
226 return builder.toString();
227 }
228
229 }
230
231 public static class ExportPackage extends HeaderEntry {
232
233 private Version version;
234
235 public ExportPackage(String name,
236 Map<String, String> attributes,
237 Map<String, String> directives) {
238 super(name, attributes, directives);
239 version = BundleDescription.getVersionRange(attributes.get(Constants.VERSION_ATTRIBUTE)).getLow();
240 }
241
242 public Version getVersion() {
243 return version;
244 }
245 }
246
247 public static class ImportPackage extends HeaderEntry {
248
249 private boolean optional;
250 private VersionRange versionRange;
251
252 public ImportPackage(String name,
253 Map<String, String> attributes,
254 Map<String, String> directives) {
255 super(name, attributes, directives);
256
257 String resolution = directives.get(Constants.RESOLUTION_DIRECTIVE);
258 optional = Constants.RESOLUTION_OPTIONAL.equals(resolution);
259
260 versionRange = BundleDescription.getVersionRange(attributes.get(Constants.VERSION_ATTRIBUTE));
261 }
262
263 public boolean isOptional() {
264 return optional;
265 }
266
267 public boolean isMandatory() {
268 return !optional;
269 }
270
271 public VersionRange getVersionRange() {
272 return versionRange;
273 }
274 }
275
276 public static class SymbolicName extends HeaderEntry {
277
278 public SymbolicName(String name,
279 Map<String, String> attributes,
280 Map<String, String> directives) {
281 super(name, attributes, directives);
282 }
283
284 }
285
286 public static class RequireBundle extends HeaderEntry {
287
288 private boolean optional;
289 private VersionRange versionRange;
290
291 public RequireBundle(String name,
292 Map<String, String> attributes,
293 Map<String, String> directives) {
294 super(name, attributes, directives);
295
296 String resolution = directives.get(Constants.RESOLUTION_DIRECTIVE);
297 optional = Constants.RESOLUTION_OPTIONAL.equals(resolution);
298
299 versionRange = BundleDescription.getVersionRange(attributes.get(Constants.BUNDLE_VERSION_ATTRIBUTE));
300 }
301
302 public boolean isOptional() {
303 return optional;
304 }
305
306 public boolean isMandatory() {
307 return !optional;
308 }
309
310 public VersionRange getVersionRange() {
311 return versionRange;
312 }
313 }
314
315 public static class FragmentHost extends HeaderEntry {
316
317 private VersionRange versionRange;
318
319 public FragmentHost(String name,
320 Map<String, String> attributes,
321 Map<String, String> directives) {
322 super(name, attributes, directives);
323 versionRange = BundleDescription.getVersionRange(attributes.get(Constants.BUNDLE_VERSION_ATTRIBUTE));
324 }
325
326 public VersionRange getVersionRange() {
327 return versionRange;
328 }
329 }
330 }