/*
* ============================================================================
* GNU Lesser General Public License
* ============================================================================
*
* Beanlet - JSE Application Container.
* Copyright (C) 2006 Leon van Zantvoort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Leon van Zantvoort
* 243 Acalanes Drive #11
* Sunnyvale, CA 94086
* USA
*
* zantvoort@users.sourceforge.net
* http://beanlet.org
*/
package org.beanlet.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicReference;
import org.beanlet.common.AbstractProvider;
import org.beanlet.plugin.BeanletConfiguration;
import org.beanlet.plugin.DependencyInjectionFactory;
import org.beanlet.plugin.spi.DependencyInjectionFactoryProvider;
import org.jargo.ComponentConfiguration;
import org.jargo.ComponentRegistration;
import org.jargo.DependencyInspector;
import org.jargo.InjectionFactory;
import org.jargo.deploy.Deployable;
import org.jargo.deploy.Deployer;
import org.jargo.spi.DependencyInspectorProvider;
import org.jargo.spi.InjectionFactoryProvider;
import org.jargo.spi.Provider;
/**
* @author Leon van Zantvoort
*/
public final class DependencyInspectorAndInjectionFactoryProviderImpl extends AbstractProvider
implements InjectionFactoryProvider, DependencyInspectorProvider, Deployer {
private final List<DependencyInjectionFactoryProvider> providers;
private final AtomicReference<List<DependencyInjectionFactoryProvider>> ref;
private final ConcurrentHashMap<ComponentConfiguration, DependencyInjectionFactories> dependencyInjectionFactoriesMap;
private final ConcurrentMap<ComponentConfiguration, List<DependencyInspector>> inspectorMap;
private final ConcurrentMap<ComponentConfiguration, List<InjectionFactory<?>>> factoryMap;
public DependencyInspectorAndInjectionFactoryProviderImpl() {
ref = new AtomicReference<List<DependencyInjectionFactoryProvider>>();
providers = new CopyOnWriteArrayList<DependencyInjectionFactoryProvider>();
ref.set(providers);
dependencyInjectionFactoriesMap = new ConcurrentHashMap<ComponentConfiguration, DependencyInjectionFactories>();
inspectorMap = new ConcurrentHashMap<ComponentConfiguration, List<DependencyInspector>>();
factoryMap = new ConcurrentHashMap<ComponentConfiguration, List<InjectionFactory<?>>>();
}
private DependencyInjectionFactories getDependencyInjectionFactories(final BeanletConfiguration configuration) {
DependencyInjectionFactories diFactories = dependencyInjectionFactoriesMap.get(configuration);
if (diFactories == null) {
List<DependencyInjectionFactory> list =
new ArrayList<DependencyInjectionFactory>();
for (DependencyInjectionFactoryProvider provider : ref.get()) {
list.addAll(provider.getDependencyInjectionFactories(configuration));
}
diFactories = new DependencyInjectionFactories(configuration, list);
dependencyInjectionFactoriesMap.putIfAbsent(configuration, diFactories);
}
diFactories = dependencyInjectionFactoriesMap.get(configuration);
assert diFactories != null;
return diFactories;
}
private List<DependencyInspector> getDependencyInspectors(
BeanletConfiguration configuration) {
List<DependencyInspector> inspectors = inspectorMap.get(configuration);
if (inspectors == null) {
DependencyInspector inspector = new DependencyInspectorImpl(configuration,
getDependencyInjectionFactories(configuration));
inspectors = Collections.singletonList(inspector);
inspectorMap.putIfAbsent(configuration, inspectors);
}
inspectors = inspectorMap.get(configuration);
assert inspectors != null;
return inspectors;
}
public List<DependencyInspector> getDependencyInspectors(
final ComponentConfiguration configuration) {
final List<DependencyInspector> list;
if (configuration instanceof BeanletConfiguration) {
list = getDependencyInspectors((BeanletConfiguration) configuration);
} else {
list = Collections.emptyList();
}
return list;
}
private <T> List<InjectionFactory<T>> getInjectionFactories(
BeanletConfiguration<T> configuration) {
List<InjectionFactory<?>> factories = factoryMap.get(configuration);
if (factories == null) {
InjectionFactory<T> factory = new InjectionFactoryImpl<T>(
configuration, getDependencyInjectionFactories(configuration));
factories = Collections.<InjectionFactory<?>>singletonList(factory);
factoryMap.putIfAbsent(configuration, factories);
}
@SuppressWarnings("unchecked")
List<InjectionFactory<T>> tmp = (List<InjectionFactory<T>>)
(List<?>) factoryMap.get(configuration);
assert tmp != null;
return tmp;
}
public <T> List<InjectionFactory<T>> getInjectionFactories(
final ComponentConfiguration<T> configuration) {
final List<InjectionFactory<T>> list;
if (configuration instanceof BeanletConfiguration<?>) {
list = getInjectionFactories((BeanletConfiguration<T>) configuration);
} else {
list = Collections.emptyList();
}
return list;
}
public void setParent(Deployer deployer) {
// Do nothing.
}
public void deploy(Deployable deployable) throws Exception {
if (deployable instanceof DependencyInjectionFactoryProvider) {
dependencyInjectionFactoriesMap.clear();
inspectorMap.clear();
factoryMap.clear();
providers.add((DependencyInjectionFactoryProvider) deployable);
ref.set(sort(providers));
}
}
public void undeploy(Deployable deployable) throws Exception {
if (deployable instanceof DependencyInjectionFactoryProvider) {
dependencyInjectionFactoriesMap.clear();
inspectorMap.clear();
factoryMap.clear();
providers.remove((DependencyInjectionFactoryProvider) deployable);
ref.set(sort(providers));
}
if (deployable instanceof ComponentRegistration) {
List<ComponentConfiguration<?>> configurations =
((ComponentRegistration) deployable).getComponentConfigurations();
dependencyInjectionFactoriesMap.keySet().removeAll(configurations);
inspectorMap.keySet().removeAll(configurations);
factoryMap.keySet().removeAll(configurations);
}
}
/**
* Sorts the specified {@code providers} list according to the rules of
* the {@code SequentialDeployable} interface.
*/
private <T extends Provider> List<T> sort(List<T> providers) {
List<T> list = new ArrayList<T>(providers);
Collections.sort(list, new SequentialDeployableComparator<T>());
return list;
}
}