/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.application.modelling.impl;
import static org.apache.aries.application.utils.AppConstants.LOG_ENTRY;
import static org.apache.aries.application.utils.AppConstants.LOG_EXIT;
import static org.osgi.framework.Constants.BUNDLE_VERSION_ATTRIBUTE;
import static org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE;
import static org.osgi.framework.Constants.EXPORT_PACKAGE;
import static org.osgi.framework.Constants.EXPORT_SERVICE;
import static org.osgi.framework.Constants.IMPORT_PACKAGE;
import static org.osgi.framework.Constants.IMPORT_SERVICE;
import static org.osgi.framework.Constants.REQUIRE_BUNDLE;
import static org.osgi.framework.Constants.RESOLUTION_DIRECTIVE;
import static org.osgi.framework.Constants.RESOLUTION_OPTIONAL;
import static org.osgi.framework.Constants.VERSION_ATTRIBUTE;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
import org.apache.aries.application.InvalidAttributeException;
import org.apache.aries.application.management.BundleInfo;
import org.apache.aries.application.modelling.ExportedBundle;
import org.apache.aries.application.modelling.ExportedPackage;
import org.apache.aries.application.modelling.ExportedService;
import org.apache.aries.application.modelling.ImportedBundle;
import org.apache.aries.application.modelling.ImportedPackage;
import org.apache.aries.application.modelling.ImportedService;
import org.apache.aries.application.modelling.ModelledResource;
import org.apache.aries.application.modelling.ModellingConstants;
import org.apache.aries.application.modelling.ResourceType;
import org.apache.aries.util.manifest.ManifestHeaderProcessor;
import org.apache.aries.util.manifest.ManifestHeaderProcessor.NameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A model of a bundle or composite. Used for example to supply information to
* RepositoryGenerator.generateRepository()
*
*/
public class ModelledResourceImpl implements ModelledResource
{
private final Logger logger = LoggerFactory.getLogger(ModelledResourceImpl.class);
private final String _fileURI;
private final Collection<ImportedService> _importedServices;
private final Collection<ExportedService> _exportedServices;
private final Collection<ExportedPackage> _exportedPackages;
private final Collection<ImportedPackage> _importedPackages;
private final Collection<ImportedBundle> _requiredBundles;
private final ExportedBundle _exportedBundle;
private final ResourceType _resourceType;
/**
* Construct a new {@link ModelledResourceImpl} for the following manifest and services
* @param fileURI The location of the bundle, may be null, which indicates a by value bundle
* @param bundleInfo The bundle info object
* @param importedServices The blueprint references defined by the bundle. May be null
* @param exportedServices The blueprint services exported by the bundle. May be null
* @throws InvalidAttributeException
*/
public ModelledResourceImpl (String fileURI, BundleInfo bundleInfo,
Collection<ImportedService> importedServices,
Collection<ExportedService> exportedServices) throws InvalidAttributeException
{
this(fileURI, bundleInfo.getRawAttributes(), importedServices, exportedServices);
}
/**
* Construct a new {@link ModelledResourceImpl} for the following manifest and services
* @param fileURI The location of the bundle, may be null, which indicates a by value bundle
* @param bundleAttributes The bundle manifest, must not be null
* @param importedServices The blueprint references defined by the bundle. May be null
* @param exportedServices The blueprint services exported by the bundle. May be null
* @throws InvalidAttributeException
*/
@SuppressWarnings("deprecation")
public ModelledResourceImpl (String fileURI, Attributes bundleAttributes, ExportedBundle exportedBundle, ResourceType resourceType,
Collection<ImportedService> importedServices,
Collection<ExportedService> exportedServices) throws InvalidAttributeException
{
this (fileURI, bundleAttributes, resourceType, exportedBundle, importedServices, exportedServices);
logger.debug(LOG_ENTRY, "ModelledResourceImpl", new Object[]{fileURI, bundleAttributes, importedServices, exportedServices});
logger.debug(LOG_EXIT, "ModelledResourceImpl");
}
/**
* Construct a new {@link ModelledResourceImpl} for the following manifest and services
* @param fileURI The location of the bundle, may be null, which indicates a by value bundle
* @param bundleAttributes The bundle manifest, must not be null
* @param importedServices The blueprint references defined by the bundle. May be null
* @param exportedServices The blueprint services exported by the bundle. May be null
* @throws InvalidAttributeException
*/
@SuppressWarnings("deprecation")
public ModelledResourceImpl (String fileURI, Attributes bundleAttributes,
Collection<ImportedService> importedServices,
Collection<ExportedService> exportedServices) throws InvalidAttributeException
{
this (fileURI, bundleAttributes, ResourceType.BUNDLE, null, importedServices, exportedServices );
logger.debug(LOG_ENTRY, "ModelledResourceImpl", new Object[]{fileURI, bundleAttributes, importedServices, exportedServices});
logger.debug(LOG_EXIT, "ModelledResourceImpl");
}
public ModelledResourceImpl (String fileURI, Attributes bundleAttributes,
ResourceType resourceType, ExportedBundle exportedBundle,
Collection<ImportedService> importedServices,
Collection<ExportedService> exportedServices
) throws InvalidAttributeException
{
logger.debug(LOG_ENTRY, "ModelledResourceImpl", new Object[]{fileURI, bundleAttributes, importedServices, exportedServices,
resourceType});
if (exportedBundle == null) {
_exportedBundle = new ExportedBundleImpl (bundleAttributes);
} else {
_exportedBundle = exportedBundle;
}
_resourceType = resourceType;
_fileURI = fileURI;
if(importedServices != null)
_importedServices = new ArrayList<ImportedService> (importedServices);
else
_importedServices = new ArrayList<ImportedService>();
if(exportedServices != null)
_exportedServices = new ArrayList<ExportedService> (exportedServices);
else
_exportedServices = new ArrayList<ExportedService>();
_exportedPackages = new ArrayList<ExportedPackage>();
String packageExports = bundleAttributes.getValue(EXPORT_PACKAGE);
if (packageExports != null) {
List<NameValuePair> exportedPackages = ManifestHeaderProcessor
.parseExportString(packageExports);
for (NameValuePair exportedPackage : exportedPackages) {
_exportedPackages.add(new ExportedPackageImpl(this, exportedPackage.getName(),
new HashMap<String, Object>(exportedPackage.getAttributes())));
}
}
_importedPackages = new ArrayList<ImportedPackage>();
String packageImports = bundleAttributes.getValue(IMPORT_PACKAGE);
if (packageImports != null) {
Map<String, Map<String, String>> importedPackages = ManifestHeaderProcessor
.parseImportString(packageImports);
for (Map.Entry<String, Map<String, String>> importedPackage : importedPackages.entrySet()) {
Map<String, String> atts = importedPackage.getValue();
_importedPackages.add(new ImportedPackageImpl(importedPackage.getKey(), atts));
}
}
// Use of Import-Service and Export-Service is deprecated in OSGi. We like Blueprint.
// Blueprint is good.
String serviceExports = null;
if (_resourceType == ResourceType.BUNDLE) {
serviceExports = bundleAttributes.getValue(EXPORT_SERVICE);
}
if (serviceExports != null) {
List<NameValuePair> expServices = ManifestHeaderProcessor
.parseExportString(serviceExports);
for (NameValuePair exportedService : expServices) {
_exportedServices.add(new ExportedServiceImpl(exportedService.getName(), exportedService.getAttributes()));
}
}
String serviceImports =null;
if (_resourceType == ResourceType.BUNDLE) {
serviceImports = bundleAttributes.getValue(IMPORT_SERVICE);
}
if (serviceImports != null) {
Map<String, Map<String, String>> svcImports = ManifestHeaderProcessor
.parseImportString(serviceImports);
for (Map.Entry<String, Map<String, String>> importedService : svcImports.entrySet()) {
_importedServices.add(new ImportedServiceImpl(importedService.getKey(), importedService.getValue()));
}
}
_requiredBundles = new ArrayList<ImportedBundle>();
// Require-Bundle and DynamicImport-Package relevant to Bundles but not Composites
if (_resourceType == ResourceType.BUNDLE) {
String requireBundleHeader = bundleAttributes.getValue(REQUIRE_BUNDLE);
if (requireBundleHeader != null) {
Map<String, Map<String, String>> requiredBundles = ManifestHeaderProcessor
.parseImportString(requireBundleHeader);
for (Map.Entry<String, Map<String, String>> bundle : requiredBundles.entrySet()) {
String type = bundle.getKey();
Map<String, String> attribs = bundle.getValue();
// We may parse a manifest with a header like Require-Bundle: bundle.a;bundle-version=3.0.0
// The filter that we generate is intended for OBR in which case we need (version>=3.0.0) and not (bundle-version>=3.0.0)
String bundleVersion = attribs.remove(BUNDLE_VERSION_ATTRIBUTE);
if (bundleVersion != null && attribs.get(VERSION_ATTRIBUTE) == null) {
attribs.put (VERSION_ATTRIBUTE, bundleVersion);
}
String filter = ManifestHeaderProcessor.generateFilter(ModellingConstants.OBR_SYMBOLIC_NAME, type, attribs);
Map<String, String> atts = new HashMap<String, String>(bundle.getValue());
atts.put(ModellingConstants.OBR_SYMBOLIC_NAME, bundle.getKey());
_requiredBundles.add(new ImportedBundleImpl(filter, atts));
}
}
String dynamicImports = bundleAttributes.getValue(DYNAMICIMPORT_PACKAGE);
if (dynamicImports != null) {
Map<String, Map<String, String>> dynamicImportPackages = ManifestHeaderProcessor
.parseImportString(dynamicImports);
for (Map.Entry<String, Map<String, String>> dynImportPkg : dynamicImportPackages.entrySet()) {
if (dynImportPkg.getKey().indexOf("*") == -1) {
dynImportPkg.getValue().put(RESOLUTION_DIRECTIVE + ":", RESOLUTION_OPTIONAL);
_importedPackages.add(new ImportedPackageImpl(dynImportPkg.getKey(), dynImportPkg.getValue()));
}
}
}
}
logger.debug(LOG_EXIT, "ModelledResourceImpl");
}
public String getLocation() {
logger.debug(LOG_ENTRY, "getLocation");
logger.debug(LOG_EXIT, "getLocation", _fileURI);
return _fileURI;
}
public ExportedBundle getExportedBundle() {
logger.debug(LOG_ENTRY, "getExportedBundle");
logger.debug(LOG_EXIT, "getExportedBundle", _exportedBundle);
return _exportedBundle;
}
public Collection<ExportedPackage> getExportedPackages() {
logger.debug(LOG_ENTRY, "getExportedPackages");
logger.debug(LOG_EXIT, "getExportedPackages", _exportedPackages);
return Collections.unmodifiableCollection(_exportedPackages);
}
public Collection<ImportedPackage> getImportedPackages() {
logger.debug(LOG_ENTRY, "getImportedPackages");
logger.debug(LOG_EXIT, "getImportedPackages", _importedPackages);
return Collections.unmodifiableCollection(_importedPackages);
}
public Collection<ExportedService> getExportedServices() {
logger.debug(LOG_ENTRY, "getExportedServices");
logger.debug(LOG_EXIT, "getExportedServices", _exportedServices);
return Collections.unmodifiableCollection(_exportedServices);
}
public Collection<ImportedService> getImportedServices() {
logger.debug(LOG_ENTRY, "getImportedServices");
logger.debug(LOG_EXIT, "getImportedServices", _exportedServices);
return Collections.unmodifiableCollection(_importedServices);
}
public String getSymbolicName() {
logger.debug(LOG_ENTRY, "getSymbolicName");
String result = _exportedBundle.getSymbolicName();
logger.debug(LOG_EXIT, "getSymbolicName", result);
return result;
}
public String getVersion() {
logger.debug(LOG_ENTRY, "getVersion");
String result = _exportedBundle.getVersion();
logger.debug(LOG_EXIT, "getVersion", result);
return result;
}
public String toDeploymentString() {
logger.debug(LOG_ENTRY, "toDeploymentString");
String result = _exportedBundle.toDeploymentString();
logger.debug(LOG_EXIT, "toDeploymentString", result);
return result;
}
public ResourceType getType() {
logger.debug(LOG_ENTRY, "getType");
logger.debug(LOG_EXIT, "getType", ResourceType.BUNDLE);
return _resourceType;
}
public String toString() {
return toDeploymentString();
}
public Collection<ImportedBundle> getRequiredBundles() {
logger.debug(LOG_ENTRY, "getRequiredBundles");
logger.debug(LOG_EXIT, "getRequiredBundles", _requiredBundles);
return Collections.unmodifiableCollection(_requiredBundles);
}
public ImportedBundle getFragmentHost() {
logger.debug(LOG_ENTRY, "getFragmentHost");
ImportedBundle result = _exportedBundle.getFragmentHost();
logger.debug(LOG_EXIT, "getFragmentHost", result);
return result;
}
public boolean isFragment() {
logger.debug(LOG_ENTRY, "isFragment");
boolean result = _exportedBundle.isFragment();
logger.debug(LOG_EXIT, "isFragment", result);
return result;
}
}