blob: 9022064745b5f8a578647b8cbf5bfb6249da538e [file] [log] [blame]
/*
* 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.felix.dm.runtime;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.osgi.framework.Bundle;
/**
* This class parses service descriptors generated by the annotation bnd processor.
* The descriptors are located under META-INF/dependencymanager directory. Such files are actually
* referenced by a specific "DependendencyManager-Component" manifest header.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class DependencyManagerRuntime
{
private ConcurrentHashMap<Bundle, DependencyManager> m_managers =
new ConcurrentHashMap<Bundle, DependencyManager>();
private DescriptorParser m_parser;
/**
* Our constructor. We'll initialize here our DM component builders.
*/
public DependencyManagerRuntime()
{
// Instantiates our descriptor parser, and register our service builders into it.
m_parser = new DescriptorParser();
m_parser.addBuilder(new ComponentBuilder());
m_parser.addBuilder(new AspectServiceBuilder());
m_parser.addBuilder(new AdapterServiceBuilder());
m_parser.addBuilder(new BundleAdapterServiceBuilder());
m_parser.addBuilder(new FactoryConfigurationAdapterServiceBuilder());
m_parser.addBuilder(new ResourceAdapterServiceBuilder());
}
/**
* Return our Object Composition (the Activator will inject dependencies into it)
*/
protected Object[] getComposition()
{
return new Object[] { this, Log.instance() };
}
/**
* Starts our Service (at this point, we have been injected with our bundle context, as well
* as with our log service. We'll listen to bundle start/stop events (we implement the
* SynchronousBundleListener interface).
*/
protected void start()
{
Log.instance().info("Starting Dependency Manager annotation runtime");
}
/**
* Stops our service. We'll stop all activated DependencyManager services.
*/
@SuppressWarnings("unchecked")
protected void stop()
{
Log.instance().info("Runtime: stopping services");
for (DependencyManager dm : m_managers.values())
{
List<Component> services = new ArrayList<Component>(dm.getComponents());
for (Component service : services)
{
dm.remove(service);
}
}
m_managers.clear();
}
/**
* Checks if a started bundle have some DependencyManager descriptors
* referenced in the "DependencyManager-Component" OSGi header.
* @param b the started bundle.
*/
protected void bundleStarted(Bundle b)
{
String descriptorPaths = (String) b.getHeaders().get("DependencyManager-Component");
if (descriptorPaths == null)
{
return;
}
for (String descriptorPath : descriptorPaths.split(","))
{
URL descriptorURL = b.getEntry(descriptorPath);
if (descriptorURL == null)
{
Log.instance().error("Runtime: " + "DependencyManager component descriptor not found: %s",
descriptorPath);
continue;
}
loadDescriptor(b, descriptorURL);
}
}
/**
* Unregisters all services for a stopping bundle.
* @param b
*/
@SuppressWarnings("unchecked")
protected void bundleStopped(Bundle b)
{
Log.instance().info("Runtime: Removing services from stopping bundle: %s", b.getSymbolicName());
DependencyManager dm = m_managers.remove(b);
if (dm != null)
{
List<Component> services = new ArrayList(dm.getComponents());
for (Component service : services)
{
Log.instance().info("Runtime: Removing service: %s", service);
dm.remove(service);
}
}
}
/**
* Load a DependencyManager component descriptor from a given bundle.
* @param b
* @param descriptorURL
*/
private void loadDescriptor(Bundle b, URL descriptorURL)
{
Log.instance().debug("Runtime: ++++ Parsing descriptor %s from bundle %s",
descriptorURL,
b.getSymbolicName());
BufferedReader in = null;
try
{
in = new BufferedReader(new InputStreamReader(descriptorURL.openStream()));
DependencyManager dm = m_managers.get(b);
if (dm == null)
{
dm = new DependencyManager(b.getBundleContext());
m_managers.put(b, dm);
}
m_parser.parse(in, b, dm);
m_managers.put(b, dm);
}
catch (Throwable t)
{
Log.instance().error("Runtime: Error while parsing descriptor %s from bundle %s",
t,
descriptorURL,
b.getSymbolicName());
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException ignored)
{
}
}
}
}
}