| /* |
| * 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.util.List; |
| |
| import org.apache.felix.dm.Component; |
| import org.apache.felix.dm.Component.ServiceScope; |
| import org.apache.felix.dm.ComponentState; |
| import org.apache.felix.dm.ComponentStateListener; |
| import org.apache.felix.dm.Dependency; |
| import org.apache.felix.dm.DependencyManager; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceRegistration; |
| |
| /** |
| * Base class for all kind of DM component builders (for Component, Aspect, Adapters ...). |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public abstract class AbstractBuilder |
| { |
| /** |
| * Returns the service component type. |
| */ |
| abstract String getType(); |
| |
| /** |
| * Builds the service component. |
| * @param serviceMetaData the service component metadata parsed from the descriptor file. |
| * @param serviceDependencies the service component dependencies metadata parsed from the descriptor file. |
| */ |
| abstract void build(MetaData serviceMetaData, List<MetaData> serviceDependencies, Bundle b, DependencyManager dm) |
| throws Exception; |
| |
| /** |
| * Sets common Service parameters, if provided from our Component descriptor |
| */ |
| protected void setCommonServiceParams(Component c, MetaData srvMeta) throws Exception |
| { |
| // Set auto configured component fields. |
| DependencyManager dm = c.getDependencyManager(); |
| boolean autoConfigureComponents = "true".equals(dm.getBundleContext().getProperty( |
| Activator.CONF_ENABLE_AUTOCONFIG)); |
| |
| if (!autoConfigureComponents) |
| { |
| c.setAutoConfig(BundleContext.class, Boolean.FALSE); |
| c.setAutoConfig(ServiceRegistration.class, Boolean.FALSE); |
| c.setAutoConfig(DependencyManager.class, Boolean.FALSE); |
| c.setAutoConfig(Component.class, Boolean.FALSE); |
| c.setAutoConfig(Bundle.class, Boolean.FALSE); |
| } |
| |
| // See if BundleContext must be auto configured. |
| String bundleContextField = srvMeta.getString(Params.bundleContextField, null); |
| if (bundleContextField != null) |
| { |
| c.setAutoConfig(BundleContext.class, bundleContextField); |
| } |
| |
| // See if DependencyManager must be auto configured. |
| String dependencyManagerField = srvMeta.getString(Params.dependencyManagerField, null); |
| if (dependencyManagerField != null) |
| { |
| c.setAutoConfig(DependencyManager.class, dependencyManagerField); |
| } |
| |
| // See if Component must be auto configured. |
| String componentField = srvMeta.getString(Params.componentField, null); |
| if (componentField != null) |
| { |
| c.setAutoConfig(Component.class, componentField); |
| } |
| |
| // See if Service Registration must be auto configured |
| String registrationField = srvMeta.getString(Params.registrationField, null); |
| if (registrationField != null) |
| { |
| c.setAutoConfig(ServiceRegistration.class, registrationField); |
| } |
| |
| // Now, if the component has a @Started annotation, then add our component state listener, |
| // which will callback the corresponding annotated method, once the component is started. |
| String registered = srvMeta.getString(Params.registered, null); |
| String unregistered = srvMeta.getString(Params.unregistered, null); |
| |
| if (registered != null || unregistered != null) |
| { |
| c.add(new RegistrationListener(registered, unregistered)); |
| } |
| |
| // See if a service scope is provided |
| String scope = srvMeta.getString(Params.scope, null); |
| if (scope != null) { |
| ServiceScope serviceScope = ServiceScope.valueOf(scope); |
| c.setScope(serviceScope); |
| } |
| |
| // See if Bundle must be auto configured |
| String bundleField = srvMeta.getString(Params.bundle, null); |
| if (bundleField != null) |
| { |
| c.setAutoConfig(Bundle.class, bundleField); |
| } |
| } |
| |
| /** |
| * Registers all unnamed dependencies into a given service. Named dependencies are |
| * handled differently, and are managed by the ServiceLifecycleHandler class. |
| * @throws Exception |
| */ |
| protected static void addUnamedDependencies(Bundle b, DependencyManager dm, Component s, MetaData srvMeta, |
| List<MetaData> depsMeta) throws Exception |
| { |
| for (MetaData dependency : depsMeta) |
| { |
| String name = dependency.getString(Params.name, null); |
| if (name == null) |
| { |
| DependencyBuilder depBuilder = new DependencyBuilder(dependency); |
| Log.instance().info("adding dependency %s into service %s", dependency, srvMeta); |
| Dependency d = depBuilder.build(b, dm); |
| s.add(d); |
| } |
| } |
| } |
| |
| static class RegistrationListener implements ComponentStateListener |
| { |
| private final String m_registered; |
| private final String m_unregistered; |
| private volatile boolean m_isRegistered; |
| |
| RegistrationListener(String registered, String unregistered) |
| { |
| m_registered = registered; |
| m_unregistered = unregistered; |
| } |
| |
| public void changed(Component c, ComponentState state) |
| { |
| boolean wasRegistered = m_isRegistered; |
| switch (state) |
| { |
| case TRACKING_OPTIONAL: |
| // Started |
| m_isRegistered = true; |
| if (!wasRegistered && m_registered != null) |
| { |
| // The component has registered a service: notify all component instances |
| Object[] componentInstances = c.getInstances(); |
| for (Object instance : componentInstances) |
| { |
| try |
| { |
| Class<?>[][] signatures = new Class<?>[][] { { ServiceRegistration.class }, {} }; |
| Object[][] params = new Object[][] { { c.getServiceRegistration() }, {} }; |
| InvocationUtil.invokeCallbackMethod(instance, m_registered, signatures, params); |
| } |
| catch (Throwable t) |
| { |
| Log.instance().error("Exception caught while invoking method %s on component %s", t, |
| m_registered, instance); |
| } |
| } |
| } |
| break; |
| |
| case INSTANTIATED_AND_WAITING_FOR_REQUIRED: |
| // Stopped |
| m_isRegistered = false; |
| if (wasRegistered && m_unregistered != null) |
| { |
| Object[] componentInstances = c.getInstances(); |
| for (Object instance : componentInstances) |
| { |
| try |
| { |
| InvocationUtil.invokeCallbackMethod(instance, m_unregistered, new Class[][] { {} }, |
| new Object[][] { {} }); |
| } |
| catch (Throwable t) |
| { |
| Log.instance().error("Exception caught while invoking method %s on component %s", t, |
| m_registered, instance); |
| } |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| } |
| } |