| /* |
| * 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) |
| { |
| } |
| } |
| } |
| } |
| } |