| /** |
| * 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.dosgi.dsw.handlers; |
| |
| import java.net.URL; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.cxf.Bus; |
| import org.apache.cxf.common.util.ProxyClassLoader; |
| import org.apache.cxf.dosgi.dsw.Constants; |
| import org.apache.cxf.dosgi.dsw.api.Endpoint; |
| import org.apache.cxf.dosgi.dsw.api.IntentUnsatisfiedException; |
| import org.apache.cxf.dosgi.dsw.qos.IntentManager; |
| import org.apache.cxf.dosgi.dsw.util.OsgiUtils; |
| import org.apache.cxf.endpoint.Server; |
| import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; |
| import org.apache.cxf.jaxrs.client.Client; |
| import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean; |
| import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; |
| import org.apache.cxf.jaxrs.model.UserResource; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.remoteserviceadmin.EndpointDescription; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class JaxRSPojoConfigurationTypeHandler extends AbstractPojoConfigurationTypeHandler { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(JaxRSPojoConfigurationTypeHandler.class); |
| |
| public JaxRSPojoConfigurationTypeHandler(BundleContext dswBC, |
| IntentManager intentManager, |
| HttpServiceManager httpServiceManager) { |
| super(dswBC, intentManager, httpServiceManager); |
| } |
| |
| public String[] getSupportedTypes() { |
| return new String[] {Constants.RS_CONFIG_TYPE}; |
| } |
| |
| public Object importEndpoint(BundleContext consumerContext, |
| Class<?> iClass, |
| EndpointDescription endpoint) { |
| String address = getPojoAddress(endpoint, iClass); |
| if (address == null) { |
| LOG.warn("Remote address is unavailable"); |
| return null; |
| } |
| ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); |
| try { |
| return createJaxrsProxy(address, consumerContext, iClass, null, endpoint); |
| } catch (Throwable e) { |
| Thread.currentThread().setContextClassLoader(oldClassLoader); |
| } |
| |
| try { |
| ProxyClassLoader cl = new ProxyClassLoader(iClass.getClassLoader()); |
| cl.addLoader(Client.class.getClassLoader()); |
| return createJaxrsProxy(address, consumerContext, iClass, cl, endpoint); |
| } catch (Throwable e) { |
| LOG.warn("proxy creation failed", e); |
| } |
| |
| return null; |
| } |
| |
| protected Object createJaxrsProxy(String address, |
| BundleContext callingContext, |
| Class<?> iClass, |
| ClassLoader loader, |
| EndpointDescription endpoint) { |
| JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); |
| bean.setAddress(address); |
| if (loader != null) { |
| bean.setClassLoader(loader); |
| } |
| |
| addRsInterceptorsFeaturesProps(bean, callingContext, endpoint.getProperties()); |
| |
| List<UserResource> resources = JaxRSUtils.getModel(callingContext, iClass); |
| if (resources != null) { |
| bean.setModelBeansWithServiceClass(resources, iClass); |
| } else { |
| bean.setServiceClass(iClass); |
| } |
| List<Object> providers = JaxRSUtils.getProviders(callingContext, endpoint.getProperties()); |
| if (providers != null && !providers.isEmpty()) { |
| bean.setProviders(providers); |
| } |
| Thread.currentThread().setContextClassLoader(JAXRSClientFactoryBean.class.getClassLoader()); |
| return getProxy(bean.create(), iClass); |
| } |
| |
| public Endpoint exportService(ServiceReference<?> sref, |
| Map<String, Object> sd, |
| String exportedInterface) throws IntentUnsatisfiedException { |
| BundleContext callingContext = sref.getBundle().getBundleContext(); |
| Object serviceBean = callingContext.getService(sref); |
| Class<?> iClass = ClassUtils.getInterfaceClass(serviceBean, exportedInterface); |
| String contextRoot = getServletContextRoot(sd); |
| String address; |
| if (contextRoot == null) { |
| address = getServerAddress(sd, iClass); |
| } else { |
| address = getClientAddress(sd); |
| if (address == null) { |
| address = "/"; |
| } |
| } |
| Bus bus = createBus(sref, callingContext, contextRoot); |
| |
| LOG.info("Creating a " + iClass.getName() |
| + " endpoint via JaxRSPojoConfigurationTypeHandler, address is " + address); |
| |
| JAXRSServerFactoryBean factory = createServerFactory(callingContext, sd, iClass, serviceBean, address, bus); |
| String completeEndpointAddress = httpServiceManager.getAbsoluteAddress(contextRoot, address); |
| |
| // The properties for the EndpointDescription |
| Map<String, Object> endpointProps = createEndpointProps(sd, iClass, new String[] {Constants.RS_CONFIG_TYPE}, |
| completeEndpointAddress, new String[] {"HTTP"}); |
| |
| return createServerFromFactory(factory, endpointProps); |
| } |
| |
| private Endpoint createServerFromFactory(JAXRSServerFactoryBean factory, |
| Map<String, Object> endpointProps) { |
| ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); |
| try { |
| Thread.currentThread().setContextClassLoader(JAXRSServerFactoryBean.class.getClassLoader()); |
| Server server = factory.create(); |
| EndpointDescription epd = new EndpointDescription(endpointProps); |
| return new ServerWrapper(epd, server); |
| } finally { |
| Thread.currentThread().setContextClassLoader(oldClassLoader); |
| } |
| } |
| |
| private JAXRSServerFactoryBean createServerFactory(BundleContext callingContext, |
| Map<String, Object> sd, |
| Class<?> iClass, |
| Object serviceBean, |
| String address, |
| Bus bus) { |
| JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean(); |
| factory.setBus(bus); |
| List<UserResource> resources = JaxRSUtils.getModel(callingContext, iClass); |
| if (resources != null) { |
| factory.setModelBeansWithServiceClass(resources, iClass); |
| factory.setServiceBeanObjects(serviceBean); |
| } else { |
| factory.setServiceClass(iClass); |
| factory.setResourceProvider(iClass, new SingletonResourceProvider(serviceBean)); |
| } |
| factory.setAddress(address); |
| List<Object> providers = JaxRSUtils.getProviders(callingContext, sd); |
| if (providers != null && !providers.isEmpty()) { |
| factory.setProviders(providers); |
| } |
| addRsInterceptorsFeaturesProps(factory, callingContext, sd); |
| String location = OsgiUtils.getProperty(sd, Constants.RS_WADL_LOCATION); |
| if (location != null) { |
| URL wadlURL = callingContext.getBundle().getResource(location); |
| if (wadlURL != null) { |
| factory.setDocLocation(wadlURL.toString()); |
| } |
| } |
| return factory; |
| } |
| |
| protected String getPojoAddress(EndpointDescription endpoint, Class<?> iClass) { |
| String address = OsgiUtils.getProperty(endpoint, Constants.RS_ADDRESS_PROPERTY); |
| |
| if (address == null) { |
| address = httpServiceManager.getDefaultAddress(iClass); |
| if (address != null) { |
| LOG.info("Using a default address: " + address); |
| } |
| } |
| return address; |
| } |
| } |