/** * Returns the first annotation descriptor matching the given method. * * @param method The method to match. * @param entity The request entity or null. * @return The annotation descriptor. */ private AnnotationInfo getAnnotation(Method method, Representation entity) { if (isAnnotated()) { return AnnotationUtils.getAnnotation( getAnnotations(), method, entity, getMetadataService(), getConverterService()); } return null; }
private static void completeOperationThrows( CollectInfo collectInfo, Operation operation, MethodAnnotationInfo mai, List<? extends IntrospectionHelper> introspectionHelper) { Class<?>[] thrownClasses = mai.getJavaMethod().getExceptionTypes(); if (thrownClasses != null) { for (Class<?> thrownClass : thrownClasses) { ThrowableAnnotationInfo throwableAnnotationInfo = AnnotationUtils.getInstance().getThrowableAnnotationInfo(thrownClass); if (throwableAnnotationInfo != null) { int statusCode = throwableAnnotationInfo.getStatus().getCode(); Response response = new Response(); response.setCode(statusCode); response.setName(Status.valueOf(statusCode).getReasonPhrase()); response.setMessage("Status " + statusCode); Class<?> outputPayloadType = throwableAnnotationInfo.isSerializable() ? thrownClass : StatusInfo.class; TypeInfo outputTypeInfo = null; try { outputTypeInfo = Types.getTypeInfo(outputPayloadType, null); } catch (UnsupportedTypeException e) { LOGGER.warning( "Could not add output payload for exception " + thrownClass + " throws by method " + mai.getJavaMethod() + ". " + e.getMessage()); continue; } RepresentationCollector.addRepresentation( collectInfo, outputTypeInfo, introspectionHelper); PayLoad outputPayLoad = new PayLoad(); outputPayLoad.setType(outputTypeInfo.getRepresentationName()); response.setOutputPayLoad(outputPayLoad); operation.getResponses().add(response); } } } }
/** * Wraps the client resource to proxy calls to the given Java interface into Restlet method calls. * * @param <T> * @param resourceInterface The annotated resource interface class to proxy. * @return The proxy instance. */ @SuppressWarnings("unchecked") public <T> T wrap(Class<? extends T> resourceInterface) { T result = null; // Introspect the interface for Restlet annotations final List<org.restlet.engine.resource.AnnotationInfo> annotations = org.restlet.engine.resource.AnnotationUtils.getAnnotations(resourceInterface); final ClientResource clientResource = this; // Create the client resource proxy java.lang.reflect.InvocationHandler h = new java.lang.reflect.InvocationHandler() { @SuppressWarnings("rawtypes") public Object invoke(Object proxy, java.lang.reflect.Method javaMethod, Object[] args) throws Throwable { Object result = null; if (javaMethod.equals(Object.class.getMethod("toString"))) { // Help debug result = "ClientProxy for resource: " + clientResource; } else if (javaMethod.equals(ClientProxy.class.getMethod("getClientResource"))) { result = clientResource; } else { org.restlet.engine.resource.AnnotationInfo annotation = org.restlet.engine.resource.AnnotationUtils.getAnnotation( annotations, javaMethod); if (annotation != null) { Representation requestEntity = null; boolean isSynchronous = true; if ((args != null) && args.length > 0) { // Checks if the user has defined its own // callback. for (int i = 0; i < args.length; i++) { Object o = args[i]; if (o == null) { requestEntity = null; } else if (Result.class.isAssignableFrom(o.getClass())) { // Asynchronous mode where a callback // object is to be called. isSynchronous = false; // Get the kind of result expected. final Result rCallback = (Result) o; java.lang.reflect.Type[] genericParameterTypes = javaMethod.getGenericParameterTypes(); java.lang.reflect.Type genericParameterType = genericParameterTypes[i]; java.lang.reflect.ParameterizedType parameterizedType = (genericParameterType instanceof java.lang.reflect.ParameterizedType) ? (java.lang.reflect.ParameterizedType) genericParameterType : null; final Class<?> actualType = (parameterizedType.getActualTypeArguments()[0] instanceof Class<?>) ? (Class<?>) parameterizedType.getActualTypeArguments()[0] : null; // Define the callback Uniform callback = new Uniform() { public void handle(Request request, Response response) { if (response.getStatus().isError()) { rCallback.onFailure(new ResourceException(response.getStatus())); } else { if (actualType != null) { rCallback.onSuccess(toObject(response.getEntity(), actualType)); } else { rCallback.onSuccess(null); } } } }; setOnResponse(callback); } else { requestEntity = toRepresentation(args[i], null); } } } // Clone the prototype request Request request = createRequest(getRequest()); // The Java method was annotated request.setMethod(annotation.getRestletMethod()); // Set the entity request.setEntity(requestEntity); // Updates the client preferences List<org.restlet.representation.Variant> responseVariants = annotation.getResponseVariants(getMetadataService(), getConverterService()); if (responseVariants != null) { request.setClientInfo(new ClientInfo(responseVariants)); } // Effectively handle the call Response response = handle(request); // Handle the response if (isSynchronous) { if (response.getStatus().isError()) { throw new ResourceException(response.getStatus()); } if (!annotation.getJavaOutputType().equals(void.class)) { result = toObject( (response == null ? null : response.getEntity()), annotation.getJavaOutputType()); } } } } return result; } }; // Instantiate our dynamic proxy result = (T) java.lang.reflect.Proxy.newProxyInstance( org.restlet.engine.Engine.getInstance().getClassLoader(), new Class<?>[] {ClientProxy.class, resourceInterface}, h); return result; }
/** * Returns the annotation descriptors. * * @return The annotation descriptors. */ private List<AnnotationInfo> getAnnotations() { return isAnnotated() ? AnnotationUtils.getAnnotations(getClass()) : null; }
public static void collectResource( CollectInfo collectInfo, ServerResource sr, String basePath, ChallengeScheme scheme, List<? extends IntrospectionHelper> introspectionHelper) { Resource resource = getResource(collectInfo, sr, basePath, scheme); // add operations ArrayList<Operation> operations = new ArrayList<>(); List<AnnotationInfo> annotations = sr.isAnnotated() ? AnnotationUtils.getInstance().getAnnotations(sr.getClass()) : null; if (annotations != null) { for (AnnotationInfo annotationInfo : annotations) { if (annotationInfo instanceof MethodAnnotationInfo) { MethodAnnotationInfo methodAnnotationInfo = (MethodAnnotationInfo) annotationInfo; Method method = methodAnnotationInfo.getRestletMethod(); Operation operation = getOperationFromMethod(method); if (StringUtils.isNullOrEmpty(operation.getName())) { operation.setName(methodAnnotationInfo.getJavaMethod().getName()); } completeOperation(collectInfo, operation, methodAnnotationInfo, sr, introspectionHelper); for (IntrospectionHelper helper : introspectionHelper) { List<Class<?>> representationClasses = helper.processOperation( resource, operation, sr.getClass(), methodAnnotationInfo.getJavaMethod()); if (representationClasses != null && !representationClasses.isEmpty()) { for (Class<?> representationClazz : representationClasses) { TypeInfo typeInfo; try { typeInfo = Types.getTypeInfo(representationClazz, null); } catch (UnsupportedTypeException e) { LOGGER.warning( "Could not add representation class " + representationClazz.getName() + ". " + e.getMessage()); continue; } RepresentationCollector.addRepresentation( collectInfo, typeInfo, introspectionHelper); } } } operations.add(operation); } } if (!operations.isEmpty()) { sortOperationsByMethod(operations); resource.setOperations(operations); addSectionsForResource(collectInfo, resource); collectInfo.addResource(resource); } else { LOGGER.warning("Resource " + resource.getName() + " has no methods."); } } else { LOGGER.warning("Resource " + resource.getName() + " has no methods."); } for (IntrospectionHelper helper : introspectionHelper) { helper.processResource(resource, sr.getClass()); } }