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 10:00:08 +0200 (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 }