package org.springframework.roo.rest.publisher; import javax.ws.rs.Path; import javax.ws.rs.core.Feature; import javax.ws.rs.ext.Provider; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; /** * Track for all services and check if each one is annotated with {@link Path}, * {@link Provider} or it implements {@link Feature}. If true this tracker * publish the resource automatically. * <p/> * If you want a resource won't be published set the property * {@link AnyServiceFilter#PUBLISH} to {@code false}. * * @author Enrique Ruiz at DISID Corporation S.L. * @since 2.0 */ @SuppressWarnings({"unchecked", "rawtypes"}) public class ResourceTracker extends ServiceTracker { private final BundleContext bundleContext; private final JAXRSApplication jaxrsApplication; public ResourceTracker(BundleContext bc, JAXRSApplication jaxrsApp) { super(bc, new AnyServiceFilter(bc).getFilter(), null); this.bundleContext = bc; this.jaxrsApplication = jaxrsApp; } @Override public Object addingService(ServiceReference ref) { Object service = super.addingService(ref); return doAddService(ref, service); } /** * Check if given service is a JAX-RS resource and add it to the * JAX-RS application. * * @param ref * @param service * @return */ private Object doAddService(ServiceReference ref, Object service) { Object result; if (isResource(service)) { result = jaxrsApplication.addResource(ref); } else { bundleContext.ungetService(ref); result = null; } return result; } @Override public void removedService(ServiceReference ref, Object service) { // connector.removeResource( service ); super.removedService(ref, service); } @Override public void modifiedService(ServiceReference ref, Object service) { // connector.removeResource( service ); doAddService(ref, service); } /** * Check if the given service is a JAX-RS resource, that is, it is * annotated with {@link Path}, {@link Provider} or it implements * {@link Feature} * * @param service * @return */ private boolean isResource(Object service) { boolean result = service != null && (hasRegisterableAnnotation(service) || service instanceof Feature); return result; } /** * Check if the given service or any of the interfaces it implements * are annotated {@link Path} or {@link Provider}. * * @param service * @return */ private boolean hasRegisterableAnnotation(Object service) { boolean result = isRegisterableAnnotationPresent(service.getClass()); if (!result) { Class<?>[] interfaces = service.getClass().getInterfaces(); for (Class<?> type : interfaces) { result = result || isRegisterableAnnotationPresent(type); } } return result; } /** * Check if the given class is annotated with {@link Path} or * {@link Provider}. * * @param type class to check * @return true/false */ private boolean isRegisterableAnnotationPresent(Class<?> type) { boolean result = type.isAnnotationPresent(Path.class) || type.isAnnotationPresent(Provider.class); return result; } }