| /* |
| * 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.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Dictionary; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| import java.util.concurrent.Executor; |
| import java.util.function.Supplier; |
| import java.util.stream.Stream; |
| |
| import org.apache.felix.dm.Component; |
| import org.apache.felix.dm.ComponentDeclaration; |
| import org.apache.felix.dm.ComponentDependencyDeclaration; |
| import org.apache.felix.dm.ComponentStateListener; |
| import org.apache.felix.dm.Dependency; |
| import org.apache.felix.dm.DependencyManager; |
| import org.apache.felix.dm.Logger; |
| import org.apache.felix.dm.context.ComponentContext; |
| import org.apache.felix.dm.context.DependencyContext; |
| import org.apache.felix.dm.context.Event; |
| import org.apache.felix.dm.context.EventType; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceRegistration; |
| |
| /** |
| * This class allows to filter a Component interface. All Aspect/Adapters extend this class |
| * in order to add functionality to the default Component implementation. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public abstract class FilterComponent<T extends Component> implements Component, ComponentContext, ComponentDeclaration { |
| protected volatile ComponentImpl m_component; |
| protected volatile List<ComponentStateListener> m_stateListeners = new CopyOnWriteArrayList<>(); |
| protected volatile String m_init = "init"; |
| protected volatile String m_start = "start"; |
| protected volatile String m_stop = "stop"; |
| protected volatile String m_destroy = "destroy"; |
| protected volatile Object m_callbackObject; |
| protected volatile Object m_compositionInstance; |
| protected volatile String m_compositionMethod; |
| protected volatile String[] m_serviceInterfaces; |
| protected volatile Object m_serviceImpl; |
| protected volatile Object m_factory; |
| protected volatile String m_factoryCreateMethod; |
| protected volatile Dictionary<String, Object> m_serviceProperties; |
| protected volatile ServiceScope m_scope = ServiceScope.SINGLETON; |
| private boolean m_started; |
| private final List<Dependency> m_dependencies = new ArrayList<>(); |
| |
| public FilterComponent(Component service) { |
| m_component = (ComponentImpl) service; |
| } |
| |
| @Override |
| public boolean injectionDisabled() { |
| return m_component.injectionDisabled(); |
| } |
| |
| @Override |
| public <U> U createConfigurationType(Class<U> type, Dictionary<?, ?> config) { |
| return m_component.createConfigurationType(type, config); |
| } |
| |
| @Override |
| public Executor getExecutor() { |
| return m_component.getExecutor(); |
| } |
| |
| @Override |
| public String toString() { |
| return m_component.toString(); |
| } |
| |
| public T setScope(ServiceScope scope) { |
| m_scope = scope; |
| return (T) this; |
| } |
| |
| public T add(Dependency ... dependencies) { |
| m_component.getExecutor().execute(() -> { |
| if (! m_started) { |
| Stream.of(dependencies).forEach(m_dependencies::add); |
| return; |
| } |
| m_component.add(dependencies); |
| Object instance = m_component.getInstance(); |
| if (instance instanceof AbstractDecorator) { |
| AbstractDecorator ad = (AbstractDecorator) instance; |
| ad.addDependency(dependencies); // will clone the dependencies for each component instance |
| } |
| }); |
| return (T) this; |
| } |
| |
| public T remove(Dependency dependency) { |
| m_component.getExecutor().execute(() -> { |
| m_component.remove(dependency); |
| Object instance = m_component.getInstance(); |
| if (instance != null && instance instanceof AbstractDecorator) { |
| ((AbstractDecorator) instance).removeDependency(dependency); // will remove the previously cloned dependency |
| } |
| }); |
| return (T) this; |
| } |
| |
| public T add(ComponentStateListener listener) { |
| m_component.getExecutor().execute(() -> { |
| m_stateListeners.add(listener); |
| // Add the listener to all already instantiated services. |
| Object instance = m_component.getInstance(); |
| if (instance instanceof AbstractDecorator) { |
| ((AbstractDecorator) instance).addStateListener(listener); |
| } |
| }); |
| return (T) this; |
| } |
| |
| public List<DependencyContext> getDependencies() { |
| return m_component.getDependencies(); |
| } |
| |
| public String getClassName() { |
| return m_component.getClassName(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public Dictionary<String, Object> getServiceProperties() { |
| return m_serviceProperties; |
| } |
| |
| public ServiceRegistration<?> getServiceRegistration() { |
| return m_component.getServiceRegistration(); |
| } |
| |
| public T remove(ComponentStateListener listener) { |
| m_stateListeners.remove(listener); |
| // Remove the listener from all already instantiated services. |
| Object instance = m_component.getInstance(); |
| if (instance != null && instance instanceof AbstractDecorator) { |
| ((AbstractDecorator) instance).removeStateListener(listener); |
| } |
| return (T) this; |
| } |
| |
| public T setCallbacks(Object instance, String init, String start, String stop, String destroy) { |
| m_component.ensureNotActive(); |
| m_callbackObject = instance; |
| m_init = init; |
| m_start = start; |
| m_stop = stop; |
| m_destroy = destroy; |
| return (T) this; |
| } |
| |
| public T setCallbacks(String init, String start, String stop, String destroy) { |
| setCallbacks(null, init, start, stop, destroy); |
| return (T) this; |
| } |
| |
| public T setComposition(Object instance, String getMethod) { |
| m_component.ensureNotActive(); |
| m_compositionInstance = instance; |
| m_compositionMethod = getMethod; |
| return (T) this; |
| } |
| |
| public T setComposition(String getMethod) { |
| m_component.ensureNotActive(); |
| m_compositionMethod = getMethod; |
| return (T) this; |
| } |
| |
| public T setFactory(Object factory, String createMethod) { |
| m_component.ensureNotActive(); |
| m_factory = factory; |
| m_factoryCreateMethod = createMethod; |
| return (T) this; |
| } |
| |
| public T setFactory(String createMethod) { |
| return setFactory(null, createMethod); |
| } |
| |
| public T setImplementation(Object implementation) { |
| m_component.ensureNotActive(); |
| m_serviceImpl = implementation; |
| return (T) this; |
| } |
| |
| public T setInterface(String serviceName, Dictionary<?, ?> properties) { |
| return setInterface(new String[] { serviceName }, properties); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public T setInterface(String[] serviceInterfaces, Dictionary<?, ?> properties) { |
| m_component.ensureNotActive(); |
| if (serviceInterfaces != null) { |
| m_serviceInterfaces = new String[serviceInterfaces.length]; |
| System.arraycopy(serviceInterfaces, 0, m_serviceInterfaces, 0, serviceInterfaces.length); |
| m_serviceProperties = (Dictionary<String, Object>) properties; |
| } |
| return (T) this; |
| } |
| |
| public T setInterface(Class<?> serviceName, Dictionary<?, ?> properties) { |
| return setInterface(serviceName.getName(), properties); |
| } |
| |
| public T setInterface(Class<?>[] serviceInterfaces, Dictionary<?, ?> properties) { |
| String[] ifaces = Stream.of(serviceInterfaces).map(clazz -> clazz.getName()).toArray(String[]::new); |
| return setInterface(ifaces, properties); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public T setServiceProperties(Dictionary<?, ?> serviceProperties) { |
| m_serviceProperties = (Dictionary<String, Object>) serviceProperties; |
| // Set the properties to all already instantiated services. |
| if (serviceProperties != null) { |
| Object instance = m_component.getInstance(); |
| if (instance instanceof AbstractDecorator) { |
| ((AbstractDecorator) instance).setServiceProperties(serviceProperties); |
| } |
| } |
| return (T) this; |
| } |
| |
| public void start() { |
| m_component.getExecutor().execute(() -> { |
| if (! m_started) { |
| m_started = true; |
| // first initialize concrete adapters, which need to add |
| // their internal dependencies first. |
| startInitial(); |
| // Now, add extra dependencies |
| for (Dependency dep : m_dependencies) { |
| m_component.add(dep); |
| } |
| m_dependencies.clear(); |
| } |
| m_component.start(); |
| }); |
| } |
| |
| protected abstract void startInitial(); |
| |
| public void stop() { |
| m_component.stop(); |
| } |
| |
| public void invokeCallbackMethod(Object[] instances, String methodName, Class<?>[][] signatures, Object[][] parameters) { |
| m_component.invokeCallbackMethod(instances, methodName, signatures, parameters); |
| } |
| |
| public void invokeCallbackMethod(Object[] instances, String methodName, Class<?>[][] signatures, Object[][] parameters, boolean logIfNotFound) { |
| m_component.invokeCallbackMethod(instances, methodName, signatures, parameters, logIfNotFound); |
| } |
| |
| public void invokeCallback(Object[] instances, String methodName, Class<?>[][] signatures, Supplier<?>[][] paramsSupplier, boolean logIfNotFound) { |
| m_component.invokeCallbackMethod(instances, methodName, signatures, paramsSupplier, logIfNotFound); |
| } |
| |
| public DependencyManager getDependencyManager() { |
| return m_component.getDependencyManager(); |
| } |
| |
| public T setAutoConfig(Class<?> clazz, boolean autoConfig) { |
| m_component.setAutoConfig(clazz, autoConfig); |
| return (T) this; |
| } |
| |
| public T setAutoConfig(Class<?> clazz, String instanceName) { |
| m_component.setAutoConfig(clazz, instanceName); |
| return (T) this; |
| } |
| |
| public boolean getAutoConfig(Class<?> clazz) { |
| return m_component.getAutoConfig(clazz); |
| } |
| |
| public String getAutoConfigInstance(Class<?> clazz) { |
| return m_component.getAutoConfigInstance(clazz); |
| } |
| |
| public ComponentDependencyDeclaration[] getComponentDependencies() { |
| return m_component.getComponentDependencies(); |
| } |
| |
| public String getName() { |
| return m_component.getName(); |
| } |
| |
| public int getState() { |
| return m_component.getState(); |
| } |
| |
| public long getId() { |
| return m_component.getId(); |
| } |
| |
| public String[] getServices() { |
| return m_component.getServices(); |
| } |
| |
| public BundleContext getBundleContext() { |
| return m_component.getBundleContext(); |
| } |
| |
| @Override |
| public boolean isActive() { |
| return m_component.isActive(); |
| } |
| |
| @Override |
| public boolean isAvailable() { |
| return m_component.isAvailable(); |
| } |
| |
| @Override |
| public void handleEvent(DependencyContext dc, EventType type, Event ... e) { |
| m_component.handleEvent(dc, type, e); |
| } |
| |
| @Override |
| public <U> U getInstance() { |
| return m_component.getInstance(); |
| } |
| |
| @Override |
| public Object[] getInstances() { |
| return m_component.getInstances(); |
| } |
| |
| @Override |
| public Event getDependencyEvent(DependencyContext dc) { |
| return m_component.getDependencyEvent(dc); |
| } |
| |
| @Override |
| public Set<Event> getDependencyEvents(DependencyContext dc) { |
| return m_component.getDependencyEvents(dc); |
| } |
| |
| public ComponentDeclaration getComponentDeclaration() { |
| return this; |
| } |
| |
| @Override |
| public T setDebug(String label) { |
| m_component.setDebug(label); |
| return (T) this; |
| } |
| |
| @Override |
| public void setThreadPool(Executor threadPool) { |
| m_component.setThreadPool(threadPool); |
| } |
| |
| @Override |
| public Map<String, Long> getCallbacksTime() { |
| return m_component.getCallbacksTime(); |
| } |
| |
| @Override |
| public Bundle getBundle() { |
| return m_component.getBundle(); |
| } |
| |
| @Override |
| public Logger getLogger() { |
| return m_component.getLogger(); |
| } |
| |
| protected void copyDependencies(List<DependencyContext> dependencies, Component component) { |
| dependencies.stream().map(dc -> dc.createCopy()).forEach(component::add); |
| } |
| |
| @Override |
| public ComponentContext instantiateComponent() { |
| return m_component.instantiateComponent(); |
| } |
| } |