001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.bus.extension;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Enumeration;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.concurrent.ConcurrentHashMap;
029:
030: import org.apache.cxf.common.injection.ResourceInjector;
031: import org.apache.cxf.configuration.Configurer;
032: import org.apache.cxf.resource.ObjectTypeResolver;
033: import org.apache.cxf.resource.ResourceManager;
034: import org.apache.cxf.resource.ResourceResolver;
035: import org.apache.cxf.resource.SinglePropertyResolver;
036:
037: public class ExtensionManagerImpl implements ExtensionManager {
038:
039: public static final String EXTENSIONMANAGER_PROPERTY_NAME = "extensionManager";
040: public static final String ACTIVATION_NAMESPACES_PROPERTY_NAME = "activationNamespaces";
041: public static final String BUS_EXTENSION_RESOURCE = "META-INF/bus-extensions.xml";
042:
043: private final ClassLoader loader;
044: private ResourceManager resourceManager;
045: private Map<String, Collection<Extension>> deferred;
046: private final Map<Class, Object> activated;
047: private final Map<String, Collection<Object>> namespaced = new ConcurrentHashMap<String, Collection<Object>>();
048:
049: public ExtensionManagerImpl(ClassLoader cl,
050: Map<Class, Object> initialExtensions, ResourceManager rm) {
051: this (BUS_EXTENSION_RESOURCE, cl, initialExtensions, rm);
052: }
053:
054: public ExtensionManagerImpl(String resource, ClassLoader cl,
055: Map<Class, Object> initialExtensions, ResourceManager rm) {
056:
057: loader = cl;
058: activated = initialExtensions;
059: resourceManager = rm;
060:
061: ResourceResolver extensionManagerResolver = new SinglePropertyResolver(
062: EXTENSIONMANAGER_PROPERTY_NAME, this );
063: resourceManager.addResourceResolver(extensionManagerResolver);
064: resourceManager
065: .addResourceResolver(new ObjectTypeResolver(this ));
066:
067: deferred = new ConcurrentHashMap<String, Collection<Extension>>();
068:
069: try {
070: load(resource);
071: } catch (IOException ex) {
072: throw new ExtensionException(ex);
073: }
074: }
075:
076: public synchronized void activateViaNS(String namespaceURI) {
077: Collection<Extension> extensions = deferred.get(namespaceURI);
078: if (null == extensions) {
079: return;
080: }
081: for (Extension e : extensions) {
082: loadAndRegister(e);
083: }
084: extensions.clear();
085: deferred.remove(namespaceURI);
086: }
087:
088: final void load(String resource) throws IOException {
089: Enumeration<URL> urls = Thread.currentThread()
090: .getContextClassLoader().getResources(resource);
091: while (urls.hasMoreElements()) {
092: URL url = urls.nextElement();
093:
094: InputStream is = url.openStream();
095: loadFragment(is);
096: }
097:
098: }
099:
100: final void loadFragment(InputStream is) {
101: List<Extension> extensions = new ExtensionFragmentParser()
102: .getExtensions(is);
103: for (Extension e : extensions) {
104: processExtension(e);
105: }
106: }
107:
108: final void processExtension(Extension e) {
109:
110: if (!e.isDeferred()) {
111: loadAndRegister(e);
112: }
113:
114: Collection<String> namespaces = e.getNamespaces();
115: for (String ns : namespaces) {
116: Collection<Extension> extensions = deferred.get(ns);
117: if (null == extensions) {
118: extensions = new ArrayList<Extension>();
119: deferred.put(ns, extensions);
120: }
121: extensions.add(e);
122: }
123: }
124:
125: final void loadAndRegister(Extension e) {
126:
127: Class<?> cls = null;
128: if (null != e.getInterfaceName()
129: && !"".equals(e.getInterfaceName())) {
130: cls = e.loadInterface(loader);
131: }
132:
133: if (null != activated && null != cls
134: && null != activated.get(cls)) {
135: return;
136: }
137:
138: Object obj = e.load(loader);
139:
140: Configurer configurer = (Configurer) (activated
141: .get(Configurer.class));
142: if (null != configurer) {
143: configurer.configureBean(obj);
144: }
145:
146: // let the object know for which namespaces it has been activated
147: ResourceResolver namespacesResolver = null;
148: if (null != e.getNamespaces()) {
149: namespacesResolver = new SinglePropertyResolver(
150: ACTIVATION_NAMESPACES_PROPERTY_NAME, e
151: .getNamespaces());
152: resourceManager.addResourceResolver(namespacesResolver);
153: }
154:
155: ResourceInjector injector = new ResourceInjector(
156: resourceManager);
157:
158: try {
159: injector.inject(obj);
160: } finally {
161: if (null != namespacesResolver) {
162: resourceManager
163: .removeResourceResolver(namespacesResolver);
164: }
165: }
166:
167: if (null != activated) {
168: if (cls == null) {
169: cls = obj.getClass();
170: }
171: activated.put(cls, obj);
172: }
173: for (String ns : e.getNamespaces()) {
174: Collection<Object> intf2Obj = namespaced.get(ns);
175: if (intf2Obj == null) {
176: intf2Obj = new ArrayList<Object>();
177: if (!namespaced.containsKey(ns)) {
178: namespaced.put(ns, intf2Obj);
179: }
180: }
181: intf2Obj.add(obj);
182: }
183: }
184:
185: public <T> T getExtension(String ns, Class<T> type) {
186: Collection<Object> nsExts = namespaced.get(ns);
187: if (nsExts != null) {
188: for (Object o : nsExts) {
189: if (type.isAssignableFrom(o.getClass())) {
190: return type.cast(o);
191: }
192: }
193: }
194: return null;
195: }
196:
197: }
|