| /* |
| * 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.camel.blueprint; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.StringWriter; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Dictionary; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| import java.util.jar.JarInputStream; |
| |
| import org.apache.camel.impl.engine.DefaultClassResolver; |
| import org.apache.camel.spi.ClassResolver; |
| import org.apache.camel.support.ObjectHelper; |
| import org.apache.camel.util.FileUtil; |
| import org.apache.camel.util.IOHelper; |
| import org.apache.felix.connect.PojoServiceRegistryFactoryImpl; |
| import org.apache.felix.connect.felix.framework.util.Util; |
| import org.apache.felix.connect.launch.BundleDescriptor; |
| import org.apache.felix.connect.launch.ClasspathScanner; |
| import org.apache.felix.connect.launch.PojoServiceRegistry; |
| import org.apache.felix.connect.launch.PojoServiceRegistryFactory; |
| import org.ops4j.pax.tinybundles.core.TinyBundle; |
| import org.ops4j.pax.tinybundles.core.TinyBundles; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleActivator; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.BundleEvent; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.Filter; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.framework.SynchronousBundleListener; |
| import org.osgi.service.blueprint.container.BlueprintEvent; |
| import org.osgi.service.blueprint.container.BlueprintListener; |
| import org.osgi.service.cm.Configuration; |
| import org.osgi.service.cm.ConfigurationAdmin; |
| import org.osgi.util.tracker.ServiceTracker; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Helper for using Blueprint with Camel. |
| */ |
| public final class CamelBlueprintHelper { |
| |
| public static final long DEFAULT_TIMEOUT = 30000; |
| public static final String BUNDLE_FILTER = "(Bundle-SymbolicName=*)"; |
| public static final String BUNDLE_VERSION = "1.0.0"; |
| private static final Logger LOG = LoggerFactory.getLogger(CamelBlueprintHelper.class); |
| private static final ClassResolver RESOLVER = new DefaultClassResolver(); |
| |
| private CamelBlueprintHelper() { |
| } |
| |
| public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle) throws Exception { |
| return createBundleContext(name, descriptors, includeTestBundle, BUNDLE_FILTER, BUNDLE_VERSION); |
| } |
| |
| public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle, |
| String bundleFilter, String testBundleVersion) throws Exception { |
| return createBundleContext(name, descriptors, includeTestBundle, bundleFilter, testBundleVersion, null); |
| } |
| |
| public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle, |
| String bundleFilter, String testBundleVersion, String testBundleDirectives, |
| String[]... configAdminPidFiles) throws Exception { |
| return createBundleContext(name, descriptors, includeTestBundle, |
| bundleFilter, testBundleVersion, testBundleDirectives, |
| null, |
| configAdminPidFiles); |
| } |
| |
| public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle, |
| String bundleFilter, String testBundleVersion, String testBundleDirectives, |
| ClassLoader loader, |
| String[]... configAdminPidFiles) throws Exception { |
| TinyBundle bundle = null; |
| TinyBundle configAdminInitBundle = null; |
| |
| if (includeTestBundle) { |
| // add ourselves as a bundle |
| bundle = createTestBundle(testBundleDirectives == null ? name : name + ';' + testBundleDirectives, |
| testBundleVersion, descriptors); |
| } |
| if (configAdminPidFiles != null) { |
| configAdminInitBundle = createConfigAdminInitBundle(configAdminPidFiles); |
| } |
| |
| return createBundleContext(name, bundleFilter, bundle, configAdminInitBundle, loader); |
| } |
| |
| public static BundleContext createBundleContext(String name, String bundleFilter, TinyBundle bundle) throws Exception { |
| return createBundleContext(name, bundleFilter, bundle, null, null); |
| } |
| |
| public static BundleContext createBundleContext(String name, String bundleFilter, |
| TinyBundle bundle, TinyBundle configAdminInitBundle, |
| ClassLoader loader) throws Exception { |
| // ensure felix-connect stores bundles in an unique target directory |
| String uid = "" + System.currentTimeMillis(); |
| String tempDir = "target/bundles/" + uid; |
| System.setProperty("org.osgi.framework.storage", tempDir); |
| createDirectory(tempDir); |
| |
| // use another directory for the jar of the bundle as it cannot be in the same directory |
| // as it has a file lock during running the tests which will cause the temp dir to not be |
| // fully deleted between tests |
| createDirectory("target/test-bundles"); |
| |
| List<BundleDescriptor> bundles = new LinkedList<>(); |
| |
| if (configAdminInitBundle != null) { |
| String jarName = "configAdminInitBundle-" + uid + ".jar"; |
| bundles.add(getBundleDescriptor("target/test-bundles/" + jarName, configAdminInitBundle)); |
| } |
| |
| if (bundle != null) { |
| String jarName = name.toLowerCase(Locale.ENGLISH) + "-" + uid + ".jar"; |
| bundles.add(getBundleDescriptor("target/test-bundles/" + jarName, bundle)); |
| } |
| |
| List<BundleDescriptor> bundleDescriptors = getBundleDescriptors(bundleFilter, loader); |
| // let's put configadmin before blueprint.core |
| int idx1 = -1; |
| int idx2 = -1; |
| for (int i = 0; i < bundleDescriptors.size(); i++) { |
| BundleDescriptor bd = bundleDescriptors.get(i); |
| if ("org.apache.felix.configadmin".equals(bd.getHeaders().get("Bundle-SymbolicName"))) { |
| idx1 = i; |
| } |
| if ("org.apache.aries.blueprint.core".equals(bd.getHeaders().get("Bundle-SymbolicName"))) { |
| idx2 = i; |
| } |
| } |
| if (idx1 >= 0 && idx2 >= 0 && idx1 > idx2) { |
| bundleDescriptors.add(idx2, bundleDescriptors.remove(idx1)); |
| } |
| |
| // get the bundles |
| bundles.addAll(bundleDescriptors); |
| |
| if (LOG.isDebugEnabled()) { |
| for (int i = 0; i < bundles.size(); i++) { |
| BundleDescriptor desc = bundles.get(i); |
| LOG.debug("Bundle #{} -> {}", i, desc); |
| } |
| } |
| |
| // setup felix-connect to use our bundles |
| Map<String, Object> config = new HashMap<>(); |
| config.put(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS, bundles); |
| |
| // create pojorsr osgi service registry |
| PojoServiceRegistry reg = new PojoServiceRegistryFactoryImpl().newPojoServiceRegistry(config); |
| return reg.getBundleContext(); |
| } |
| |
| public static void disposeBundleContext(BundleContext bundleContext) throws BundleException { |
| try { |
| if (bundleContext != null) { |
| List<Bundle> bundles = new ArrayList<>(); |
| bundles.addAll(Arrays.asList(bundleContext.getBundles())); |
| Collections.reverse(bundles); |
| for (Bundle bundle : bundles) { |
| LOG.debug("Stopping bundle {}", bundle); |
| bundle.stop(); |
| } |
| } |
| } catch (Exception e) { |
| IllegalStateException ise = org.apache.camel.util.ObjectHelper.getException(IllegalStateException.class, e); |
| if (ise != null) { |
| // we dont care about illegal state exception as that may happen from OSGi |
| LOG.debug("Error during disposing BundleContext. This exception will be ignored.", e); |
| } else { |
| LOG.warn("Error during disposing BundleContext. This exception will be ignored.", e); |
| } |
| } finally { |
| String tempDir = System.clearProperty("org.osgi.framework.storage"); |
| if (tempDir != null) { |
| LOG.info("Deleting work directory {}", tempDir); |
| deleteDirectory(tempDir); |
| } |
| } |
| } |
| |
| // pick up persistent file configuration |
| @SuppressWarnings({"unchecked", "rawtypes"}) |
| public static void setPersistentFileForConfigAdmin(BundleContext bundleContext, String pid, |
| String fileName, final Dictionary props, |
| String symbolicName, Set<Long> bpEvents, |
| boolean expectReload) throws IOException, InterruptedException { |
| if (pid != null) { |
| if (fileName == null) { |
| throw new IllegalArgumentException("The persistent file should not be null"); |
| } else { |
| File load = new File(fileName); |
| LOG.debug("Loading properties from OSGi config admin file: {}", load); |
| org.apache.felix.utils.properties.Properties cfg = new org.apache.felix.utils.properties.Properties(load); |
| for (Object key : cfg.keySet()) { |
| props.put(key, cfg.get(key)); |
| } |
| |
| ConfigurationAdmin configAdmin = CamelBlueprintHelper |
| .getOsgiService(bundleContext, ConfigurationAdmin.class); |
| if (configAdmin != null) { |
| // ensure we update |
| // we *have to* use "null" as 2nd arg to have correct bundle location for Configuration object |
| final Configuration config = configAdmin.getConfiguration(pid, null); |
| LOG.info("Updating ConfigAdmin {} by overriding properties {}", config, props); |
| // we may have update and in consequence, BP container reload, let's wait for it to |
| // be CREATED again |
| if (expectReload) { |
| CamelBlueprintHelper.waitForBlueprintContainer(bpEvents, bundleContext, symbolicName, BlueprintEvent.CREATED, new Runnable() { |
| @Override |
| public void run() { |
| try { |
| config.update(props); |
| } catch (IOException e) { |
| throw new RuntimeException(e.getMessage(), e); |
| } |
| } |
| }); |
| } else { |
| config.update(props); |
| } |
| } |
| } |
| } |
| } |
| |
| public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, long timeout) { |
| return getOsgiService(bundleContext, type, null, timeout); |
| } |
| |
| public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type) { |
| return getOsgiService(bundleContext, type, null, DEFAULT_TIMEOUT); |
| } |
| |
| public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, String filter) { |
| return getOsgiService(bundleContext, type, filter, DEFAULT_TIMEOUT); |
| } |
| |
| public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, String filter, long timeout) { |
| ServiceTracker<T, T> tracker; |
| try { |
| String flt; |
| if (filter != null) { |
| if (filter.startsWith("(")) { |
| flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")"; |
| } else { |
| flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))"; |
| } |
| } else { |
| flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")"; |
| } |
| Filter osgiFilter = FrameworkUtil.createFilter(flt); |
| tracker = new ServiceTracker<>(bundleContext, osgiFilter, null); |
| tracker.open(true); |
| // Note that the tracker is not closed to keep the reference |
| // This is buggy, as the service reference may change i think |
| Object svc = tracker.waitForService(timeout); |
| |
| if (svc == null) { |
| Dictionary<?, ?> dic = bundleContext.getBundle().getHeaders(); |
| LOG.warn("Test bundle headers: " + explode(dic)); |
| |
| for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) { |
| LOG.warn("ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName()); |
| } |
| |
| for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) { |
| LOG.warn("Filtered ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName()); |
| } |
| |
| throw new RuntimeException("Gave up waiting for service " + flt); |
| } |
| return type.cast(svc); |
| } catch (InvalidSyntaxException e) { |
| throw new IllegalArgumentException("Invalid filter", e); |
| } catch (InterruptedException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| /** |
| * Synchronization method to wait for particular state of BlueprintContainer under test. |
| */ |
| public static void waitForBlueprintContainer(final Set<Long> eventHistory, BundleContext context, |
| final String symbolicName, final int bpEvent, final Runnable runAndWait) |
| throws InterruptedException { |
| final CountDownLatch latch = new CountDownLatch(1); |
| final Throwable[] pThrowable = new Throwable[] {null}; |
| ServiceRegistration<BlueprintListener> registration = context.registerService(BlueprintListener.class, new BlueprintListener() { |
| @Override |
| public void blueprintEvent(BlueprintEvent event) { |
| if (event.getBundle().getSymbolicName().equals(symbolicName)) { |
| if (event.getType() == bpEvent) { |
| // we skip events that we've already seen |
| // it works with BP container reloads if next CREATE state is at least 1ms after previous one |
| if (eventHistory == null || eventHistory.add(event.getTimestamp())) { |
| latch.countDown(); |
| } |
| } else if (event.getType() == BlueprintEvent.FAILURE) { |
| // we didn't wait for FAILURE, but we got it - fail fast then |
| pThrowable[0] = event.getCause(); |
| latch.countDown(); |
| } |
| } |
| } |
| }, null); |
| if (runAndWait != null) { |
| runAndWait.run(); |
| } |
| boolean found = latch.await(CamelBlueprintHelper.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); |
| registration.unregister(); |
| |
| if (!found) { |
| throw new RuntimeException("Gave up waiting for BlueprintContainer from bundle \"" + symbolicName + "\""); |
| } |
| |
| if (pThrowable[0] != null) { |
| throw new RuntimeException(pThrowable[0].getMessage(), pThrowable[0]); |
| } |
| } |
| |
| protected static TinyBundle createConfigAdminInitBundle(String[]... configAdminPidFiles) throws IOException { |
| TinyBundle bundle = TinyBundles.bundle(); |
| StringWriter configAdminInit = null; |
| for (String[] configAdminPidFile : configAdminPidFiles) { |
| if (configAdminPidFile == null) { |
| continue; |
| } |
| if (configAdminInit == null) { |
| configAdminInit = new StringWriter(); |
| } else { |
| configAdminInit.append(','); |
| } |
| configAdminInit.append(configAdminPidFile[1]).append("="); |
| configAdminInit.append(new File(configAdminPidFile[0]).toURI().toString()); |
| } |
| bundle.add(TestBundleActivator.class); |
| bundle.add(Util.class); |
| bundle.set("Manifest-Version", "2") |
| .set("Bundle-ManifestVersion", "2") |
| .set("Bundle-SymbolicName", "ConfigAdminInit") |
| .set("Bundle-Version", BUNDLE_VERSION) |
| .set("Bundle-Activator", TestBundleActivator.class.getName()); |
| |
| if (configAdminInit != null) { |
| bundle.set("X-Camel-Blueprint-ConfigAdmin-Init", configAdminInit.toString()); |
| } |
| |
| return bundle; |
| } |
| |
| protected static TinyBundle createTestBundle(String name, String version, String descriptors) throws IOException { |
| TinyBundle bundle = TinyBundles.bundle(); |
| for (URL url : getBlueprintDescriptors(descriptors)) { |
| LOG.info("Using Blueprint XML file: " + url.getFile()); |
| bundle.add("OSGI-INF/blueprint/blueprint-" + url.getFile().replace("/", "-"), url); |
| } |
| bundle.set("Manifest-Version", "2") |
| .set("Bundle-ManifestVersion", "2") |
| .set("Bundle-SymbolicName", name) |
| .set("Bundle-Version", version); |
| |
| return bundle; |
| } |
| |
| /** |
| * Explode the dictionary into a <code>,</code> delimited list of <code>key=value</code> pairs. |
| */ |
| private static String explode(Dictionary<?, ?> dictionary) { |
| Enumeration<?> keys = dictionary.keys(); |
| StringBuilder result = new StringBuilder(); |
| while (keys.hasMoreElements()) { |
| Object key = keys.nextElement(); |
| result.append(String.format("%s=%s", key, dictionary.get(key))); |
| if (keys.hasMoreElements()) { |
| result.append(", "); |
| } |
| } |
| return result.toString(); |
| } |
| |
| /** |
| * create the directory |
| * |
| * @param file the directory to be created |
| */ |
| public static void createDirectory(String file) { |
| File dir = new File(file); |
| dir.mkdirs(); |
| } |
| |
| /** |
| * Recursively delete a directory, useful to zapping test data |
| * |
| * @param file the directory to be deleted |
| * @return <tt>false</tt> if error deleting directory |
| */ |
| public static boolean deleteDirectory(String file) { |
| return deleteDirectory(new File(file)); |
| } |
| |
| /** |
| * Recursively delete a directory, useful to zapping test data |
| * |
| * @param file the directory to be deleted |
| * @return <tt>false</tt> if error deleting directory |
| */ |
| public static boolean deleteDirectory(File file) { |
| int tries = 0; |
| int maxTries = 5; |
| boolean exists = true; |
| while (exists && (tries < maxTries)) { |
| recursivelyDeleteDirectory(file); |
| tries++; |
| exists = file.exists(); |
| if (exists) { |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| // Ignore |
| } |
| } |
| } |
| return !exists; |
| } |
| |
| private static void recursivelyDeleteDirectory(File file) { |
| if (!file.exists()) { |
| return; |
| } |
| |
| if (file.isDirectory()) { |
| File[] files = file.listFiles(); |
| for (File child : files) { |
| recursivelyDeleteDirectory(child); |
| } |
| } |
| boolean success = file.delete(); |
| if (!success) { |
| LOG.warn("Deletion of file: " + file.getAbsolutePath() + " failed"); |
| } |
| } |
| |
| /** |
| * Provides an iterable collection of references, even if the original array is <code>null</code>. |
| */ |
| private static Collection<ServiceReference> asCollection(ServiceReference[] references) { |
| return references == null ? new ArrayList<>(0) : Arrays.asList(references); |
| } |
| |
| /** |
| * Gets list of bundle descriptors. |
| * @param bundleFilter Filter expression for OSGI bundles. |
| * |
| * @return List pointers to OSGi bundles. |
| * @throws Exception If looking up the bundles fails. |
| */ |
| private static List<BundleDescriptor> getBundleDescriptors(final String bundleFilter, ClassLoader loader) throws Exception { |
| return new ClasspathScanner().scanForBundles(bundleFilter, loader); |
| } |
| |
| /** |
| * Gets the bundle descriptors as {@link URL} resources. |
| * |
| * @param descriptors the bundle descriptors, can be separated by comma |
| * @return the bundle descriptors. |
| * @throws FileNotFoundException is thrown if a bundle descriptor cannot be found |
| */ |
| public static Collection<URL> getBlueprintDescriptors(String descriptors) throws FileNotFoundException, MalformedURLException { |
| List<URL> answer = new ArrayList<>(); |
| if (descriptors != null) { |
| // there may be more resources separated by comma |
| Iterator<?> it = ObjectHelper.createIterator(descriptors); |
| while (it.hasNext()) { |
| String s = (String) it.next(); |
| LOG.trace("Resource descriptor: {}", s); |
| |
| // remove leading / to be able to load resource from the classpath |
| s = FileUtil.stripLeadingSeparator(s); |
| |
| // if there is wildcards for *.xml then we need to find the urls from the package |
| if (s.endsWith("*.xml")) { |
| String packageName = s.substring(0, s.length() - 5); |
| // remove trailing / to be able to load resource from the classpath |
| Enumeration<URL> urls = org.apache.camel.util.ObjectHelper.loadResourcesAsURL(packageName); |
| while (urls.hasMoreElements()) { |
| URL url = urls.nextElement(); |
| File dir = new File(url.getFile()); |
| if (dir.isDirectory()) { |
| File[] files = dir.listFiles(); |
| if (files != null) { |
| for (File file : files) { |
| if (file.isFile() && file.exists() && file.getName().endsWith(".xml")) { |
| String name = packageName + file.getName(); |
| LOG.debug("Resolving resource: {}", name); |
| URL xmlUrl = org.apache.camel.util.ObjectHelper.loadResourceAsURL(name); |
| if (xmlUrl != null) { |
| answer.add(xmlUrl); |
| } |
| } |
| } |
| } |
| } |
| } |
| } else { |
| LOG.debug("Resolving resource: {}", s); |
| URL url = RESOLVER.loadResourceAsURL(s); |
| if (url == null) { |
| throw new FileNotFoundException("Resource " + s + " not found"); |
| } |
| answer.add(url); |
| } |
| } |
| } else { |
| throw new IllegalArgumentException("No bundle descriptor configured. Override getBlueprintDescriptor() or getBlueprintDescriptors() method"); |
| } |
| |
| if (answer.isEmpty()) { |
| throw new IllegalArgumentException("Cannot find any resources in classpath from descriptor " + descriptors); |
| } |
| return answer; |
| } |
| |
| private static BundleDescriptor getBundleDescriptor(String path, TinyBundle bundle) throws Exception { |
| File file = new File(path); |
| // tell the JVM its okay to delete this file on exit as its a temporary file |
| // the JVM may not successfully delete the file though |
| file.deleteOnExit(); |
| |
| FileOutputStream fos = new FileOutputStream(file, false); |
| InputStream is = bundle.build(); |
| try { |
| IOHelper.copyAndCloseInput(is, fos); |
| } finally { |
| IOHelper.close(is, fos); |
| } |
| |
| BundleDescriptor answer; |
| FileInputStream fis = null; |
| JarInputStream jis = null; |
| try { |
| fis = new FileInputStream(file); |
| jis = new JarInputStream(fis); |
| Map<String, String> headers = new HashMap<>(); |
| for (Map.Entry<Object, Object> entry : jis.getManifest().getMainAttributes().entrySet()) { |
| headers.put(entry.getKey().toString(), entry.getValue().toString()); |
| } |
| |
| answer = new BundleDescriptor( |
| bundle.getClass().getClassLoader(), |
| "jar:" + file.toURI().toString() + "!/", |
| headers); |
| } finally { |
| IOHelper.close(jis, fis); |
| } |
| |
| return answer; |
| } |
| |
| /** |
| * Bundle activator that will be invoked in right time to set initial configadmin configuration |
| * for blueprint container. |
| */ |
| public static class TestBundleActivator implements BundleActivator { |
| @Override |
| public void start(BundleContext bundleContext) throws Exception { |
| final String configAdminInit = bundleContext.getBundle().getHeaders().get("X-Camel-Blueprint-ConfigAdmin-Init"); |
| if (configAdminInit != null) { |
| final BundleContext sysContext = bundleContext.getBundle(0).getBundleContext(); |
| // we are started before blueprint.core and felix.configadmin |
| // we are sure that felix.configadmin is started before blueprint.core |
| sysContext.addBundleListener(new SynchronousBundleListener() { |
| @Override |
| public void bundleChanged(BundleEvent event) { |
| if (event.getType() == BundleEvent.STARTED |
| && "org.apache.felix.configadmin".equals(event.getBundle().getSymbolicName())) { |
| // configadmin should have already been started |
| ServiceReference<?> sr = sysContext.getServiceReference("org.osgi.service.cm.ConfigurationAdmin"); |
| if (sr != null && sysContext.getService(sr) != null) { |
| initializeConfigAdmin(sysContext, configAdminInit); |
| } |
| } |
| } |
| }); |
| } |
| } |
| |
| private void initializeConfigAdmin(BundleContext context, String configAdminInit) { |
| String[] pidFiles = configAdminInit.split(","); |
| for (String pidFile : pidFiles) { |
| String[] pf = pidFile.split("="); |
| try { |
| CamelBlueprintHelper.setPersistentFileForConfigAdmin(context, pf[0], new URI(pf[1]).getPath(), |
| new Properties(), null, null, false); |
| } catch (IOException | URISyntaxException e) { |
| throw new RuntimeException(e.getMessage(), e); |
| } catch (InterruptedException e) { |
| Thread.currentThread().interrupt(); |
| throw new RuntimeException(e.getMessage(), e); |
| } |
| } |
| } |
| |
| @Override |
| public void stop(BundleContext bundleContext) throws Exception { |
| } |
| } |
| } |