| /** |
| * 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.cxf.bus.osgi; |
| |
| import java.util.Dictionary; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.regex.Pattern; |
| |
| import org.apache.cxf.Bus; |
| import org.apache.cxf.bus.extension.ExtensionManagerImpl; |
| import org.apache.cxf.buslifecycle.BusCreationListener; |
| import org.apache.cxf.buslifecycle.BusLifeCycleListener; |
| import org.apache.cxf.buslifecycle.BusLifeCycleManager; |
| import org.apache.cxf.common.util.CollectionUtils; |
| import org.apache.cxf.common.util.StringUtils; |
| import org.apache.cxf.configuration.ConfiguredBeanLocator; |
| import org.apache.cxf.endpoint.ClientLifeCycleListener; |
| import org.apache.cxf.endpoint.ClientLifeCycleManager; |
| import org.apache.cxf.endpoint.ServerLifeCycleListener; |
| import org.apache.cxf.endpoint.ServerLifeCycleManager; |
| import org.apache.cxf.feature.Feature; |
| import org.apache.cxf.workqueue.WorkQueueManager; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.framework.Version; |
| |
| public class OSGIBusListener implements BusLifeCycleListener { |
| public static final String CONTEXT_SYMBOLIC_NAME_PROPERTY = "cxf.context.symbolicname"; |
| public static final String CONTEXT_VERSION_PROPERTY = "cxf.context.version"; |
| public static final String CONTEXT_NAME_PROPERTY = "cxf.bus.id"; |
| |
| private static final String SERVICE_PROPERTY_PRIVATE = "org.apache.cxf.bus.private.extension"; |
| private static final String SERVICE_PROPERTY_RESTRICTED = "org.apache.cxf.bus.restricted.extension"; |
| private static final String BUS_EXTENSION_BUNDLES_EXCLUDES = "bus.extension.bundles.excludes"; |
| Bus bus; |
| ServiceRegistration<?> service; |
| BundleContext defaultContext; |
| private Pattern extensionBundlesExcludesPattern; |
| |
| public OSGIBusListener(Bus b) { |
| this(b, null); |
| } |
| public OSGIBusListener(Bus b, Object[] args) { |
| bus = b; |
| if (args != null && args.length > 0 |
| && args[0] instanceof BundleContext) { |
| defaultContext = (BundleContext)args[0]; |
| } |
| String extExcludes = (String)bus.getProperty(BUS_EXTENSION_BUNDLES_EXCLUDES); |
| if (!StringUtils.isEmpty(extExcludes)) { |
| try { |
| extensionBundlesExcludesPattern = Pattern.compile(extExcludes); |
| } catch (IllegalArgumentException e) { |
| // ignore |
| } |
| } |
| BusLifeCycleManager manager = bus.getExtension(BusLifeCycleManager.class); |
| manager.registerLifeCycleListener(this); |
| registerConfiguredBeanLocator(); |
| registerClientLifeCycleListeners(); |
| registerServerLifecycleListeners(); |
| registerBusFeatures(); |
| sendBusCreatedToBusCreationListeners(); |
| |
| } |
| private void registerConfiguredBeanLocator() { |
| final ConfiguredBeanLocator cbl = bus.getExtension(ConfiguredBeanLocator.class); |
| if (cbl instanceof ExtensionManagerImpl) { |
| // wire in the OSGi things |
| bus.setExtension(new OSGiBeanLocator(cbl, defaultContext), |
| ConfiguredBeanLocator.class); |
| } |
| } |
| |
| public void initComplete() { |
| ManagedWorkQueueList wqList = bus.getExtension(ManagedWorkQueueList.class); |
| if (wqList != null) { |
| WorkQueueManager manager = bus.getExtension(WorkQueueManager.class); |
| wqList.addAllToWorkQueueManager(manager); |
| } |
| registerBusAsService(); |
| } |
| |
| |
| public void preShutdown() { |
| } |
| |
| public void postShutdown() { |
| if (service != null) { |
| service.unregister(); |
| service = null; |
| } |
| } |
| |
| private static ServiceReference<?>[] getServiceReferences(BundleContext context, Class<?> serviceClass) { |
| ServiceReference<?>[] refs = null; |
| try { |
| refs = context.getServiceReferences(serviceClass.getName(), null); |
| } catch (InvalidSyntaxException e) { |
| // ignore |
| } |
| if (refs == null) { |
| refs = new ServiceReference<?>[]{}; |
| } |
| return refs; |
| } |
| |
| private void sendBusCreatedToBusCreationListeners() { |
| ServiceReference<?>[] refs = getServiceReferences(defaultContext, BusCreationListener.class); |
| for (ServiceReference<?> ref : refs) { |
| if (!isPrivate(ref) && !isExcluded(ref)) { |
| BusCreationListener listener = (BusCreationListener)defaultContext.getService(ref); |
| listener.busCreated(bus); |
| } |
| } |
| } |
| |
| private void registerServerLifecycleListeners() { |
| ServiceReference<?>[] refs = getServiceReferences(defaultContext, ServerLifeCycleListener.class); |
| ServerLifeCycleManager clcm = bus.getExtension(ServerLifeCycleManager.class); |
| for (ServiceReference<?> ref : refs) { |
| if (!isPrivate(ref) && !isExcluded(ref)) { |
| ServerLifeCycleListener listener = (ServerLifeCycleListener)defaultContext.getService(ref); |
| clcm.registerListener(listener); |
| } |
| } |
| } |
| private void registerClientLifeCycleListeners() { |
| ServiceReference<?>[] refs = getServiceReferences(defaultContext, ClientLifeCycleListener.class); |
| ClientLifeCycleManager clcm = bus.getExtension(ClientLifeCycleManager.class); |
| for (ServiceReference<?> ref : refs) { |
| if (!isPrivate(ref) && !isExcluded(ref)) { |
| ClientLifeCycleListener listener = (ClientLifeCycleListener)defaultContext.getService(ref); |
| clcm.registerListener(listener); |
| } |
| } |
| } |
| |
| private void registerBusFeatures() { |
| ServiceReference<?>[] refs = getServiceReferences(defaultContext, Feature.class); |
| for (ServiceReference<?> ref : refs) { |
| if (!isPrivate(ref) && !isExcluded(ref)) { |
| Feature feature = (Feature)defaultContext.getService(ref); |
| bus.getFeatures().add(feature); |
| } |
| } |
| } |
| |
| private boolean isPrivate(ServiceReference<?> ref) { |
| Object o = ref.getProperty(SERVICE_PROPERTY_PRIVATE); |
| |
| if (o == null) { |
| return false; |
| } |
| |
| Boolean pvt = Boolean.FALSE; |
| if (o instanceof String) { |
| pvt = Boolean.parseBoolean((String)o); |
| } else if (o instanceof Boolean) { |
| pvt = (Boolean)o; |
| } |
| return pvt.booleanValue(); |
| } |
| |
| private boolean isExcluded(ServiceReference<?> ref) { |
| String o = (String)ref.getProperty(SERVICE_PROPERTY_RESTRICTED); |
| if (!StringUtils.isEmpty(o)) { |
| // if the service's restricted-regex is set, the service is excluded when the app not matching that regex |
| BundleContext app = bus.getExtension(BundleContext.class); |
| try { |
| if (app != null && !app.getBundle().getSymbolicName().matches(o)) { |
| return true; |
| } |
| } catch (IllegalArgumentException e) { |
| // ignore |
| } |
| } |
| // if the excludes-regex is set, the service is excluded when matching that regex. |
| return extensionBundlesExcludesPattern != null |
| && extensionBundlesExcludesPattern.matcher(ref.getBundle().getSymbolicName()).matches(); |
| } |
| |
| private Version getBundleVersion(Bundle bundle) { |
| Dictionary<?, ?> headers = bundle.getHeaders(); |
| String version = (String) headers.get(Constants.BUNDLE_VERSION); |
| return (version != null) ? Version.parseVersion(version) : Version.emptyVersion; |
| } |
| |
| |
| |
| private void registerBusAsService() { |
| BundleContext context = bus.getExtension(BundleContext.class); |
| if (context != null) { |
| Map<String, Object> props = new HashMap<>(); |
| props.put(CONTEXT_SYMBOLIC_NAME_PROPERTY, context.getBundle().getSymbolicName()); |
| props.put(CONTEXT_VERSION_PROPERTY, getBundleVersion(context.getBundle())); |
| props.put(CONTEXT_NAME_PROPERTY, bus.getId()); |
| |
| service = context.registerService(Bus.class.getName(), bus, CollectionUtils.toDictionary(props)); |
| } |
| } |
| |
| } |