/** * Copyright 2008 - 2009 Pro-Netics S.P.A. * * Licensed 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 it.pronetics.madstore.server.jaxrs.atom.resolver; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.UriBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Resolve the resource uri for resource classes with logical names annotated through {@link ResourceUriFor}. * * @author Sergio Bossa */ public class ResourceResolver { private static final Logger LOG = LoggerFactory.getLogger(ResourceResolver.class); private final Map<String, Class> resourceClasses; public ResourceResolver(Map<String, Class> resourceClasses) { this.resourceClasses = resourceClasses; } public URL resolveResourceUriFor(String resourceName, String uriBase, Object... uriParameters) { Class resourceClass = resourceClasses.get(resourceName); if (resourceClass != null) { List<Method> resourceUriMethodsStack = new LinkedList<Method>(); Class resourceEntryPoint = resourceClass; Method resourceUriMethod = pushAnnotatedResourceMethod(resourceClass, resourceName, resourceUriMethodsStack); ResourceUriFor resourceUriAnnotation = resourceUriMethod.getAnnotation(ResourceUriFor.class); if (!resourceUriAnnotation.locator().equals(Void.class)) { String locatedResource = resourceName; Class locatorResource = resourceUriAnnotation.locator(); do { resourceUriMethod = pushAnnotatedLocatorMethod(locatorResource, locatedResource, resourceUriMethodsStack); resourceUriAnnotation = resourceUriMethod.getAnnotation(ResourceUriFor.class); resourceEntryPoint = locatorResource; locatedResource = resourceUriAnnotation.resource(); locatorResource = resourceUriAnnotation.locator(); } while (!locatorResource.equals(Void.class)); } URL resourceUrl = buildResourceUrl(uriBase, resourceEntryPoint, resourceUriMethodsStack, uriParameters); return resourceUrl; } else { throw new IllegalStateException("No resource class with name " + resourceName); } } public String resolveResourceIdFor(String uriBase, String resourceName, String... resourceParameters) { String tagPrefix = "tag"; String strippedUriBase = uriBase.replaceFirst("\\w+\\://", ""); if (strippedUriBase.indexOf("/") != -1) { strippedUriBase = strippedUriBase.substring(0, strippedUriBase.indexOf("/")); } if (strippedUriBase.indexOf(":") != -1) { strippedUriBase = strippedUriBase.substring(0, strippedUriBase.indexOf(":")); } StringBuilder idBuilder = new StringBuilder(); idBuilder.append(tagPrefix).append(":").append(strippedUriBase).append(":").append(resourceName); if (resourceParameters.length > 0) { for (String parameter : resourceParameters) { idBuilder.append(":").append(parameter); } } return idBuilder.toString(); } private Method pushAnnotatedResourceMethod(Class resourceClass, String resourceName, List<Method> resourceUriMethodsStack) { Method[] methods = resourceClass.getMethods(); Method annotatedMethod = null; for (Method method : methods) { ResourceUriFor annotation = method.getAnnotation(ResourceUriFor.class); if (annotation != null && annotation.resource().equals(resourceName)) { annotatedMethod = method; break; } } if (annotatedMethod != null) { resourceUriMethodsStack.add(annotatedMethod); return annotatedMethod; } else { throw new IllegalStateException( "No method with " + ResourceUriFor.class + " annotation found for class " + resourceClass + " and resource " + resourceName); } } private Method pushAnnotatedLocatorMethod(Class locatorResource, String locatedResource, List<Method> resourceUriMethodsStack) { Method[] methods = locatorResource.getMethods(); Method annotatedMethod = null; for (Method method : methods) { ResourceUriFor annotation = method.getAnnotation(ResourceUriFor.class); if (annotation != null && Arrays.asList(annotation.subResources()).contains(locatedResource)) { annotatedMethod = method; break; } } if (annotatedMethod != null) { resourceUriMethodsStack.add(annotatedMethod); return annotatedMethod; } else { throw new IllegalStateException( "No method with " + ResourceUriFor.class + " annotation found for class " + locatorResource + " and resource " + locatedResource); } } private URL buildResourceUrl(String baseUrl, Class resourceEntryPoint, List<Method> resourceUrlMethodsStack, Object[] urlParameters) { try { URL resourceUrl = null; UriBuilder builder = UriBuilder.fromUri(baseUrl).path(resourceEntryPoint); for (int i = resourceUrlMethodsStack.size() - 1; i >= 0; i--) { Method resourceUrlMethod = resourceUrlMethodsStack.get(i); builder.path(resourceUrlMethod); } resourceUrl = builder.build(urlParameters).toURL(); return resourceUrl; } catch (MalformedURLException ex) { LOG.error(ex.getMessage(), ex); throw new WebApplicationException(); } } }