blob: 6037525c92ac3b3f4a47f43ceef7d74e25192f82 [file] [log] [blame]
/*
* Licensed 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.aries.subsystem.core.archive;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.apache.aries.subsystem.core.internal.BasicSubsystem;
import org.apache.aries.util.manifest.ManifestProcessor;
import org.osgi.framework.Constants;
import org.osgi.resource.Resource;
import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.SubsystemConstants;
public class DeploymentManifest {
public static class Builder {
private Map<String, Header<?>> headers = new HashMap<String, Header<?>>();
public DeploymentManifest build() {
return new DeploymentManifest(headers);
}
public Builder autostart(boolean value) {
header(new GenericHeader(ARIESSUBSYSTEM_AUTOSTART, Boolean.toString(value)));
return this;
}
// public Builder content(Resource resource) {
// return content(resource, true);
// }
public Builder content(Resource resource, boolean referenced) {
DeployedContentHeader header = (DeployedContentHeader)headers.get(DeploymentManifest.DEPLOYED_CONTENT);
if (header == null) {
DeployedContentHeader.Clause clause = new DeployedContentHeader.Clause(resource, referenced);
header(new DeployedContentHeader(Collections.singleton(clause)));
return this;
}
DeployedContentHeader.Clause clause = header.getClause(resource);
if (clause == null) {
clause = new DeployedContentHeader.Clause(resource, referenced);
List<DeployedContentHeader.Clause> clauses = new ArrayList<DeployedContentHeader.Clause>(header.getClauses().size() + 1);
clauses.addAll(header.getClauses());
clauses.add(clause);
header(new DeployedContentHeader(clauses));
return this;
}
Collection<DeployedContentHeader.Clause> clauses = new ArrayList<DeployedContentHeader.Clause>(header.getClauses());
for (Iterator<DeployedContentHeader.Clause> i = clauses.iterator(); i.hasNext();)
if (clause.equals(i.next())) {
i.remove();
break;
}
clauses.add(new DeployedContentHeader.Clause(resource, referenced));
header(new DeployedContentHeader(clauses));
return this;
}
public Builder header(Header<?> value) {
if (value != null)
headers.put(value.getName(), value);
return this;
}
public Builder id(long value) {
header(new GenericHeader(ARIESSUBSYSTEM_ID, Long.toString(value)));
return this;
}
public Builder lastId(long value) {
header(new GenericHeader(ARIESSUBSYSTEM_LASTID, Long.toString(value)));
return this;
}
public Builder location(String value) {
if (value != null)
header(new GenericHeader(ARIESSUBSYSTEM_LOCATION, value));
return this;
}
public Builder manifest(DeploymentManifest value) {
if (value != null)
for (Entry<String, Header<?>> entry : value.getHeaders().entrySet())
header(entry.getValue());
return this;
}
public Builder manifest(SubsystemManifest value) {
if (value != null)
for (Entry<String, Header<?>> entry : value.getHeaders().entrySet())
header(entry.getValue());
return this;
}
public Builder parent(BasicSubsystem value, boolean referenceCount) {
AriesSubsystemParentsHeader.Clause clause = new AriesSubsystemParentsHeader.Clause(value, referenceCount);
AriesSubsystemParentsHeader header = (AriesSubsystemParentsHeader)headers.get(ARIESSUBSYSTEM_PARENTS);
if (header == null)
header(new AriesSubsystemParentsHeader(Collections.singleton(clause)));
else {
Collection<AriesSubsystemParentsHeader.Clause> clauses = new ArrayList<AriesSubsystemParentsHeader.Clause>(header.getClauses().size() + 1);
clauses.addAll(header.getClauses());
clauses.add(clause);
header(new AriesSubsystemParentsHeader(clauses));
}
return this;
}
public Builder region(String value) {
if (value != null)
header(new GenericHeader(ARIESSUBSYSTEM_REGION, value));
return this;
}
public Builder region(org.eclipse.equinox.region.Region value) {
if (value != null)
region(value.getName());
return this;
}
public Builder state(Subsystem.State value) {
if (value != null)
header(new GenericHeader(ARIESSUBSYSTEM_STATE, value.toString()));
return this;
}
}
public static final String DEPLOYED_CONTENT = SubsystemConstants.DEPLOYED_CONTENT;
public static final String DEPLOYMENT_MANIFESTVERSION = SubsystemConstants.DEPLOYMENT_MANIFESTVERSION;
public static final String EXPORT_PACKAGE = Constants.EXPORT_PACKAGE;
public static final String IMPORT_PACKAGE = Constants.IMPORT_PACKAGE;
public static final String PROVIDE_CAPABILITY = Constants.PROVIDE_CAPABILITY;
public static final String PROVISION_RESOURCE = SubsystemConstants.PROVISION_RESOURCE;
public static final String REQUIRE_BUNDLE = Constants.REQUIRE_BUNDLE;
public static final String REQUIRE_CAPABILITY = Constants.REQUIRE_CAPABILITY;
public static final String SUBSYSTEM_EXPORTSERVICE = SubsystemConstants.SUBSYSTEM_EXPORTSERVICE;
public static final String SUBSYSTEM_IMPORTSERVICE = SubsystemConstants.SUBSYSTEM_IMPORTSERVICE;
public static final String SUBSYSTEM_SYMBOLICNAME = SubsystemConstants.SUBSYSTEM_SYMBOLICNAME;
public static final String SUBSYSTEM_VERSION = SubsystemConstants.SUBSYSTEM_VERSION;
public static final String ARIESSUBSYSTEM_AUTOSTART = "AriesSubsystem-Autostart";
public static final String ARIESSUBSYSTEM_ID = "AriesSubsystem-Id";
public static final String ARIESSUBSYSTEM_LASTID = "AriesSubsystem-LastId";
public static final String ARIESSUBSYSTEM_LOCATION = "AriesSubsystem-Location";
public static final String ARIESSUBSYSTEM_PARENTS = "AriesSubsystem-Parents";
public static final String ARIESSUBSYSTEM_REGION = "AriesSubsystem-Region";
public static final String ARIESSUBSYSTEM_STATE = "AriesSubsystem-State";
private final Map<String, Header<?>> headers;
public DeploymentManifest(java.util.jar.Manifest manifest) {
headers = new HashMap<String, Header<?>>();
for (Entry<Object, Object> entry : manifest.getMainAttributes().entrySet()) {
String key = String.valueOf(entry.getKey());
if (key.equals(SubsystemManifest.SUBSYSTEM_SYMBOLICNAME))
continue;
headers.put(key, HeaderFactory.createHeader(key, String.valueOf(entry.getValue())));
}
}
public DeploymentManifest(File file) throws IOException {
this(new FileInputStream(file));
}
public DeploymentManifest(InputStream in) throws IOException {
Manifest manifest = ManifestProcessor.parseManifest(in);
Attributes attributes = manifest.getMainAttributes();
Map<String, Header<?>> headers = new HashMap<String, Header<?>>(attributes.size() + 4); // Plus the # of potentially derived headers.
for (Entry<Object, Object> entry : attributes.entrySet()) {
String key = String.valueOf(entry.getKey());
headers.put(key, HeaderFactory.createHeader(key, String.valueOf(entry.getValue())));
}
this.headers = Collections.unmodifiableMap(headers);
}
public DeploymentManifest(
DeploymentManifest deploymentManifest,
SubsystemManifest subsystemManifest,
boolean autostart,
long id,
long lastId,
String location,
boolean overwrite,
boolean acceptDependencies) throws ResolutionException, IOException, URISyntaxException {
Map<String, Header<?>> headers;
if (deploymentManifest == null // We're generating a new deployment manifest.
|| (deploymentManifest != null && overwrite)) { // A deployment manifest already exists but overwriting it with subsystem manifest content is desired.
headers = computeHeaders(subsystemManifest);
}
else {
headers = new HashMap<String, Header<?>>(deploymentManifest.getHeaders());
}
// TODO DEPLOYMENT_MANIFESTVERSION
headers.put(ARIESSUBSYSTEM_AUTOSTART, new GenericHeader(ARIESSUBSYSTEM_AUTOSTART, Boolean.toString(autostart)));
headers.put(ARIESSUBSYSTEM_ID, new GenericHeader(ARIESSUBSYSTEM_ID, Long.toString(id)));
headers.put(ARIESSUBSYSTEM_LOCATION, new GenericHeader(ARIESSUBSYSTEM_LOCATION, location));
headers.put(ARIESSUBSYSTEM_LASTID, new GenericHeader(ARIESSUBSYSTEM_LASTID, Long.toString(lastId)));
this.headers = Collections.unmodifiableMap(headers);
}
private DeploymentManifest(Map<String, Header<?>> headers) {
Map<String, Header<?>> map = new HashMap<String, Header<?>>(headers);
this.headers = Collections.unmodifiableMap(map);
}
public DeployedContentHeader getDeployedContentHeader() {
return (DeployedContentHeader)getHeaders().get(DEPLOYED_CONTENT);
}
public ExportPackageHeader getExportPackageHeader() {
return (ExportPackageHeader)getHeaders().get(EXPORT_PACKAGE);
}
public Map<String, Header<?>> getHeaders() {
return headers;
}
public AriesSubsystemParentsHeader getAriesSubsystemParentsHeader() {
return (AriesSubsystemParentsHeader)getHeaders().get(ARIESSUBSYSTEM_PARENTS);
}
public ImportPackageHeader getImportPackageHeader() {
return (ImportPackageHeader)getHeaders().get(IMPORT_PACKAGE);
}
public ProvideCapabilityHeader getProvideCapabilityHeader() {
return (ProvideCapabilityHeader)getHeaders().get(PROVIDE_CAPABILITY);
}
public ProvisionResourceHeader getProvisionResourceHeader() {
return (ProvisionResourceHeader)getHeaders().get(PROVISION_RESOURCE);
}
public RequireBundleHeader getRequireBundleHeader() {
return (RequireBundleHeader)getHeaders().get(REQUIRE_BUNDLE);
}
public RequireCapabilityHeader getRequireCapabilityHeader() {
return (RequireCapabilityHeader)getHeaders().get(REQUIRE_CAPABILITY);
}
public SubsystemExportServiceHeader getSubsystemExportServiceHeader() {
return (SubsystemExportServiceHeader)getHeaders().get(SUBSYSTEM_EXPORTSERVICE);
}
public SubsystemImportServiceHeader getSubsystemImportServiceHeader() {
return (SubsystemImportServiceHeader)getHeaders().get(SUBSYSTEM_IMPORTSERVICE);
}
public void write(OutputStream out) throws IOException {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
// The manifest won't write anything unless the following header is present.
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
for (Entry<String, Header<?>> entry : headers.entrySet()) {
attributes.putValue(entry.getKey(), entry.getValue().getValue());
}
manifest.write(out);
}
private Map<String, Header<?>> computeHeaders(SubsystemManifest manifest) {
return new HashMap<String, Header<?>>(manifest.getHeaders());
}
}