blob: e196145c2ba9f2d585db80a3676c420b50fdd44d [file] [log] [blame]
/*
* 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
* WARRANTIES OR 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.sling.feature.resolver.impl;
import org.apache.felix.utils.resource.CapabilityImpl;
import org.apache.felix.utils.resource.RequirementImpl;
import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.resolver.FeatureResource;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.PackageInfo;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementation of the OSGi Resource interface.
*/
public class BundleResourceImpl extends AbstractResourceImpl implements FeatureResource {
final Artifact artifact;
final String bsn;
final Version version;
final Map<String, List<Capability>> capabilities;
final Map<String, List<Requirement>> requirements;
final Feature feature;
/**
* Create a resource based on a BundleDescriptor.
* @param bd The BundleDescriptor to represent.
*/
public BundleResourceImpl(BundleDescriptor bd, Feature feat) {
artifact = bd.getArtifact();
bsn = bd.getBundleSymbolicName();
version = bd.getArtifact().getId().getOSGiVersion();
feature = feat;
Map<String, List<Capability>> caps = new HashMap<>();
for (Capability c : bd.getCapabilities()) {
List<Capability> l = caps.get(c.getNamespace());
if (l == null) {
l = new ArrayList<>();
caps.put(c.getNamespace(), l);
}
l.add(new CapabilityImpl(this, c));
}
// Add the identity capability
Map<String, Object> idattrs = new HashMap<>();
idattrs.put(IdentityNamespace.IDENTITY_NAMESPACE, bsn);
idattrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, IdentityNamespace.TYPE_BUNDLE);
idattrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
Capability idCap = new CapabilityImpl(this, IdentityNamespace.IDENTITY_NAMESPACE, null, idattrs);
caps.put(IdentityNamespace.IDENTITY_NAMESPACE, Collections.singletonList(idCap));
// Add the bundle capability
Map<String, Object> battrs = new HashMap<>();
battrs.put(BundleNamespace.BUNDLE_NAMESPACE, bsn);
battrs.put(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE, version);
Capability bundleCap = new CapabilityImpl(this, BundleNamespace.BUNDLE_NAMESPACE, null, battrs);
caps.put(BundleNamespace.BUNDLE_NAMESPACE, Collections.singletonList(bundleCap));
capabilities = Collections.unmodifiableMap(caps);
Map<String, List<Requirement>> reqs = new HashMap<>();
for (Requirement r : bd.getRequirements()) {
List<Requirement> l = reqs.get(r.getNamespace());
if (l == null) {
l = new ArrayList<>();
reqs.put(r.getNamespace(), l);
}
// Add the requirement and associate with this resource
l.add(new RequirementImpl(this, r));
}
// TODO What do we do with the execution environment?
reqs.remove(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
requirements = Collections.unmodifiableMap(reqs);
}
public BundleResourceImpl(String sn, String ver, Artifact art, Feature feat, Map<String, List<Capability>> caps, Map<String, List<Requirement>> reqs) {
this(sn, new Version(ver), art, feat, caps, reqs);
}
public BundleResourceImpl(String sn, Version ver, Artifact art, Feature feat, Map<String, List<Capability>> caps, Map<String, List<Requirement>> reqs) {
artifact = art;
bsn = sn;
version = ver;
feature = feat;
capabilities = caps;
requirements = reqs;
}
@Override
public Artifact getArtifact() {
return artifact;
}
@Override
public String getId() {
return bsn;
}
@Override
public Version getVersion() {
return version;
}
@Override
public List<Capability> getCapabilities(String namespace) {
return super.getCapabilities(namespace, capabilities);
}
@Override
public List<Requirement> getRequirements(String namespace) {
return super.getRequirements(namespace, requirements);
}
@Override
public Feature getFeature() {
return feature;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((artifact == null) ? 0 : artifact.hashCode());
result = prime * result + ((bsn == null) ? 0 : bsn.hashCode());
if (capabilities != null) {
// Don't delegate to the capabilities to compute their hashcode since that results in an endless loop
for (List<Capability> lc : capabilities.values()) {
for (Capability c : lc) {
result = prime * result + c.getNamespace().hashCode();
result = prime * result + c.getAttributes().hashCode();
result = prime * result + c.getDirectives().hashCode();
}
}
}
if (requirements != null) {
// Don't delegate to the requirements to compute their hashcode since that results in an endless loop
for (List<Requirement> lr : requirements.values()) {
for (Requirement r : lr) {
result = prime * result + r.getNamespace().hashCode();
result = prime * result + r.getAttributes().hashCode();
result = prime * result + r.getDirectives().hashCode();
}
}
}
result = prime * result + ((feature == null) ? 0 : feature.hashCode());
result = prime * result + ((version == null) ? 0 : version.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BundleResourceImpl other = (BundleResourceImpl) obj;
if (artifact == null) {
if (other.artifact != null)
return false;
} else if (!artifact.equals(other.artifact))
return false;
if (bsn == null) {
if (other.bsn != null)
return false;
} else if (!bsn.equals(other.bsn))
return false;
if (capabilities == null) {
if (other.capabilities != null)
return false;
} else if (!capabilities.equals(other.capabilities))
return false;
if (feature == null) {
if (other.feature != null)
return false;
} else if (!feature.equals(other.feature))
return false;
if (requirements == null) {
if (other.requirements != null)
return false;
} else if (!requirements.equals(other.requirements))
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
@Override
public String toString() {
return "BundleResourceImpl [bsn=" + bsn + ", version=" + version + "]";
}
}