/* * 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.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 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 class FilterComponent 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; public FilterComponent(Component service) { m_component = (ComponentImpl) service; } @Override public <T> T createConfigurationType(Class<T> 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 Component add(Dependency ... dependencies) { m_component.getExecutor().execute(() -> { 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 this; } public Component 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 this; } public Component 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 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 Component 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 this; } public Component 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 this; } public Component setCallbacks(String init, String start, String stop, String destroy) { setCallbacks(null, init, start, stop, destroy); return this; } public Component setComposition(Object instance, String getMethod) { m_component.ensureNotActive(); m_compositionInstance = instance; m_compositionMethod = getMethod; return this; } public Component setComposition(String getMethod) { m_component.ensureNotActive(); m_compositionMethod = getMethod; return this; } public Component setFactory(Object factory, String createMethod) { m_component.ensureNotActive(); m_factory = factory; m_factoryCreateMethod = createMethod; return this; } public Component setFactory(String createMethod) { return setFactory(null, createMethod); } public Component setImplementation(Object implementation) { m_component.ensureNotActive(); m_serviceImpl = implementation; return this; } public Component setInterface(String serviceName, Dictionary<?, ?> properties) { return setInterface(new String[] { serviceName }, properties); } @SuppressWarnings("unchecked") public Component 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 this; } @SuppressWarnings("unchecked") public Component 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 this; } public void start() { m_component.start(); } 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 Component setAutoConfig(Class<?> clazz, boolean autoConfig) { m_component.setAutoConfig(clazz, autoConfig); return this; } public Component setAutoConfig(Class<?> clazz, String instanceName) { m_component.setAutoConfig(clazz, instanceName); return 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 <T> T 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 Component setDebug(String label) { m_component.setDebug(label); return 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(); } }