package org.jboss.resteasy.wadl; import org.jboss.resteasy.wadl.i18n.LogMessages; import org.jboss.resteasy.wadl.i18n.Messages; import org.jboss.resteasy.wadl.jaxb.*; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.namespace.QName; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import static org.jboss.resteasy.wadl.ResteasyWadlMethodParamMetaData.MethodParamType.*; /** * @author <a href="mailto:l.weinan@gmail.com">Weinan Li</a> */ public class ResteasyWadlWriter { public byte[] getBytes(String base, Map<String, ResteasyWadlServiceRegistry> serviceRegistries) throws JAXBException { StringWriter stringWriter = getStringWriter(base, serviceRegistries); return stringWriter.toString().getBytes(); } public StringWriter getStringWriter(String base, Map<String, ResteasyWadlServiceRegistry> serviceRegistries) throws JAXBException { ObjectFactory factory = new ObjectFactory(); Application app = factory.createApplication(); JAXBContext context = JAXBContext.newInstance(Application.class); Marshaller marshaller = context.createMarshaller(); for (Map.Entry<String, ResteasyWadlServiceRegistry> entry : serviceRegistries.entrySet()) { String uri = base; if (entry.getKey() != null) uri += entry.getKey(); Resources resources = new Resources(); resources.setBase(uri); app.getResources().add(resources); processWadl(entry.getValue(), resources); } StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(app, writer); return stringWriter; } private void processWadl(ResteasyWadlServiceRegistry serviceRegistry, Resources root) throws JAXBException { for (Map.Entry<String, ResteasyWadlResourceMetaData> resourceMetaDataEntry : serviceRegistry.getResources().entrySet()) { LogMessages.LOGGER.debug(Messages.MESSAGES.path(resourceMetaDataEntry.getKey())); Resource resourceClass = new Resource(); resourceClass.setPath(resourceMetaDataEntry.getKey()); root.getResource().add(resourceClass); for (ResteasyWadlMethodMetaData methodMetaData : resourceMetaDataEntry.getValue().getMethodsMetaData()) { Method method = new Method(); // First we need to check whether @Path annotation exists in a method. // If the @Path annotation exists, we need to create a resource for it. if (methodMetaData.getMethodUri() != null) { Resource methodResource = new Resource(); methodResource.setPath(methodMetaData.getMethodUri()); methodResource.getMethodOrResource().add(method); resourceClass.getMethodOrResource().add(methodResource); // add params into method resource processMethodParams(methodResource, methodMetaData, method); } else { // register method into resource resourceClass.getMethodOrResource().add(method); // we need to check whether the method have parameters or not. // params belong to the resource of the method processMethodParams(resourceClass, methodMetaData, method); } // method name = {GET, POST, DELETE, ...} for (String name : methodMetaData.getHttpMethods()) { method.setName(name); } // method id = method name method.setId(methodMetaData.getMethod().getName()); // process response of method Response response = createResponse(serviceRegistry, methodMetaData); method.getResponse().add(response); } } for (ResteasyWadlServiceRegistry subService : serviceRegistry.getLocators()) processWadl(subService, root); } private void processMethodParams(Resource currentResourceClass, ResteasyWadlMethodMetaData methodMetaData, Method method) { // process method parameters Request request = new Request(); for (ResteasyWadlMethodParamMetaData paramMetaData : methodMetaData.getParameters()) { Param param = createParam(currentResourceClass, method, paramMetaData, request); } } private Response createResponse(ResteasyWadlServiceRegistry serviceRegistry, ResteasyWadlMethodMetaData methodMetaData) { Response response = new Response(); Class _type = methodMetaData.getMethod().getReturnType(); Type _generic = methodMetaData.getMethod().getGenericReturnType(); MediaType mediaType = MediaType.WILDCARD_TYPE; if (methodMetaData.getProduces() != null) { for (String produces : methodMetaData.getProduces()) { for (String _produces : produces.split(",")) { mediaType = MediaType.valueOf(_produces); if (mediaType == null) { mediaType = serviceRegistry.getProviderFactory().getConcreteMediaTypeFromMessageBodyWriters(_type, _generic, methodMetaData.getMethod().getAnnotations(), MediaType.WILDCARD_TYPE); if (mediaType == null) mediaType = MediaType.WILDCARD_TYPE; } Representation representation = createRepresentation(mediaType); response.getRepresentation().add(representation); } } } return response; } private Param createParam(Resource currentResourceClass, Method method, ResteasyWadlMethodParamMetaData paramMetaData, Request request) { Param param = new Param(); setType(param, paramMetaData); // All the method's @PathParam belong to resource if (paramMetaData.getParamType().equals(PATH_PARAMETER)) { param.setStyle(ParamStyle.TEMPLATE); param.setName(paramMetaData.getParamName()); currentResourceClass.getParam().add(param); } else if (paramMetaData.getParamType().equals(COOKIE_PARAMETER)) { param.setStyle(ParamStyle.HEADER); request.getParam().add(param); param.setName("Cookie"); param.setPath(paramMetaData.getParamName()); method.setRequest(request); } else if (paramMetaData.getParamType().equals(HEADER_PARAMETER)) { param.setStyle(ParamStyle.HEADER); request.getParam().add(param); param.setName(paramMetaData.getParamName()); method.setRequest(request); } else if (paramMetaData.getParamType().equals(MATRIX_PARAMETER)) { param.setStyle(ParamStyle.MATRIX); param.setName(paramMetaData.getParamName()); currentResourceClass.getParam().add(param); } else if (paramMetaData.getParamType().equals(QUERY_PARAMETER)) { param.setStyle(ParamStyle.QUERY); request.getParam().add(param); param.setName(paramMetaData.getParamName()); method.setRequest(request); } else if (paramMetaData.getParamType().equals(FORM_PARAMETER)) { param.setStyle(ParamStyle.QUERY); Representation formRepresentation = createFormRepresentation(request); param.setName(paramMetaData.getParamName()); formRepresentation.getParam().add(param); method.setRequest(request); } else if (paramMetaData.getParamType().equals(FORM)) { param.setStyle(ParamStyle.QUERY); Representation formRepresentation = createFormRepresentation(request); param.setName(paramMetaData.getParamName()); formRepresentation.getParam().add(param); method.setRequest(request); } return param; } private Representation createFormRepresentation(Request request) { Representation formRepresentation = getRepresentationByMediaType(request.getRepresentation(), MediaType.APPLICATION_FORM_URLENCODED_TYPE); if (formRepresentation == null) { formRepresentation = createRepresentation(MediaType.APPLICATION_FORM_URLENCODED_TYPE); request.getRepresentation().add(formRepresentation); } return formRepresentation; } private Representation createRepresentation(MediaType mediaType) { Representation representation; representation = new Representation(); representation.setMediaType(mediaType.toString()); return representation; } private Representation getRepresentationByMediaType( final List<Representation> representations, MediaType mediaType) { for (Representation representation : representations) { if (mediaType.toString().equals(representation.getMediaType())) { return representation; } } return null; } private void setType(Param param, ResteasyWadlMethodParamMetaData paramMetaData) { if (paramMetaData.getType().equals(int.class) || paramMetaData.getType().equals(Integer.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "int", "xs")); } else if (paramMetaData.getType().equals(boolean.class) || paramMetaData.getType().equals(Boolean.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "boolean", "xs")); } else if (paramMetaData.getType().equals(long.class) || paramMetaData.getType().equals(Long.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "long", "xs")); } else if (paramMetaData.getType().equals(short.class) || paramMetaData.getType().equals(Short.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "short", "xs")); } else if (paramMetaData.getType().equals(byte.class) || paramMetaData.getType().equals(Byte.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "byte", "xs")); } else if (paramMetaData.getType().equals(float.class) || paramMetaData.getType().equals(Float.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "float", "xs")); } else if (paramMetaData.getType().equals(double.class) || paramMetaData.getType().equals(Double.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "double", "xs")); } else if (paramMetaData.getType().equals(Map.class) || paramMetaData.getType().equals(List.class)) { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "complex", "xs")); } else { param.setType(new QName("http://www.w3.org/2001/XMLSchema", "string", "xs")); } } }