blob: cd7ad143147a0bd010687ebf36bf763dbc2edbe5 [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.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();
}
}