org.apache.openejb.config.provider.ProviderManager Maven / Gradle / Ivy
/*
* 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.openejb.config.provider;
import org.apache.openejb.config.sys.ServiceProvider;
import org.apache.openejb.util.SuperProperties;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A few principles guide this new implementation of ServiceProvider tracking
*
* 1. Never expose the raw datastructure underneath so providers
* must be registered via the "front door" and can't be slipped
* in without proper parent provider resolution.
*
* 2. How to locate providers from disk or parse xml
* is completely abstracted from this implementation.
*
* @version $Rev$ $Date$
*/
public class ProviderManager {
private final List namespaces = new LinkedList();
private final Map providers = new LinkedHashMap();
private final ProviderLoader loader;
public ProviderManager(final ProviderLoader loader) {
this.loader = loader;
}
public ServiceProvider get(final String namespace, final String name) {
final ID id = new ID(namespace, name);
return getProvider(id, new LinkedHashSet());
}
public List getAll() {
return new ArrayList(providers.values());
}
public void register(final String namespace, final ServiceProvider provider) {
if (provider == null) {
throw new IllegalArgumentException("provider cannot be null");
}
final ID id = new ID(namespace, provider.getId());
register(id, provider, new LinkedHashSet());
}
public List load(String namespace) {
if (namespace == null) {
throw new IllegalArgumentException("namespace cannot be null");
}
namespace = namespace.toLowerCase();
if (!namespaces.contains(namespace)) {
namespaces.add(namespace);
{ // load
final ArrayList list = new ArrayList(loader.load(namespace));
for (final ServiceProvider provider : list) {
register(namespace, provider);
}
}
}
final List providers = new ArrayList();
for (final Map.Entry entry : this.providers.entrySet()) {
if (entry.getKey().getNamespace().equals(namespace)) {
providers.add(entry.getValue());
}
}
return providers;
}
private void register(final ID id, final ServiceProvider provider, final Set seen) {
if (providers.containsKey(id)) {
return;
}
if (provider.getParent() != null) {
final ID parentId = ID.parse(provider.getParent(), id);
// Pass in a stack on this call to prevent circular reference
final ServiceProvider parent = getProvider(parentId, seen);
if (parent == null) {
throw new NoSuchParentProviderException(provider, parentId);
}
inherit(provider, parent);
}
validate(id, provider);
providers.put(id, provider);
}
private void inherit(final ServiceProvider child, final ServiceProvider parent) {
if (n(child.getClassName())) {
child.setClassName(parent.getClassName());
}
if (n(child.getConstructor())) {
child.setConstructor(parent.getConstructor());
}
if (n(child.getFactoryName())) {
child.setFactoryName(parent.getFactoryName());
}
if (n(child.getDescription())) {
child.setDescription(parent.getDescription());
}
if (n(child.getDisplayName())) {
child.setDisplayName(parent.getDisplayName());
}
if (n(child.getService())) {
child.setService(parent.getService());
}
{ // types
final Set types = new HashSet();
types.addAll(parent.getTypes());
types.addAll(child.getTypes());
child.getTypes().clear();
child.getTypes().addAll(types);
}
{ // properties
final SuperProperties properties = new SuperProperties();
properties.putAll(parent.getProperties());
properties.putAll(child.getProperties());
child.getProperties().clear();
child.getProperties().putAll(properties);
}
}
private boolean n(final String s) {
return s == null || s.length() == 0;
}
private ServiceProvider getProvider(final ID id, final Set seen) {
if (seen.contains(id)) {
throw new ProviderCircularReferenceException(seen);
}
seen.add(id);
{ // Already loaded?
final ServiceProvider provider = providers.get(id);
if (provider != null) {
return provider;
}
}
{ // Can we load it?
final ServiceProvider provider = loader.load(id);
if (provider != null) {
register(id, provider, seen);
return provider;
}
}
return null;
}
private void validate(final ID id, final ServiceProvider provider) {
id.validate();
if (provider.getService() == null) {
throw new InvalidProviderDeclarationException("'service' attribute cannot be null", id, provider);
}
// TODO - validate provider
}
public ProviderLoader getLoader() {
return loader;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy