package org.argeo.init.osgi;
import static org.argeo.init.osgi.OsgiBootUtils.debug;
import static org.argeo.init.osgi.OsgiBootUtils.warn;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.argeo.init.a2.A2Source;
import org.argeo.init.a2.ProvisioningManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.Version;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.FrameworkWiring;
/**
* Basic provisioning of an OSGi runtime via file path patterns and system
* properties. The approach is to generate list of URLs based on various
* methods, configured via properties.
*/
public class OsgiBoot implements OsgiBootConstants {
public final static String PROP_ARGEO_OSGI_START = "argeo.osgi.start";
public final static String PROP_ARGEO_OSGI_MAX_START_LEVEL = "argeo.osgi.maxStartLevel";
public final static String PROP_ARGEO_OSGI_SOURCES = "argeo.osgi.sources";
@Deprecated
final static String PROP_ARGEO_OSGI_BUNDLES = "argeo.osgi.bundles";
final static String PROP_ARGEO_OSGI_BASE_URL = "argeo.osgi.baseUrl";
final static String PROP_ARGEO_OSGI_LOCAL_CACHE = "argeo.osgi.localCache";
final static String PROP_ARGEO_OSGI_DISTRIBUTION_URL = "argeo.osgi.distributionUrl";
// booleans
@Deprecated
final static String PROP_ARGEO_OSGI_BOOT_DEBUG = "argeo.osgi.boot.debug";
final static String PROP_ARGEO_OSGI_BOOT_SYSTEM_PROPERTIES_FILE = "argeo.osgi.boot.systemPropertiesFile";
final static String PROP_ARGEO_OSGI_BOOT_APPCLASS = "argeo.osgi.boot.appclass";
final static String PROP_ARGEO_OSGI_BOOT_APPARGS = "argeo.osgi.boot.appargs";
@Deprecated
public final static String DEFAULT_BASE_URL = "reference:file:";
final static String DEFAULT_MAX_START_LEVEL = "32";
// OSGi standard properties
final static String PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL = "osgi.bundles.defaultStartLevel";
final static String PROP_OSGI_STARTLEVEL = "osgi.startLevel";
public final static String PROP_OSGI_INSTANCE_AREA = "osgi.instance.area";
public final static String PROP_OSGI_CONFIGURATION_AREA = "osgi.configuration.area";
public final static String PROP_OSGI_SHARED_CONFIGURATION_AREA = "osgi.sharedConfiguration.area";
public final static String PROP_OSGI_USE_SYSTEM_PROPERTIES = "osgi.framework.useSystemProperties";
// Symbolic names
final static String SYMBOLIC_NAME_OSGI_BOOT = "org.argeo.init";
final static String SYMBOLIC_NAME_EQUINOX = "org.eclipse.osgi";
private final BundleContext bundleContext;
private final String localCache;
private final ProvisioningManager provisioningManager;
/*
* INITIALISATION
*/
/** Constructor */
public OsgiBoot(BundleContext bundleContext) {
this.bundleContext = bundleContext;
Path homePath = Paths.get(System.getProperty("user.home")).toAbsolutePath();
String homeUri = homePath.toUri().toString();
localCache = getProperty(PROP_ARGEO_OSGI_LOCAL_CACHE, homeUri + ".m2/repository/");
provisioningManager = new ProvisioningManager(bundleContext);
String sources = getProperty(PROP_ARGEO_OSGI_SOURCES);
if (sources == null) {
provisioningManager.registerDefaultSource();
} else {
// OsgiBootUtils.debug("Found sources " + sources);
for (String source : sources.split(",")) {
int qmIndex = source.lastIndexOf('?');
String queryPart = "";
if (qmIndex >= 0) {
queryPart = source.substring(qmIndex);
source = source.substring(0, qmIndex);
}
if (source.trim().equals(A2Source.DEFAULT_A2_URI)) {
if (Files.exists(homePath))
provisioningManager.registerSource(
A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart);
} else {
provisioningManager.registerSource(source + queryPart);
}
}
}
}
ProvisioningManager getProvisioningManager() {
return provisioningManager;
}
/*
* HIGH-LEVEL METHODS
*/
/**
* Bootstraps the OSGi runtime using these properties, which MUST be consistent
* with {@link BundleContext#getProperty(String)}. If these properties are
* null
, system properties are used instead.
*/
public void bootstrap(Map properties) {
try {
long begin = System.currentTimeMillis();
// check properties
// if (properties != null) {
// for (String property : properties.keySet()) {
// String value = properties.get(property);
// String bcValue = bundleContext.getProperty(property);
// if (PROP_OSGI_CONFIGURATION_AREA.equals(property) || PROP_OSGI_INSTANCE_AREA.equals(property)) {
// try {
// if (value.startsWith("/"))
// value = "file://" + value;
// URL uri = new URL(value);
// URL bcUri = new URL(bcValue);
// if (!uri.equals(bcUri))
// throw new IllegalArgumentException("Property " + property + "=" + uri
// + " is inconsistent with bundle context : " + bcUri);
// } catch (MalformedURLException e) {
// throw new IllegalArgumentException("Malformed property " + property, e);
// }
//
// } else {
// if (!value.equals(bcValue))
// throw new IllegalArgumentException("Property " + property + "=" + value
// + " is inconsistent with bundle context : " + bcValue);
// }
// }
// } else {
// String useSystemProperties = bundleContext.getProperty(PROP_OSGI_USE_SYSTEM_PROPERTIES);
// if (useSystemProperties == null || !useSystemProperties.equals("true")) {
// OsgiBootUtils.warn("No properties passed but " + PROP_OSGI_USE_SYSTEM_PROPERTIES + " is not set.");
// }
// }
// notify start
String osgiInstancePath = getProperty(PROP_OSGI_INSTANCE_AREA);
String osgiConfigurationPath = getProperty(PROP_OSGI_CONFIGURATION_AREA);
String osgiSharedConfigurationPath = getProperty(PROP_OSGI_CONFIGURATION_AREA);
OsgiBootUtils.info("OSGi bootstrap starting" //
+ (osgiInstancePath != null ? " data: " + osgiInstancePath + "" : "") //
+ (osgiConfigurationPath != null ? " state: " + osgiConfigurationPath + "" : "") //
+ (osgiSharedConfigurationPath != null ? " config: " + osgiSharedConfigurationPath + "" : "") //
);
// legacy install bundles
installUrls(getBundlesUrls());
installUrls(getDistributionUrls());
// A2 install bundles
provisioningManager.install(null);
// start bundles
// if (properties != null && !Boolean.parseBoolean(properties.get(PROP_OSGI_USE_SYSTEM_PROPERTIES)))
startBundles(properties);
// else
// startBundles();
// complete
long duration = System.currentTimeMillis() - begin;
OsgiBootUtils.info("OSGi bootstrap completed in " + Math.round(((double) duration) / 1000) + "s ("
+ duration + "ms), " + bundleContext.getBundles().length + " bundles");
} catch (RuntimeException e) {
OsgiBootUtils.error("OSGi bootstrap FAILED", e);
throw e;
}
// diagnostics
if (OsgiBootUtils.isDebug()) {
OsgiBootDiagnostics diagnostics = new OsgiBootDiagnostics(bundleContext);
diagnostics.checkUnresolved();
Map> duplicatePackages = diagnostics.findPackagesExportedTwice();
if (duplicatePackages.size() > 0) {
OsgiBootUtils.info("Packages exported twice:");
Iterator it = duplicatePackages.keySet().iterator();
while (it.hasNext()) {
String pkgName = it.next();
OsgiBootUtils.info(pkgName);
Set bdles = duplicatePackages.get(pkgName);
Iterator bdlesIt = bdles.iterator();
while (bdlesIt.hasNext())
OsgiBootUtils.info(" " + bdlesIt.next());
}
}
}
System.out.println();
}
/**
* Calls {@link #bootstrap(Map)} with null
.
*
* @see #bootstrap(Map)
*/
@Deprecated
public void bootstrap() {
bootstrap(null);
}
public void update() {
provisioningManager.update();
}
/*
* INSTALLATION
*/
/** Install a single url. Convenience method. */
public Bundle installUrl(String url) {
List urls = new ArrayList();
urls.add(url);
installUrls(urls);
return (Bundle) getBundlesByLocation().get(url);
}
/** Install the bundles at this URL list. */
public void installUrls(List urls) {
Map installedBundles = getBundlesByLocation();
for (int i = 0; i < urls.size(); i++) {
String url = (String) urls.get(i);
installUrl(url, installedBundles);
}
refreshFramework();
}
/** Actually install the provided URL */
protected void installUrl(String url, Map installedBundles) {
try {
if (installedBundles.containsKey(url)) {
Bundle bundle = (Bundle) installedBundles.get(url);
if (OsgiBootUtils.isDebug())
debug("Bundle " + bundle.getSymbolicName() + " already installed from " + url);
} else if (url.contains("/" + SYMBOLIC_NAME_EQUINOX + "/")
|| url.contains("/" + SYMBOLIC_NAME_OSGI_BOOT + "/")) {
if (OsgiBootUtils.isDebug())
warn("Skip " + url);
return;
} else {
Bundle bundle = bundleContext.installBundle(url);
if (url.startsWith("http"))
OsgiBootUtils
.info("Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url);
else if (OsgiBootUtils.isDebug())
OsgiBootUtils.debug(
"Installed " + bundle.getSymbolicName() + "-" + bundle.getVersion() + " from " + url);
assert bundle.getSymbolicName() != null;
// uninstall previous versions
bundles: for (Bundle b : bundleContext.getBundles()) {
if (b.getSymbolicName() == null)
continue bundles;
if (bundle.getSymbolicName().equals(b.getSymbolicName())) {
Version bundleV = bundle.getVersion();
Version bV = b.getVersion();
if (bV == null)
continue bundles;
if (bundleV.getMajor() == bV.getMajor() && bundleV.getMinor() == bV.getMinor()) {
if (bundleV.getMicro() > bV.getMicro()) {
// uninstall older bundles
b.uninstall();
OsgiBootUtils.debug("Uninstalled " + b);
} else if (bundleV.getMicro() < bV.getMicro()) {
// uninstall just installed bundle if newer
bundle.uninstall();
OsgiBootUtils.debug("Uninstalled " + bundle);
break bundles;
} else {
// uninstall any other with same major/minor
if (!bundleV.getQualifier().equals(bV.getQualifier())) {
b.uninstall();
OsgiBootUtils.debug("Uninstalled " + b);
}
}
}
}
}
}
} catch (BundleException e) {
final String ALREADY_INSTALLED = "is already installed";
String message = e.getMessage();
if ((message.contains("Bundle \"" + SYMBOLIC_NAME_OSGI_BOOT + "\"")
|| message.contains("Bundle \"" + SYMBOLIC_NAME_EQUINOX + "\""))
&& message.contains(ALREADY_INSTALLED)) {
// silent, in order to avoid warnings: we know that both
// have already been installed...
} else {
if (message.contains(ALREADY_INSTALLED)) {
if (OsgiBootUtils.isDebug())
OsgiBootUtils.warn("Duplicate install from " + url + ": " + message);
} else
OsgiBootUtils.warn("Could not install bundle from " + url + ": " + message);
}
if (OsgiBootUtils.isDebug() && !message.contains(ALREADY_INSTALLED))
e.printStackTrace();
}
}
/*
* START
*/
// /**
// * Start bundles based on system properties.
// *
// * @see OsgiBoot#doStartBundles(Map)
// */
// public void startBundles() {
// Properties properties = System.getProperties();
// startBundles(properties);
// }
/**
* Start bundles based on these properties.
*
* @see OsgiBoot#doStartBundles(Map)
*/
public void startBundles(Map properties) {
Map map = new TreeMap<>();
// first use properties
if (properties != null) {
for (String key : properties.keySet()) {
String property = key;
if (property.startsWith(PROP_ARGEO_OSGI_START)) {
map.put(property, properties.get(property));
}
}
}
// then try all start level until a maximum
int maxStartLevel = Integer.parseInt(getProperty(PROP_ARGEO_OSGI_MAX_START_LEVEL, DEFAULT_MAX_START_LEVEL));
for (int i = 1; i <= maxStartLevel; i++) {
String key = PROP_ARGEO_OSGI_START + "." + i;
String value = getProperty(key);
if (value != null)
map.put(key, value);
}
// finally, override with system properties
for (Object key : System.getProperties().keySet()) {
if (key.toString().startsWith(PROP_ARGEO_OSGI_START)) {
map.put(key.toString(), System.getProperty(key.toString()));
}
}
// start
doStartBundles(map);
}
@Deprecated
public void startBundles(Properties properties) {
Map map = new TreeMap<>();
// first use properties
if (properties != null) {
for (Object key : properties.keySet()) {
String property = key.toString();
if (property.startsWith(PROP_ARGEO_OSGI_START)) {
map.put(property, properties.get(property).toString());
}
}
}
startBundles(map);
}
/** Start bundle based on keys starting with {@link #PROP_ARGEO_OSGI_START}. */
protected void doStartBundles(Map properties) {
FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
// default and active start levels from System properties
Integer defaultStartLevel = Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"));
Integer activeStartLevel = Integer.parseInt(getProperty(PROP_OSGI_STARTLEVEL, "6"));
SortedMap> startLevels = new TreeMap>();
computeStartLevels(startLevels, properties, defaultStartLevel);
// inverts the map for the time being, TODO optimise
Map bundleStartLevels = new HashMap<>();
for (Integer level : startLevels.keySet()) {
for (String bsn : startLevels.get(level))
bundleStartLevels.put(bsn, level);
}
for (Bundle bundle : bundleContext.getBundles()) {
String bsn = bundle.getSymbolicName();
if (bundleStartLevels.containsKey(bsn)) {
BundleStartLevel bundleStartLevel = bundle.adapt(BundleStartLevel.class);
Integer level = bundleStartLevels.get(bsn);
if (bundleStartLevel.getStartLevel() != level || !bundleStartLevel.isPersistentlyStarted()) {
bundleStartLevel.setStartLevel(level);
try {
bundle.start();
} catch (BundleException e) {
OsgiBootUtils.error("Cannot mark " + bsn + " as started", e);
}
if (OsgiBootUtils.isDebug())
OsgiBootUtils.debug(bsn + " starts at level " + level);
}
}
}
frameworkStartLevel.setStartLevel(activeStartLevel, (FrameworkEvent event) -> {
if (OsgiBootUtils.isDebug())
OsgiBootUtils.debug("Framework event: " + event);
int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
int startLevel = frameworkStartLevel.getStartLevel();
OsgiBootUtils.debug("Framework start level: " + startLevel + " (initial: " + initialStartLevel + ")");
});
}
private static void computeStartLevels(SortedMap> startLevels, Map properties,
Integer defaultStartLevel) {
// default (and previously, only behaviour)
appendToStartLevels(startLevels, defaultStartLevel, properties.getOrDefault(PROP_ARGEO_OSGI_START, ""));
// list argeo.osgi.start.* system properties
Iterator keys = properties.keySet().iterator();
final String prefix = PROP_ARGEO_OSGI_START + ".";
while (keys.hasNext()) {
String key = keys.next();
if (key.startsWith(prefix)) {
Integer startLevel;
String suffix = key.substring(prefix.length());
String[] tokens = suffix.split("\\.");
if (tokens.length > 0 && !tokens[0].trim().equals(""))
try {
// first token is start level
startLevel = Integer.parseInt(tokens[0]);
} catch (NumberFormatException e) {
startLevel = defaultStartLevel;
}
else
startLevel = defaultStartLevel;
// append bundle names
String bundleNames = properties.get(key);
appendToStartLevels(startLevels, startLevel, bundleNames);
}
}
}
/** Append a comma-separated list of bundles to the start levels. */
private static void appendToStartLevels(SortedMap> startLevels, Integer startLevel,
String str) {
if (str == null || str.trim().equals(""))
return;
if (!startLevels.containsKey(startLevel))
startLevels.put(startLevel, new ArrayList());
String[] bundleNames = str.split(",");
for (int i = 0; i < bundleNames.length; i++) {
if (bundleNames[i] != null && !bundleNames[i].trim().equals(""))
(startLevels.get(startLevel)).add(bundleNames[i]);
}
}
// /**
// * Start the provided list of bundles
// *
// * @return whether all bundles are now in active state
// * @deprecated
// */
// @Deprecated
// public boolean startBundles(List bundlesToStart) {
// if (bundlesToStart.size() == 0)
// return true;
//
// // used to monitor ACTIVE states
// List startedBundles = new ArrayList();
// // used to log the bundles not found
// List notFoundBundles = new ArrayList(bundlesToStart);
//
// Bundle[] bundles = bundleContext.getBundles();
// long startBegin = System.currentTimeMillis();
// for (int i = 0; i < bundles.length; i++) {
// Bundle bundle = bundles[i];
// String symbolicName = bundle.getSymbolicName();
// if (bundlesToStart.contains(symbolicName))
// try {
// try {
// bundle.start();
// if (OsgiBootUtils.isDebug())
// debug("Bundle " + symbolicName + " started");
// } catch (Exception e) {
// OsgiBootUtils.warn("Start of bundle " + symbolicName + " failed because of " + e
// + ", maybe bundle is not yet resolved," + " waiting and trying again.");
// waitForBundleResolvedOrActive(startBegin, bundle);
// bundle.start();
// startedBundles.add(bundle);
// }
// notFoundBundles.remove(symbolicName);
// } catch (Exception e) {
// OsgiBootUtils.warn("Bundle " + symbolicName + " cannot be started: " + e.getMessage());
// if (OsgiBootUtils.isDebug())
// e.printStackTrace();
// // was found even if start failed
// notFoundBundles.remove(symbolicName);
// }
// }
//
// for (int i = 0; i < notFoundBundles.size(); i++)
// OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) + "' not started because it was not found.");
//
// // monitors that all bundles are started
// long beginMonitor = System.currentTimeMillis();
// boolean allStarted = !(startedBundles.size() > 0);
// List notStarted = new ArrayList();
// while (!allStarted && (System.currentTimeMillis() - beginMonitor) < defaultTimeout) {
// notStarted = new ArrayList();
// allStarted = true;
// for (int i = 0; i < startedBundles.size(); i++) {
// Bundle bundle = (Bundle) startedBundles.get(i);
// // TODO check behaviour of lazs bundles
// if (bundle.getState() != Bundle.ACTIVE) {
// allStarted = false;
// notStarted.add(bundle.getSymbolicName());
// }
// }
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// // silent
// }
// }
// long duration = System.currentTimeMillis() - beginMonitor;
//
// if (!allStarted)
// for (int i = 0; i < notStarted.size(); i++)
// OsgiBootUtils.warn("Bundle '" + notStarted.get(i) + "' not ACTIVE after " + (duration / 1000) + "s");
//
// return allStarted;
// }
// /** Waits for a bundle to become active or resolved */
// @Deprecated
// private void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) throws Exception {
// int originalState = bundle.getState();
// if ((originalState == Bundle.RESOLVED) || (originalState == Bundle.ACTIVE))
// return;
//
// String originalStateStr = OsgiBootUtils.stateAsString(originalState);
//
// int currentState = bundle.getState();
// while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) {
// long now = System.currentTimeMillis();
// if ((now - startBegin) > defaultTimeout * 10)
// throw new Exception("Bundle " + bundle.getSymbolicName() + " was not RESOLVED or ACTIVE after "
// + (now - startBegin) + "ms (originalState=" + originalStateStr + ", currentState="
// + OsgiBootUtils.stateAsString(currentState) + ")");
//
// try {
// Thread.sleep(100l);
// } catch (InterruptedException e) {
// // silent
// }
// currentState = bundle.getState();
// }
// }
/*
* BUNDLE PATTERNS INSTALLATION
*/
/**
* Computes a list of URLs based on Ant-like include/exclude patterns defined by
* ${argeo.osgi.bundles} with the following format:
* /base/directory;in=*.jar;in=**;ex=org.eclipse.osgi_*;jar
* WARNING: /base/directory;in=*.jar,\
at the end of a file,
* without a new line causes a '.' to be appended with unexpected side effects.
*/
public List getBundlesUrls() {
String bundlePatterns = getProperty(PROP_ARGEO_OSGI_BUNDLES);
return getBundlesUrls(bundlePatterns);
}
/**
* Compute a list of URLs to install based on the provided patterns, with
* default base url
*/
public List getBundlesUrls(String bundlePatterns) {
String baseUrl = getProperty(PROP_ARGEO_OSGI_BASE_URL, DEFAULT_BASE_URL);
return getBundlesUrls(baseUrl, bundlePatterns);
}
/** Implements the path matching logic */
@Deprecated
public List getBundlesUrls(String baseUrl, String bundlePatterns) {
List urls = new ArrayList();
if (bundlePatterns == null)
return urls;
// bundlePatterns = SystemPropertyUtils.resolvePlaceholders(bundlePatterns);
if (OsgiBootUtils.isDebug())
debug(PROP_ARGEO_OSGI_BUNDLES + "=" + bundlePatterns);
StringTokenizer st = new StringTokenizer(bundlePatterns, ",");
List bundlesSets = new ArrayList();
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (new File(token).exists()) {
String url = locationToUrl(baseUrl, token);
urls.add(url);
} else
bundlesSets.add(new BundlesSet(token));
}
// find included
List included = new ArrayList();
// PathMatcher matcher = new AntPathMatcher();
for (int i = 0; i < bundlesSets.size(); i++) {
BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i);
for (int j = 0; j < bundlesSet.getIncludes().size(); j++) {
String pattern = (String) bundlesSet.getIncludes().get(j);
match(included, bundlesSet.getDir(), null, pattern);
}
}
// find excluded
List excluded = new ArrayList();
for (int i = 0; i < bundlesSets.size(); i++) {
BundlesSet bundlesSet = (BundlesSet) bundlesSets.get(i);
for (int j = 0; j < bundlesSet.getExcludes().size(); j++) {
String pattern = (String) bundlesSet.getExcludes().get(j);
match(excluded, bundlesSet.getDir(), null, pattern);
}
}
// construct list
for (int i = 0; i < included.size(); i++) {
String fullPath = (String) included.get(i);
if (!excluded.contains(fullPath))
urls.add(locationToUrl(baseUrl, fullPath));
}
return urls;
}
/*
* DISTRIBUTION JAR INSTALLATION
*/
public List getDistributionUrls() {
String distributionUrl = getProperty(PROP_ARGEO_OSGI_DISTRIBUTION_URL);
String baseUrl = getProperty(PROP_ARGEO_OSGI_BASE_URL);
return getDistributionUrls(distributionUrl, baseUrl);
}
public List getDistributionUrls(String distributionUrl, String baseUrl) {
List urls = new ArrayList();
if (distributionUrl == null)
return urls;
DistributionBundle distributionBundle;
if (distributionUrl.startsWith("http") || distributionUrl.startsWith("file")) {
distributionBundle = new DistributionBundle(distributionUrl);
if (baseUrl != null)
distributionBundle.setBaseUrl(baseUrl);
} else {
// relative url
if (baseUrl == null) {
baseUrl = localCache;
}
if (distributionUrl.contains(":")) {
// TODO make it safer
String[] parts = distributionUrl.trim().split(":");
String[] categoryParts = parts[0].split("\\.");
String artifactId = parts[1];
String version = parts[2];
StringBuilder sb = new StringBuilder();
for (String categoryPart : categoryParts) {
sb.append(categoryPart).append('/');
}
sb.append(artifactId).append('/');
sb.append(version).append('/');
sb.append(artifactId).append('-').append(version).append(".jar");
distributionUrl = sb.toString();
}
distributionBundle = new DistributionBundle(baseUrl, distributionUrl, localCache);
}
// if (baseUrl != null && !(distributionUrl.startsWith("http") ||
// distributionUrl.startsWith("file"))) {
// // relative url
// distributionBundle = new DistributionBundle(baseUrl, distributionUrl,
// localCache);
// } else {
// distributionBundle = new DistributionBundle(distributionUrl);
// if (baseUrl != null)
// distributionBundle.setBaseUrl(baseUrl);
// }
distributionBundle.processUrl();
return distributionBundle.listUrls();
}
/*
* HIGH LEVEL UTILITIES
*/
/** Actually performs the matching logic. */
protected void match(List matched, String base, String currentPath, String pattern) {
if (currentPath == null) {
// Init
File baseDir = new File(base.replace('/', File.separatorChar));
File[] files = baseDir.listFiles();
if (files == null) {
if (OsgiBootUtils.isDebug())
OsgiBootUtils.warn("Base dir " + baseDir + " has no children, exists=" + baseDir.exists()
+ ", isDirectory=" + baseDir.isDirectory());
return;
}
for (int i = 0; i < files.length; i++)
match(matched, base, files[i].getName(), pattern);
} else {
PathMatcher matcher = FileSystems.getDefault().getPathMatcher(pattern);
String fullPath = base + '/' + currentPath;
if (matched.contains(fullPath))
return;// don't try deeper if already matched
boolean ok = matcher.matches(Paths.get(currentPath));
// if (debug)
// debug(currentPath + " " + (ok ? "" : " not ")
// + " matched with " + pattern);
if (ok) {
matched.add(fullPath);
return;
} else {
String newFullPath = relativeToFullPath(base, currentPath);
File newFile = new File(newFullPath);
File[] files = newFile.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
String newCurrentPath = currentPath + '/' + files[i].getName();
if (files[i].isDirectory()) {
// if (matcher.matchStart(pattern, newCurrentPath)) {
// FIXME recurse only if start matches ?
match(matched, base, newCurrentPath, pattern);
// } else {
// if (OsgiBootUtils.isDebug())
// debug(newCurrentPath + " does not start match with " + pattern);
//
// }
} else {
boolean nonDirectoryOk = matcher.matches(Paths.get(newCurrentPath));
if (OsgiBootUtils.isDebug())
debug(currentPath + " " + (ok ? "" : " not ") + " matched with " + pattern);
if (nonDirectoryOk)
matched.add(relativeToFullPath(base, newCurrentPath));
}
}
}
}
}
}
/*
* LOW LEVEL UTILITIES
*/
/**
* The bundles already installed. Key is location (String) , value is a
* {@link Bundle}
*/
public Map getBundlesByLocation() {
Map installedBundles = new HashMap();
Bundle[] bundles = bundleContext.getBundles();
for (int i = 0; i < bundles.length; i++) {
installedBundles.put(bundles[i].getLocation(), bundles[i]);
}
return installedBundles;
}
/**
* The bundles already installed. Key is symbolic name (String) , value is a
* {@link Bundle}
*/
public Map getBundlesBySymbolicName() {
Map namedBundles = new HashMap();
Bundle[] bundles = bundleContext.getBundles();
for (int i = 0; i < bundles.length; i++) {
namedBundles.put(bundles[i].getSymbolicName(), bundles[i]);
}
return namedBundles;
}
/** Creates an URL from a location */
protected String locationToUrl(String baseUrl, String location) {
return baseUrl + location;
}
/** Transforms a relative path in a full system path. */
protected String relativeToFullPath(String basePath, String relativePath) {
return (basePath + '/' + relativePath).replace('/', File.separatorChar);
}
private void refreshFramework() {
Bundle systemBundle = bundleContext.getBundle(0);
FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
frameworkWiring.refreshBundles(null);
}
/**
* Gets a property value
*
* @return null when defaultValue is ""
*/
public String getProperty(String name, String defaultValue) {
String value = bundleContext.getProperty(name);
if (value == null)
return defaultValue; // may be null
else
return value;
}
public String getProperty(String name) {
return getProperty(name, null);
}
/*
* BEAN METHODS
*/
// public boolean getDebug() {
// return OsgiBootUtils.debug;
// }
// public void setDebug(boolean debug) {
// this.debug = debug;
// }
public BundleContext getBundleContext() {
return bundleContext;
}
// public String getLocalCache() {
// return localCache;
// }
// public void setDefaultTimeout(long defaultTimeout) {
// this.defaultTimeout = defaultTimeout;
// }
// public boolean isExcludeSvn() {
// return excludeSvn;
// }
//
// public void setExcludeSvn(boolean excludeSvn) {
// this.excludeSvn = excludeSvn;
// }
/*
* INTERNAL CLASSES
*/
}