/******************************************************************************* * Copyright (c) 2008 Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source$ * Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>) * Created on: Aug 19, 2008 * Revision: $Id$ * * Contributors: * Cambridge Semantics Incorporated - initial API and implementation *******************************************************************************/ package org.openanzo.osgi.bootstrap; import java.io.IOException; import java.net.URL; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashSet; import java.util.StringTokenizer; import java.util.concurrent.locks.ReentrantLock; import org.openanzo.exceptions.LogUtils; import org.openanzo.osgi.OsgiConfigurationUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; import org.osgi.framework.SynchronousBundleListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com</a>) * */ class ManifestConfigurationListener implements SynchronousBundleListener { private static final Logger log = LoggerFactory.getLogger(ManifestConfigurationListener.class); private static final String BUNDLE_CONFIG = "Configuration-Properties"; private final BundleContext context; private final BootstrapActivator activator; private final HashSet<Long> bundles = new HashSet<Long>(); protected final ReentrantLock lock = new ReentrantLock(); protected ManifestConfigurationListener(BundleContext context, BootstrapActivator activator) { this.context = context; this.activator = activator; } // marshal from xml decoder protected void open() { lock.lock(); try { Bundle[] bundles = context.getBundles(); for (Bundle bundle : bundles) { if (Bundle.ACTIVE == bundle.getState()) { addingBundle(bundle); } } context.addBundleListener(this); } finally { lock.unlock(); } } protected void close() { context.removeBundleListener(this); } public void bundleChanged(BundleEvent event) { lock.lock(); try { Bundle bundle = event.getBundle(); if (Bundle.ACTIVE == bundle.getState()) { addingBundle(bundle); } } finally { lock.unlock(); } } @SuppressWarnings("unchecked") private void addingBundle(Bundle bundle) { if (!bundles.contains(bundle.getBundleId())) { bundles.add(bundle.getBundleId()); Dictionary<String, String> headers = bundle.getHeaders(); String initPath = headers.get(BUNDLE_CONFIG); if (initPath != null) { StringTokenizer st = new StringTokenizer(initPath, ","); while (st.hasMoreTokens()) { String token = st.nextToken(); token = OsgiConfigurationUtils.preprocessString(token, bundle.getBundleContext()); if (token.endsWith(BootstrapActivator.FILE_EXTENSION)) { processFile(bundle, token); } else if (token.endsWith("/")) { processDirectory(bundle, token, false); } else if (token.endsWith("/*")) { processDirectory(bundle, token, true); } } } } } private void processFile(Bundle bundle, String fileName) { try { URL initResource = bundle.getEntry(fileName); if (initResource != null) { activator.loadBootStrapFile(bundle, initResource.openStream()); } } catch (IOException ioe) { log.error(LogUtils.LIFECYCLE_MARKER, "Error loding bundle's " + bundle.getSymbolicName() + " file:" + fileName, ioe); } } @SuppressWarnings("unchecked") private void processDirectory(Bundle bundle, String directoryName, boolean subDirs) { Enumeration entries = bundle.getEntryPaths(directoryName); if (entries != null) { while (entries.hasMoreElements()) { String entry = (String) entries.nextElement(); if (entry.endsWith(BootstrapActivator.FILE_EXTENSION)) { processFile(bundle, entry); } else if (subDirs && entry.endsWith("/")) { processDirectory(bundle, entry, subDirs); } } } } }