/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.osgi;
import java.io.File;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.utils.JarUtils;
import org.nuxeo.common.utils.StringUtils;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public final class BundleManifestReader {
private static final Log log = LogFactory.getLog(BundleManifestReader.class);
private static final Pattern PARAMS_PATTERN = Pattern.compile("\\s*([^:\\s]+)\\s*:=\\s*([^;\\s]+)\\s*;?");
public static final String COMPONENT_HEADER = "Nuxeo-Component";
public static final String ALLOW_HOST_OVERRIDE = "Nuxeo-AllowOverride";
public static final String WEB_MODULE = "Nuxeo-WebModule";
public static String[] CUSTOM_HEADERS = { COMPONENT_HEADER, WEB_MODULE, ALLOW_HOST_OVERRIDE };
static { // we can add dynamically new headers through system properties
String h = System.getProperty("org.nuxeo.manifest.headers");
if (h != null) {
CUSTOM_HEADERS = StringUtils.split(h, ',', true);
}
}
// Utility class
private BundleManifestReader() {
}
public static Dictionary<String, String> getHeadersFromJar(URL url) {
Manifest mf = JarUtils.getManifest(url);
if (mf != null) {
try {
return getHeaders(mf);
} catch (BundleException e) {
log.error(e, e);
}
}
// not an osgi bundle
return getDefaultHeaders(url.toExternalForm());
}
public static Dictionary<String, String> getHeadersFromFile(File file) {
Manifest mf = JarUtils.getManifest(file);
if (mf != null) {
try {
return getHeaders(mf);
} catch (BundleException e) {
log.error(e, e);
}
}
// not an osgi bundle
return getDefaultHeaders(file.getAbsolutePath());
}
public static Dictionary<String, String> getDefaultHeaders(String symbolicName) {
Dictionary<String, String> headers = new Hashtable<String, String>();
headers.put(Constants.BUNDLE_SYMBOLICNAME, symbolicName);
headers.put(Constants.BUNDLE_ACTIVATOR, NullActivator.class.getName());
return headers;
}
public static Dictionary<String, String> getHeaders(Manifest mf) throws BundleException {
Attributes attrs = mf.getMainAttributes();
String symbolicName = attrs.getValue(Constants.BUNDLE_SYMBOLICNAME);
if (symbolicName == null) {
throw new BundleException("Missing " + Constants.BUNDLE_SYMBOLICNAME);
}
Hashtable<String, String> headers = new Hashtable<String, String>();
parseSymbolicName(headers, symbolicName);
String val = attrs.getValue(Constants.BUNDLE_ACTIVATOR);
if (val != null) {
headers.put(Constants.BUNDLE_ACTIVATOR, val.trim());
}
val = attrs.getValue(Constants.BUNDLE_CLASSPATH);
if (val != null) {
headers.put(Constants.BUNDLE_CLASSPATH, val.trim());
}
val = attrs.getValue(Constants.BUNDLE_NAME);
if (val != null) {
headers.put(Constants.BUNDLE_NAME, val);
}
val = attrs.getValue(Constants.BUNDLE_VENDOR);
if (val != null) {
headers.put(Constants.BUNDLE_VENDOR, val);
}
val = attrs.getValue(Constants.BUNDLE_VERSION);
if (val != null) {
headers.put(Constants.BUNDLE_VERSION, val);
}
val = attrs.getValue(Constants.BUNDLE_DESCRIPTION);
if (val != null) {
headers.put(Constants.BUNDLE_DESCRIPTION, val);
}
val = attrs.getValue(Constants.BUNDLE_DOCURL);
if (val != null) {
headers.put(Constants.BUNDLE_DOCURL, val);
}
val = attrs.getValue(Constants.BUNDLE_COPYRIGHT);
if (val != null) {
headers.put(Constants.BUNDLE_COPYRIGHT, val);
}
val = attrs.getValue(Constants.BUNDLE_LOCALIZATION);
if (val != null) {
headers.put(Constants.BUNDLE_LOCALIZATION, val);
}
val = attrs.getValue(Constants.REQUIRE_BUNDLE);
if (val != null) {
headers.put(Constants.REQUIRE_BUNDLE, val);
}
val = attrs.getValue(Constants.FRAGMENT_HOST);
if (val != null) {
headers.put(Constants.FRAGMENT_HOST, val);
}
// Nuxeo headers
for (String key : CUSTOM_HEADERS) {
val = attrs.getValue(key);
if (val != null) {
headers.put(key, val);
}
}
return headers;
}
private static void parseSymbolicName(Dictionary<String, String> headers, String name) {
int p = name.indexOf(';');
if (p > 0) {
headers.put(Constants.BUNDLE_SYMBOLICNAME, name.substring(0, p).trim());
String tail = name.substring(p + 1);
Matcher m = PARAMS_PATTERN.matcher(tail);
while (m.find()) {
headers.put(m.group(1), m.group(2));
}
} else {
headers.put(Constants.BUNDLE_SYMBOLICNAME, name.trim());
}
}
public static String removePropertiesFromHeaderValue(String value) {
int p = value.indexOf(';');
if (p > 0) {
return value.substring(0, p).trim();
} else {
return value;
}
}
}