Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 037F7200C25 for ; Fri, 24 Feb 2017 17:41:51 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 024F2160B79; Fri, 24 Feb 2017 16:41:51 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id DC224160B83 for ; Fri, 24 Feb 2017 17:41:49 +0100 (CET) Received: (qmail 77874 invoked by uid 500); 24 Feb 2017 16:41:49 -0000 Mailing-List: contact commits-help@aries.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aries.apache.org Delivered-To: mailing list commits@aries.apache.org Received: (qmail 77252 invoked by uid 99); 24 Feb 2017 16:41:48 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Feb 2017 16:41:48 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 7534EDFFD7; Fri, 24 Feb 2017 16:41:48 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: csierra@apache.org To: commits@aries.apache.org Date: Fri, 24 Feb 2017 16:41:56 -0000 Message-Id: In-Reply-To: <8e0abbe534cb411ab53f0b541633ccf6@git.apache.org> References: <8e0abbe534cb411ab53f0b541633ccf6@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [09/12] aries-jax-rs-whiteboard git commit: Add support for services lifecycle archived-at: Fri, 24 Feb 2017 16:41:51 -0000 Add support for services lifecycle Project: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/repo Commit: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/commit/2bac01c8 Tree: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/tree/2bac01c8 Diff: http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/diff/2bac01c8 Branch: refs/heads/master Commit: 2bac01c8f35d79686c0d28c0b86eff137998d2fc Parents: 62b53f9 Author: Carlos Sierra Authored: Thu Feb 23 15:44:41 2017 +0100 Committer: Raymond Auge Committed: Fri Feb 24 10:11:03 2017 -0500 ---------------------------------------------------------------------- jax-rs.itests/pom.xml | 2 +- jax-rs.itests/src/main/java/test/JaxrsTest.java | 97 +++++++++++++++- .../java/test/types/TestAddonLifecycle.java | 31 +++++ jax-rs.whiteboard/pom.xml | 2 +- .../activator/CXFJaxRsBundleActivator.java | 114 ++++++++++++++++--- .../internal/CXFJaxRsServiceRegistrator.java | 68 +++++------ 6 files changed, 260 insertions(+), 54 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.itests/pom.xml ---------------------------------------------------------------------- diff --git a/jax-rs.itests/pom.xml b/jax-rs.itests/pom.xml index 59e4b50..d5147a1 100644 --- a/jax-rs.itests/pom.xml +++ b/jax-rs.itests/pom.xml @@ -46,7 +46,7 @@ org.osgi org.osgi.core - 5.0.0 + 6.0.0 org.osgi http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.itests/src/main/java/test/JaxrsTest.java ---------------------------------------------------------------------- diff --git a/jax-rs.itests/src/main/java/test/JaxrsTest.java b/jax-rs.itests/src/main/java/test/JaxrsTest.java index f5b434b..20f8910 100644 --- a/jax-rs.itests/src/main/java/test/JaxrsTest.java +++ b/jax-rs.itests/src/main/java/test/JaxrsTest.java @@ -21,11 +21,15 @@ import java.util.Dictionary; import java.util.Hashtable; import org.junit.Test; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.PrototypeServiceFactory; +import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceRegistration; import test.types.TestAddon; +import test.types.TestAddonLifecycle; import test.types.TestApplication; import test.types.TestFilter; @@ -36,6 +40,7 @@ import javax.ws.rs.core.Application; import javax.ws.rs.core.Response; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; @@ -341,6 +346,60 @@ public class JaxrsTest { } @Test + public void testStandaloneEndPointSingletonLifecycle() { + Client client = createClient(); + + WebTarget webTarget = client. + target("http://localhost:8080"). + path("/test-addon"); + + ServiceRegistration serviceRegistration = null; + + try { + serviceRegistration = registerAddonLifecycle( + true, "osgi.jaxrs.resource.base", "/test-addon"); + + String first = webTarget.request().get().readEntity(String.class); + + String second = webTarget.request().get().readEntity(String.class); + + assertEquals("This should be equal", first, second); + } + finally { + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + } + } + + @Test + public void testStandaloneEndPointPrototypeLifecycle() { + Client client = createClient(); + + WebTarget webTarget = client. + target("http://localhost:8080"). + path("/test-addon"); + + ServiceRegistration serviceRegistration = null; + + try { + serviceRegistration = registerAddonLifecycle( + false, "osgi.jaxrs.resource.base", "/test-addon"); + + String first = webTarget.request().get().readEntity(String.class); + + String second = webTarget.request().get().readEntity(String.class); + + assertNotEquals("This should be different", first, second); + } + finally { + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + } + } + + @Test public void testStandaloneFilter() { Client client = createClient(); @@ -512,7 +571,6 @@ public class JaxrsTest { } private ServiceRegistration registerAddon(Object ... keyValues) { - TestAddon testAddon = new TestAddon(); Dictionary properties = new Hashtable<>(); @@ -525,6 +583,43 @@ public class JaxrsTest { Object.class, testAddon, properties); } + private ServiceRegistration registerAddonLifecycle( + boolean singleton, Object ... keyValues) { + + Dictionary properties = new Hashtable<>(); + + for (int i = 0; i < keyValues.length; i = i + 2) { + properties.put(keyValues[i].toString(), keyValues[i + 1]); + } + + if (singleton) { + return bundleContext.registerService( + Object.class, new TestAddonLifecycle(), properties); + } + else { + PrototypeServiceFactory prototypeServiceFactory = + new PrototypeServiceFactory() { + @Override + public Object getService( + Bundle bundle, ServiceRegistration registration) { + + return new TestAddonLifecycle(); + } + + @Override + public void ungetService( + Bundle bundle, ServiceRegistration registration, + Object service) { + + } + }; + + return bundleContext.registerService( + Object.class, (ServiceFactory)prototypeServiceFactory, + properties); + } + } + private ServiceRegistration registerApplication() { TestApplication testApplication = new TestApplication(); http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.itests/src/main/java/test/types/TestAddonLifecycle.java ---------------------------------------------------------------------- diff --git a/jax-rs.itests/src/main/java/test/types/TestAddonLifecycle.java b/jax-rs.itests/src/main/java/test/types/TestAddonLifecycle.java new file mode 100644 index 0000000..f271dc7 --- /dev/null +++ b/jax-rs.itests/src/main/java/test/types/TestAddonLifecycle.java @@ -0,0 +1,31 @@ +/* + * 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 test.types; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +public class TestAddonLifecycle { + + @GET + @Path("/") + public String sayHello() { + return this.toString(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.whiteboard/pom.xml ---------------------------------------------------------------------- diff --git a/jax-rs.whiteboard/pom.xml b/jax-rs.whiteboard/pom.xml index 132eb32..b3db5cd 100644 --- a/jax-rs.whiteboard/pom.xml +++ b/jax-rs.whiteboard/pom.xml @@ -80,7 +80,7 @@ org.osgi org.osgi.core - 5.0.0 + 6.0.0 org.osgi http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java ---------------------------------------------------------------------- diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java index 8618122..23d0427 100644 --- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java +++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/activator/CXFJaxRsBundleActivator.java @@ -19,6 +19,7 @@ package org.apache.aries.jax.rs.whiteboard.activator; import javax.servlet.Servlet; import javax.ws.rs.core.Application; +import javax.ws.rs.ext.Provider; import javax.ws.rs.ext.RuntimeDelegate; import org.apache.aries.jax.rs.whiteboard.internal.CXFJaxRsServiceRegistrator; @@ -28,10 +29,13 @@ import org.apache.aries.osgi.functional.OSGiResult; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.bus.CXFBusFactory; +import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; +import org.apache.cxf.message.Message; import org.apache.cxf.transport.servlet.CXFNonSpringServlet; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; +import org.osgi.framework.ServiceObjects; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.framework.wiring.BundleWiring; @@ -68,6 +72,15 @@ public class CXFJaxRsBundleActivator implements BundleActivator { )); } + private static OSGi> serviceObjects( + ServiceReference serviceReference) { + + return + bundleContext().flatMap(bundleContext -> + just(bundleContext.getServiceObjects(serviceReference)) + ); + } + private static OSGi cxfRegistrator( Bus bus, Application application, Map props) { @@ -129,7 +142,7 @@ public class CXFJaxRsBundleActivator implements BundleActivator { OSGi extensions = serviceReferences(getExtensionFilter()).flatMap(ref -> waitForExtensionDependencies(ref, - safeRegisterEndpoint(ref, defaultServiceRegistrator) + safeRegisterExtension(ref, defaultServiceRegistrator) ) ); @@ -142,12 +155,44 @@ public class CXFJaxRsBundleActivator implements BundleActivator { flatMap(applicationFilter -> services(CXFJaxRsServiceRegistrator.class, applicationFilter). flatMap(registrator -> - safeRegisterEndpoint(ref, registrator) + testProvider(ref).flatMap(isProvider -> { + if (isProvider) { + return safeRegisterExtension(ref, registrator); + } + else { + return safeRegisterEndpoint(ref, registrator); + } + }) ))); _applicationSingletonsResult = applicationSingletons.run(bundleContext); } + private OSGi testProvider(ServiceReference serviceReference) { + return bundleContext().flatMap(bundleContext -> { + Object service = bundleContext.getService(serviceReference); + Class serviceClass = service.getClass(); + if (serviceClass.isAnnotationPresent(Provider.class)) { + return just(Boolean.TRUE); + } + else { + return just(Boolean.FALSE); + } + }); + } + + private OSGi safeRegisterExtension( + ServiceReference ref, + CXFJaxRsServiceRegistrator registrator) { + + return + service(ref).flatMap(extension -> + onClose(() -> registrator.removeProvider(extension)). + foreach(ign -> + registrator.addProvider(extension) + )); + } + /** * Initialize instance so it is never looked up again * @param bundleContext @@ -195,20 +240,22 @@ public class CXFJaxRsBundleActivator implements BundleActivator { return program; } - private OSGi safeRegisterEndpoint( - ServiceReference ref, CXFJaxRsServiceRegistrator registrator) { + private OSGi safeRegisterEndpoint( + ServiceReference ref, CXFJaxRsServiceRegistrator registrator) { return bundleContext().flatMap(bundleContext -> - service(ref).flatMap(service -> - onClose(() -> unregisterEndpoint(registrator, service)).then( - registerEndpoint(ref, registrator, service) - ))); + serviceObjects(ref).flatMap(service -> + registerEndpoint(ref, registrator, service). + flatMap(serviceInformation -> + onClose( + () -> unregisterEndpoint(registrator, serviceInformation))))); } - private OSGi registerEndpoint( + private OSGi registerEndpoint( ServiceReference ref, - CXFJaxRsServiceRegistrator registrator, Object service) { + CXFJaxRsServiceRegistrator registrator, + ServiceObjects serviceObjects) { Thread thread = Thread.currentThread(); ClassLoader contextClassLoader = thread.getContextClassLoader(); @@ -216,6 +263,8 @@ public class CXFJaxRsBundleActivator implements BundleActivator { getClassLoader(); Object resourceBaseObject = ref.getProperty("osgi.jaxrs.resource.base"); + ResourceProvider resourceProvider = getResourceProvider(serviceObjects); + String resourceBase; if (resourceBaseObject == null) { @@ -226,18 +275,55 @@ public class CXFJaxRsBundleActivator implements BundleActivator { } try { thread.setContextClassLoader(classLoader); - registrator.add(new ServiceInformation(resourceBase, "", service)); + ServiceInformation serviceInformation = new ServiceInformation( + resourceBase, resourceProvider); + registrator.add(serviceInformation); + return just(serviceInformation); } finally { thread.setContextClassLoader(contextClassLoader); } - return just(service); + } + + private ResourceProvider getResourceProvider( + ServiceObjects serviceObjects) { + + ResourceProvider resourceProvider; + T service = serviceObjects.getService(); + Class serviceClass = service.getClass(); + + resourceProvider = new ResourceProvider() { + + @Override + public Object getInstance(Message m) { + return serviceObjects.getService(); + } + + @Override + public void releaseInstance(Message m, Object o) { + serviceObjects.ungetService((T)o); + } + + @Override + public Class getResourceClass() { + return serviceClass; + } + + @Override + public boolean isSingleton() { + return false; + } + }; + + serviceObjects.ungetService(service); + return resourceProvider; } private void unregisterEndpoint( - CXFJaxRsServiceRegistrator registrator, Object service) { + CXFJaxRsServiceRegistrator registrator, + ServiceInformation serviceInformation) { - registrator.remove(service); + registrator.remove(serviceInformation); } private ServiceRegistration registerCXFServletService(Bus bus) { http://git-wip-us.apache.org/repos/asf/aries-jax-rs-whiteboard/blob/2bac01c8/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java ---------------------------------------------------------------------- diff --git a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java index 683cb0f..e6170cb 100644 --- a/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java +++ b/jax-rs.whiteboard/src/main/java/org/apache/aries/jax/rs/whiteboard/internal/CXFJaxRsServiceRegistrator.java @@ -20,19 +20,17 @@ package org.apache.aries.jax.rs.whiteboard.internal; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import javax.ws.rs.core.Application; -import javax.ws.rs.ext.Provider; import javax.ws.rs.ext.RuntimeDelegate; import org.apache.cxf.Bus; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean; -import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider; +import org.apache.cxf.jaxrs.lifecycle.ResourceProvider; import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.jaxrs.model.URITemplate; import org.apache.cxf.jaxrs.provider.json.JSONProvider; @@ -89,38 +87,40 @@ public class CXFJaxRsServiceRegistrator { return; } - Object object = serviceInformation.getService(); + _services.add(serviceInformation); - if (object.getClass().isAnnotationPresent(Provider.class)) { - _providers.add(object); - } else { - _services.add(serviceInformation); - } rewire(); } - public void remove(Object object) { + public void remove(ServiceInformation serviceInformation) { if (_closed) { return; } - if (object.getClass().isAnnotationPresent(Provider.class)) { - _providers.remove(object); - } - else { - Iterator iterator = _services.iterator(); - while (iterator.hasNext()) { - ServiceInformation next = iterator.next(); + _services.remove(serviceInformation); - if (next.getService() == object) { - iterator.remove(); - } - } + rewire(); + } + + public void addProvider(Object provider) { + if (_closed) { + return; } + _providers.add(provider); + rewire(); } + public void removeProvider(Object provider) { + if (_closed) { + return; + } + + _providers.remove(provider); + + rewire(); + } protected synchronized void rewire() { if (_server != null) { _server.destroy(); @@ -159,18 +159,18 @@ public class CXFJaxRsServiceRegistrator { jaxRsServerFactoryBean.getServiceFactory(); for (ServiceInformation serviceInformation : _services) { - Object service = serviceInformation.getService(); - SingletonResourceProvider rp = new SingletonResourceProvider( - service, true); + ResourceProvider resourceProvider = + serviceInformation.getResourceProvider(); - jaxRsServerFactoryBean.setResourceProvider(rp); + jaxRsServerFactoryBean.setResourceProvider(resourceProvider); List classResourceInfo = serviceFactory.getClassResourceInfo(); for (ClassResourceInfo resourceInfo : classResourceInfo) { - if (resourceInfo.getServiceClass() == service.getClass()) { + if (resourceInfo.getServiceClass() == + resourceProvider.getResourceClass()) { URITemplate uriTemplate = resourceInfo.getURITemplate(); resourceInfo.setURITemplate( new URITemplate( @@ -203,27 +203,21 @@ public class CXFJaxRsServiceRegistrator { public static class ServiceInformation { private final String prefixPath; - private final String scope; - private final Object service; + private final ResourceProvider _resourceProvider; public ServiceInformation( - String prefixPath, String scope, Object service) { + String prefixPath, ResourceProvider resourceProvider) { this.prefixPath = prefixPath; - this.scope = scope; - this.service = service; + this._resourceProvider = resourceProvider; } public String getPrefixPath() { return prefixPath; } - public String getScope() { - return scope; - } - - public Object getService() { - return service; + public ResourceProvider getResourceProvider() { + return _resourceProvider; } }