View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2019 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.caravan.jaxrs.publisher.impl;
21  
22  import static io.wcm.caravan.jaxrs.publisher.impl.ServletContainerBridge.isJaxRsGlobal;
23  
24  import javax.ws.rs.Path;
25  import javax.ws.rs.container.PreMatching;
26  import javax.ws.rs.ext.Provider;
27  
28  import org.osgi.framework.Bundle;
29  import org.osgi.framework.BundleContext;
30  import org.osgi.framework.ServiceReference;
31  import org.osgi.util.tracker.ServiceTracker;
32  
33  import io.wcm.caravan.jaxrs.publisher.JaxRsComponent;
34  
35  /**
36   * Tracks {@link JaxRsComponent} instances.
37   */
38  class JaxRsComponentTracker extends ServiceTracker<JaxRsComponent, Object> {
39  
40    private final ServletContainerBridge bridge;
41    private final BundleContext bundleContext;
42    private final Bundle bundle;
43  
44    JaxRsComponentTracker(ServletContainerBridge bridge) {
45      super(bridge.getBundleContext(), JaxRsComponent.class, null);
46      this.bridge = bridge;
47      this.bundleContext = bridge.getBundleContext();
48      this.bundle = bridge.getBundle();
49    }
50  
51    @Override
52    public Object addingService(ServiceReference<JaxRsComponent> reference) {
53      if (isJaxRsGlobal(reference)) {
54        JaxRsComponent serviceInstance = bundle.getBundleContext().getService(reference);
55        if (isJaxRsComponent(serviceInstance)) {
56          ServletContainerBridge.log.debug("Register global component {} for {}", serviceInstance.getClass().getName(), bundle.getSymbolicName());
57          bridge.getGlobalComponents().add(serviceInstance);
58          bridge.markAsDirty();
59        }
60      }
61      else if (reference.getBundle() == bundle) {
62        JaxRsComponent serviceInstance = bundle.getBundleContext().getService(reference);
63        if (isJaxRsComponent(serviceInstance)) {
64          ServletContainerBridge.log.debug("Register component {} for {}", serviceInstance.getClass().getName(), bundle.getSymbolicName());
65          bridge.getLocalComponents().add(serviceInstance);
66          bridge.markAsDirty();
67        }
68      }
69      return super.addingService(reference);
70    }
71  
72    @Override
73    public void removedService(ServiceReference<JaxRsComponent> reference, Object service) {
74      if (isJaxRsGlobal(reference)) {
75        JaxRsComponent serviceInstance = bundle.getBundleContext().getService(reference);
76        if (isJaxRsComponent(serviceInstance)) {
77          ServletContainerBridge.log.debug("Unregister global component {} for {}", serviceInstance.getClass().getName(), bundle.getSymbolicName());
78          bridge.getGlobalComponents().remove(serviceInstance);
79          bundleContext.ungetService(reference);
80          bridge.markAsDirty();
81        }
82      }
83      else if (reference.getBundle() == bundle) {
84        JaxRsComponent serviceInstance = bundle.getBundleContext().getService(reference);
85        if (isJaxRsComponent(serviceInstance)) {
86          ServletContainerBridge.log.debug("Unregister component {} for {}", serviceInstance.getClass().getName(), bundle.getSymbolicName());
87          bridge.getLocalComponents().remove(serviceInstance);
88          bundleContext.ungetService(reference);
89          bridge.markAsDirty();
90        }
91      }
92      super.removedService(reference, service);
93    }
94  
95    private boolean isJaxRsComponent(Object serviceInstance) {
96      return (serviceInstance instanceof JaxRsComponent && hasAnyJaxRsAnnotation(serviceInstance.getClass()));
97    }
98  
99    private boolean hasAnyJaxRsAnnotation(Class<?> clazz) {
100     return clazz.isAnnotationPresent(Path.class)
101         || clazz.isAnnotationPresent(Provider.class)
102         || clazz.isAnnotationPresent(PreMatching.class);
103   }
104 
105 }