All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cxf.jaxrs.ext.codegen.CodeGeneratorProvider Maven / Gradle / Ivy

There is a newer version: 2.7.18
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 org.apache.cxf.jaxrs.ext.codegen;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.MatrixParam;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.namespace.QName;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;

import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.PackageUtils;
import org.apache.cxf.common.util.ReflectionInvokationHandler;
import org.apache.cxf.common.xmlschema.XmlSchemaConstants;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.helpers.FileUtils;
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.jaxb.JAXBUtils;
import org.apache.cxf.jaxb.JAXBUtils.JCodeModel;
import org.apache.cxf.jaxb.JAXBUtils.S2JJAXBModel;
import org.apache.cxf.jaxb.JAXBUtils.SchemaCompiler;
import org.apache.cxf.jaxrs.ext.RequestHandler;
import org.apache.cxf.jaxrs.model.ClassResourceInfo;
import org.apache.cxf.jaxrs.model.ProviderInfo;
import org.apache.cxf.jaxrs.model.wadl.WadlGenerator;
import org.apache.cxf.jaxrs.provider.ProviderFactory;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.message.Message;

public class CodeGeneratorProvider implements RequestHandler {
    public static final String CODE_QUERY = "_code";
    public static final String LANGUAGE_QUERY = "_lang";
    public static final String OS_QUERY = "_os";
    public static final String SOURCE_QUERY = "_source";
    public static final String CODE_TYPE_QUERY = "_codeType";
    public static final String CODE_TYPE_GRAMMAR = "grammar";
    public static final String CODE_TYPE_PROXY = "proxy";
    public static final String CODE_TYPE_WEB = "web";
    
    private static final Logger LOG = LogUtils.getL7dLogger(CodeGeneratorProvider.class);
    private static final Set SUPPORTED_LANGUAGES = new HashSet(
        Arrays.asList(new String[]{"java"}));
    
    private static final File TMPDIR = FileUtils.getDefaultTempDir();
    private static final String TAB = "    "; 
    
    private static final Map> HTTP_METHOD_ANNOTATIONS;
    private static final Map> PARAM_ANNOTATIONS;
    
    static {
        HTTP_METHOD_ANNOTATIONS = new HashMap>();
        HTTP_METHOD_ANNOTATIONS.put("get", GET.class);
        HTTP_METHOD_ANNOTATIONS.put("put", PUT.class);
        HTTP_METHOD_ANNOTATIONS.put("post", POST.class);
        HTTP_METHOD_ANNOTATIONS.put("delete", DELETE.class);
        HTTP_METHOD_ANNOTATIONS.put("head", HEAD.class);
        HTTP_METHOD_ANNOTATIONS.put("options", OPTIONS.class);
        
        PARAM_ANNOTATIONS = new HashMap>();
        PARAM_ANNOTATIONS.put("template", PathParam.class);
        PARAM_ANNOTATIONS.put("header", HeaderParam.class);
        PARAM_ANNOTATIONS.put("query", QueryParam.class);
        PARAM_ANNOTATIONS.put("matrix", MatrixParam.class);
    }

    private Comparator importsComparator;
    private UriInfo ui;
    private boolean generateInterfaces = true;
    
    
    @Context
    public void setUriInfo(UriInfo uriInfo) {
        this.ui = uriInfo;
    }
    
    public Response handleRequest(Message m, ClassResourceInfo resourceClass) {
        
        if (!"GET".equals(m.get(Message.HTTP_REQUEST_METHOD))) {
            return null;
        }
        
        if (ui.getQueryParameters().containsKey(SOURCE_QUERY)) {
            synchronized (this) { 
                return getSource(new File(TMPDIR, getStem(resourceClass, "zip")));
            }
        }
        
        String codeQuery = ui.getQueryParameters().getFirst(CODE_QUERY);
        if (codeQuery == null) {
            return null;
        }
        
        String language = ui.getQueryParameters().getFirst(LANGUAGE_QUERY);
        if (language != null && !SUPPORTED_LANGUAGES.contains(language)) {
            return Response.noContent().entity("Unsupported language" + language).type("text/plain").build();
        }
        return doHandleRequest(m, resourceClass);
    }
    
    protected Response doHandleRequest(Message m, ClassResourceInfo resourceClass) { 
        synchronized (this) {
            File zipDir = new File(TMPDIR, getStem(resourceClass, "zip"));
            Response r = getLink(zipDir, m);
            if (r != null) {
                return r;
            }
            
            File srcDir = new File(TMPDIR, getStem(resourceClass, "src"));
            if (!srcDir.exists() && !srcDir.mkdir()) {
                throw new IllegalStateException("Unable to create working directory " + srcDir.getPath());
            }
            String codeType = ui.getQueryParameters().getFirst(CODE_TYPE_QUERY);
            try {
                String wadl = getWadl(m, resourceClass);
                if (wadl == null) {
                    LOG.warning("WADL for " 
                         + (resourceClass != null ? resourceClass.getServiceClass().getName() 
                             : "this service")
                         + " can not be loaded");
                    return Response.noContent().build();
                }
                generateSource(wadl, srcDir, codeType);
                zipSource(srcDir, zipDir);
                return getLink(zipDir, m);
            } catch (Exception ex) {
                LOG.warning("Code can not be generated for " 
                            + resourceClass != null ? resourceClass.getServiceClass().getName() 
                                : "this service");
                FileUtils.removeDir(zipDir);
                return Response.noContent().build();
            } finally {
                FileUtils.removeDir(srcDir);
            }
        }
    }
    
    private void zipSource(File srcDir, File zipDir) throws Exception {
        if (!zipDir.exists()) {
            zipDir.mkdir();
        }
        String pathSep = getPathSep();
        File zipFile = new File(zipDir.getAbsolutePath(), "src.zip");
        zipFile.createNewFile();
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
        List srcFiles = FileUtils.getFilesRecurse(srcDir, ".+\\.java$");
        for (File f : srcFiles) {
            String entryName = f.getAbsolutePath().substring(srcDir.getAbsolutePath().length() + 1);
            entryName = entryName.replace(".", pathSep).replace(pathSep + "java", ".java");
            zos.putNextEntry(new ZipEntry(entryName));
            IOUtils.copy(new FileInputStream(f), zos);
        }
        zos.close();
    }
    
    private String getLineSep() {
        String os = ui.getQueryParameters().getFirst(OS_QUERY);
        if (os == null) {
            return "\r\n";
        }
        return "unix".equals(os) ? "\r" : "\r\n";
    }
    
    protected String getPathSep() {
        String os = ui.getQueryParameters().getFirst(OS_QUERY);
        if (os == null) {
            return "\\";
        }
        return "unix".equals(os) ? "/" : "\\";
    }
    
    private Response getSource(File zipDir) {
        if (zipDir.exists()) {
            File zipFile = new File(zipDir.getAbsolutePath(), "src.zip");
            if (zipFile.exists()) {
                try {
                    return Response.ok().type("application/zip").entity(new FileInputStream(zipFile)).build();
                } catch (FileNotFoundException ex) {
                    // should not happen given we've checked it exists
                    throw new WebApplicationException();
                }
            }
        } 
        return Response.noContent().build();
        
    }
    
    private Response getLink(File zipDir, Message m) {
        if (zipDir.exists() && new File(zipDir.getAbsolutePath(), "src.zip").exists()) {
            UriBuilder builder = ui.getAbsolutePathBuilder();
            String link = builder.queryParam(SOURCE_QUERY).build().toString();
            // TODO : move it into a resource template
            StringBuilder sb = new StringBuilder();
            sb.append("");
            sb.append("Download the source");
            sb.append("");
            sb.append("

Link:


"); sb.append(""); sb.append(""); sb.append(""); m.getExchange().put(JAXRSUtils.IGNORE_MESSAGE_WRITERS, true); return Response.ok().type("application/xhtml+xml").entity( sb.toString()).build(); } return null; } public void removeCode(ClassResourceInfo cri) { removeCode(new File(TMPDIR, getStem(cri, "src"))); removeCode(new File(TMPDIR, getStem(cri, "zip"))); } protected String getStem(ClassResourceInfo cri, String suffix) { if (cri == null) { return "cxf-jaxrs-" + suffix; } else { return "cxf-jaxrs-" + cri.getServiceClass().getName() + "-" + suffix; } } private static void removeCode(File src) { if (src.exists()) { FileUtils.removeDir(src); } } protected String getWadl(Message m, ClassResourceInfo resourceClass) { m.put(Message.QUERY_STRING, WadlGenerator.WADL_QUERY); List> shs = ProviderFactory.getInstance(m).getRequestHandlers(); // this is actually being tested by ProviderFactory unit tests but just in case // WadlGenerator, the custom or default one, must be the first one if (shs.size() > 0 && shs.get(0).getProvider() instanceof WadlGenerator) { WadlGenerator wg = (WadlGenerator)shs.get(0).getProvider(); wg = new WadlGenerator(wg); wg.setAddResourceAndMethodIds(true); Response r = wg.handleRequest(m, resourceClass); return r == null ? null : (String)r.getEntity(); } return null; } protected void generateSource(String wadl, File srcDir, String codeType) { Element appElement = readWadl(wadl); Set typeClassNames = new HashSet(); List schemaElements = getSchemaElements(appElement); if (!schemaElements.isEmpty()) { // generate classes from schema JCodeModel codeModel = createCodeModel(schemaElements, typeClassNames); if (codeModel != null) { generateClassesFromSchema(codeModel, srcDir); } } if (!CODE_TYPE_GRAMMAR.equals(codeType)) { generateResourceClasses(appElement, schemaElements, typeClassNames, srcDir); } } private void generateResourceClasses(Element appElement, List schemaElements, Set typeClassNames, File src) { List resourcesEls = DOMUtils.getChildrenWithName(appElement, WadlGenerator.WADL_NS, "resources"); if (resourcesEls.size() != 1) { throw new IllegalStateException("WADL resources element is missing"); } List resourceEls = DOMUtils.getChildrenWithName(resourcesEls.get(0), WadlGenerator.WADL_NS, "resource"); if (resourceEls.size() == 0) { throw new IllegalStateException("WADL has no resource elements"); } GrammarInfo gInfo = getGrammarInfo(appElement, schemaElements); for (Element resource : resourceEls) { writeResourceClass(resource, typeClassNames, gInfo, src); } generateMainClass(resourcesEls.get(0), src); } private GrammarInfo getGrammarInfo(Element appElement, List schemaElements) { if (schemaElements.isEmpty()) { return null; } Map nsMap = new HashMap(); NamedNodeMap attrMap = appElement.getAttributes(); for (int i = 0; i < attrMap.getLength(); i++) { Node node = attrMap.item(i); String nodeName = node.getNodeName(); if (nodeName.startsWith("xmlns:")) { String nsValue = node.getNodeValue(); nsMap.put(nodeName.substring(6), nsValue); } } Map elementTypeMap = new HashMap(); for (Element schemaEl : schemaElements) { List elementEls = DOMUtils.getChildrenWithName(schemaEl, XmlSchemaConstants.XSD_NAMESPACE_URI, "element"); for (Element el : elementEls) { String type = el.getAttribute("type"); if (type.length() > 0) { String[] pair = type.split(":"); elementTypeMap.put(el.getAttribute("name"), pair.length == 1 ? pair[0] : pair[1]); } } } return new GrammarInfo(nsMap, elementTypeMap); } public void generateMainClass(Element resourcesEl, File src) { } private void writeResourceClass(Element rElement, Set typeClassNames, GrammarInfo gInfo, File src) { String resourceId = rElement.getAttribute("id"); String path = rElement.getAttribute("path"); if (resourceId.length() == 0) { LOG.warning("Resource with path " + path + " can not be mapped to a class"); return; } QName qname = JAXRSUtils.convertStringToQName(resourceId); if (getSchemaClassName(PackageUtils.getPackageNameByNameSpaceURI(qname.getNamespaceURI()), gInfo, qname.getLocalPart(), typeClassNames) != null) { return; } StringBuilder sbImports = new StringBuilder(); StringBuilder sbCode = new StringBuilder(); Set imports = createImports(); sbImports.append(getClassComment()).append(getLineSep()); sbImports.append("package " + qname.getNamespaceURI()) .append(";").append(getLineSep()).append(getLineSep()); writeAnnotation(sbCode, imports, Path.class, path, true, false); sbCode.append("public " + getClassType() + " " + qname.getLocalPart() + " {" + getLineSep() + getLineSep()); writeMethods(rElement, imports, sbCode, typeClassNames, gInfo); List childEls = DOMUtils.getChildrenWithName(rElement, WadlGenerator.WADL_NS, "resource"); for (Element childEl : childEls) { if (childEl.getAttribute("id").length() == 0) { writeMethods(childEl, imports, sbCode, typeClassNames, gInfo); } else { writeResourceMethod(childEl, childEl, imports, sbCode, typeClassNames, gInfo); } } sbCode.append("}"); writeImports(sbImports, imports); createJavaSourceFile(src, qname, sbCode, sbImports); for (Element subEl : childEls) { String id = subEl.getAttribute("id"); if (id.length() > 0 && !resourceId.equals(id) && !id.startsWith("{java")) { writeResourceClass(subEl, typeClassNames, gInfo, src); } } } private String getClassType() { return generateInterfaces ? "interface" : "class"; } private String getClassComment() { return "/**" + getLineSep() + " * Generated by Apache CXF" + getLineSep() + "**/"; } private void writeMethods(Element rElement, Set imports, StringBuilder sbCode, Set typeClassNames, GrammarInfo gInfo) { List methodEls = DOMUtils.getChildrenWithName(rElement, WadlGenerator.WADL_NS, "method"); for (Element methodEl : methodEls) { writeResourceMethod(rElement, methodEl, imports, sbCode, typeClassNames, gInfo); } } private void writeAnnotation(StringBuilder sbCode, Set imports, Class cls, String value, boolean nextLine, boolean addTab) { if (value != null && value.length() == 0) { return; } addImport(imports, cls.getName()); sbCode.append("@").append(cls.getSimpleName()); if (value != null) { sbCode.append("(\"" + value + "\")"); } if (nextLine) { sbCode.append(getLineSep()); if (addTab) { sbCode.append(TAB); } } } private void addImport(Set imports, String clsName) { if (imports == null || clsName.startsWith("java.lang")) { return; } if (!imports.contains(clsName)) { imports.add(clsName); } } private void writeImports(StringBuilder sbImports, Set imports) { for (String clsName : imports) { sbImports.append("import " + clsName).append(";").append(getLineSep()); } } private void writeResourceMethod(Element resourceEl, Element methodEl, Set imports, StringBuilder sbCode, Set typeClassNames, GrammarInfo gInfo) { String id = methodEl.getAttribute("id"); String methodName = methodEl.getAttribute("name"); String path = resourceEl.getAttribute("path"); if (id.length() == 0) { LOG.warning("Method with path " + path + " can not be mapped to a class method"); return; } sbCode.append(TAB); writeAnnotation(sbCode, imports, Path.class, path, true, true); if (methodName.length() > 0) { if (HTTP_METHOD_ANNOTATIONS.containsKey(methodName.toLowerCase())) { writeAnnotation(sbCode, imports, HTTP_METHOD_ANNOTATIONS.get(methodName.toLowerCase()), null, true, true); } else { // TODO : write a custom annotation class based on HttpMethod } } List responseEls = DOMUtils.getChildrenWithName(methodEl, WadlGenerator.WADL_NS, "response"); List requestEls = DOMUtils.getChildrenWithName(methodEl, WadlGenerator.WADL_NS, "request"); if (methodName.length() > 0) { writeFormatAnnotations(requestEls, sbCode, imports, true); writeFormatAnnotations(responseEls, sbCode, imports, false); } if (!generateInterfaces) { sbCode.append("public "); } boolean responseTypeAvailable = true; if (methodName.length() > 0) { responseTypeAvailable = writeResponseType(responseEls, sbCode, imports, typeClassNames, gInfo); sbCode.append(id); } else { QName qname = JAXRSUtils.convertStringToQName(id); String packageName = PackageUtils.getPackageNameByNameSpaceURI(qname.getNamespaceURI()); String clsSimpleName = getSchemaClassName(packageName, gInfo, qname.getLocalPart(), typeClassNames); String localName = clsSimpleName == null ? qname.getLocalPart() : clsSimpleName.substring(packageName.length() + 1); String parentId = ((Element)resourceEl.getParentNode()).getAttribute("id"); writeSubResponseType(id.equals(parentId), clsSimpleName == null ? qname.getNamespaceURI() : clsSimpleName.substring(0, packageName.length()), localName, sbCode, imports); // TODO : we need to take care of multiple subresource locators with diff @Path // returning the same type; also we might have ids like "{org.apache.cxf}Book#getName" sbCode.append("get" + localName); } sbCode.append("("); List inParamElements = new LinkedList(); inParamElements.addAll(DOMUtils.getChildrenWithName(resourceEl, WadlGenerator.WADL_NS, "param")); boolean form = false; if (requestEls.size() == 1 && inParamElements.size() == 0) { inParamElements.addAll(DOMUtils.getChildrenWithName(requestEls.get(0), WadlGenerator.WADL_NS, "param")); addFormParameters(inParamElements, requestEls.get(0)); form = true; } writeRequestTypes(requestEls, inParamElements, sbCode, imports, typeClassNames, gInfo, form); sbCode.append(")"); if (generateInterfaces) { sbCode.append(";"); } else { generateEmptyMethodBody(sbCode, responseTypeAvailable); } sbCode.append(getLineSep()).append(getLineSep()); } protected void generateEmptyMethodBody(StringBuilder sbCode, boolean responseTypeAvailable) { sbCode.append(" {"); sbCode.append(getLineSep()).append(TAB).append(TAB); sbCode.append("//TODO: implement").append(getLineSep()).append(TAB); if (responseTypeAvailable) { sbCode.append(TAB).append("return null;").append(getLineSep()).append(TAB); } sbCode.append("}"); } private void addFormParameters(List inParamElements, Element requestEl) { List repElements = DOMUtils.getChildrenWithName(requestEl, WadlGenerator.WADL_NS, "representation"); if (repElements.size() == 1) { String mediaType = repElements.get(0).getAttribute("mediaType"); if (MediaType.APPLICATION_FORM_URLENCODED.equals(mediaType)) { inParamElements.addAll(DOMUtils.getChildrenWithName(repElements.get(0), WadlGenerator.WADL_NS, "param")); } } } private boolean writeResponseType(List responseEls, StringBuilder sbCode, Set imports, Set typeClassNames, GrammarInfo gInfo) { List repElements = responseEls.size() == 1 ? DOMUtils.getChildrenWithName(responseEls.get(0), WadlGenerator.WADL_NS, "representation") : CastUtils.cast(Collections.emptyList(), Element.class); if (repElements.size() == 0) { sbCode.append("void "); return false; } String elementName = getElementRefName(repElements, typeClassNames, gInfo, imports); if (elementName != null) { sbCode.append(elementName + " "); } else { addImport(imports, Response.class.getName()); sbCode.append("Response "); } return true; } private void writeSubResponseType(boolean recursive, String ns, String localName, StringBuilder sbCode, Set imports) { if (!recursive && ns.length() > 0) { addImport(imports, ns + "." + localName); } sbCode.append(localName).append(" "); } private void writeRequestTypes(List requestEls, List inParamEls, StringBuilder sbCode, Set imports, Set typeClassNames, GrammarInfo gInfo, boolean form) { String elementName = null; List repElements = requestEls.size() == 1 ? DOMUtils.getChildrenWithName(requestEls.get(0), WadlGenerator.WADL_NS, "representation") : CastUtils.cast(Collections.emptyList(), Element.class); if (repElements.size() > 0) { elementName = getElementRefName(repElements, typeClassNames, gInfo, imports); } if (elementName != null) { sbCode.append(elementName).append(" ").append(elementName.toLowerCase()); if (inParamEls.size() > 0) { sbCode.append(", "); } } else if (inParamEls.size() == 0) { if (form) { addImport(imports, MultivaluedMap.class.getName()); sbCode.append("MultivaluedMap map"); } return; } for (int i = 0; i < inParamEls.size(); i++) { Element paramEl = inParamEls.get(i); String name = paramEl.getAttribute("name"); Class paramAnnotation = form ? FormParam.class : PARAM_ANNOTATIONS.get(paramEl.getAttribute("style")); writeAnnotation(sbCode, imports, paramAnnotation, name, false, false); String type = getPrimitiveType(paramEl); if (Boolean.valueOf(paramEl.getAttribute("repeating"))) { addImport(imports, List.class.getName()); type = "List<" + type + ">"; } sbCode.append(" ").append(type).append(" ").append(name.replace('.', '_')); if (i + 1 < inParamEls.size()) { sbCode.append(", "); if (i + 1 >= 4 && ((i + 1) % 4) == 0) { sbCode.append(getLineSep()).append(TAB).append(TAB).append(TAB).append(TAB); } } } } private String getPrimitiveType(Element paramEl) { String type = paramEl.getAttribute("type"); if (type == null) { return "String"; } String[] pair = type.split(":"); String value = pair.length == 2 ? pair[1] : type; return "string".equals(value) ? "String" : value; } private String getElementRefName(List repElements, Set typeClassNames, GrammarInfo gInfo, Set imports) { String elementRef = null; for (Element el : repElements) { String value = el.getAttribute("element"); if (value.length() > 0) { elementRef = value; break; } } if (elementRef != null) { String[] pair = elementRef.split(":"); if (pair.length == 2) { String namespace = gInfo != null ? gInfo.getNsMap().get(pair[0]) : null; if (namespace == null) { return null; } String packageName = PackageUtils.getPackageNameByNameSpaceURI(namespace); String clsName = getSchemaClassName(packageName, gInfo, pair[1], typeClassNames); if (clsName != null) { addImport(imports, clsName); return clsName.substring(packageName.length() + 1); } } } return null; } private String getSchemaClassName(String packageName, GrammarInfo gInfo, String localName, Set typeClassNames) { String clsName = matchClassName(typeClassNames, packageName, localName); if (clsName == null && gInfo != null) { clsName = matchClassName(typeClassNames, packageName, gInfo.getElementTypeMap().get(localName)); } return clsName; } private String matchClassName(Set typeClassNames, String packageName, String localName) { if (localName == null) { return null; } String clsName = packageName + "." + localName; for (String type : typeClassNames) { if (type.toLowerCase().equals(clsName)) { return type; } } return null; } private void writeFormatAnnotations(List parentEls, StringBuilder sbCode, Set imports, boolean inRep) { List repElements = parentEls.size() == 1 ? DOMUtils.getChildrenWithName(parentEls.get(0), WadlGenerator.WADL_NS, "representation") : CastUtils.cast(Collections.emptyList(), Element.class); if (repElements.size() == 0) { return; } Class cls = inRep ? Consumes.class : Produces.class; addImport(imports, cls.getName()); sbCode.append("@").append(cls.getSimpleName()).append("("); if (repElements.size() > 1) { sbCode.append("{"); } for (int i = 0; i < repElements.size(); i++) { String mediaType = repElements.get(i).getAttribute("mediaType"); if (mediaType != null) { sbCode.append("\"" + mediaType + "\""); if (i + 1 < repElements.size()) { sbCode.append(", "); } } } if (repElements.size() > 1) { sbCode.append(" }"); } sbCode.append(")"); sbCode.append(getLineSep()).append(TAB); } private void createJavaSourceFile(File src, QName qname, StringBuilder sbCode, StringBuilder sbImports) { String content = sbImports.toString() + getLineSep() + sbCode.toString(); File currentDir = new File(src.getAbsolutePath(), qname.getNamespaceURI()); currentDir.mkdirs(); File file = new File(currentDir.getAbsolutePath(), qname.getLocalPart() + ".java"); try { file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); fos.write(content.getBytes()); fos.close(); } catch (FileNotFoundException ex) { LOG.warning(file.getAbsolutePath() + " is not found"); } catch (IOException ex) { LOG.warning("Problem writing into " + file.getAbsolutePath()); } } private Element readWadl(String wadl) { try { Document doc = DOMUtils.readXml(new StringReader(wadl)); return doc.getDocumentElement(); } catch (Exception ex) { throw new IllegalStateException("Unable to read wadl", ex); } } private void generateClassesFromSchema(JCodeModel codeModel, File src) { try { Object writer = JAXBUtils.createFileCodeWriter(src); codeModel.build(writer); } catch (Exception e) { throw new IllegalStateException("Unable to write generated Java files for schemas: " + e.getMessage(), e); } } private List getSchemaElements(Element appElement) { List grammarEls = DOMUtils.getChildrenWithName(appElement, WadlGenerator.WADL_NS, "grammars"); if (grammarEls.size() != 1) { return null; } List schemasEls = DOMUtils.getChildrenWithName(grammarEls.get(0), XmlSchemaConstants.XSD_NAMESPACE_URI, "schema"); //TODO : check remote referencs if size() == 0 return schemasEls; } private JCodeModel createCodeModel(List schemaElements, Set type) { SchemaCompiler compiler = createCompiler(type); addSchemas(schemaElements, compiler); S2JJAXBModel intermediateModel = compiler.bind(); Object elForRun = ReflectionInvokationHandler .createProxyWrapper(new InnerErrorListener(), JAXBUtils.getParamClass(compiler, "setErrorListener")); JCodeModel codeModel = intermediateModel.generateCode(null, elForRun); JAXBUtils.logGeneratedClassNames(LOG, codeModel); return codeModel; } private SchemaCompiler createCompiler(Set typeClassNames) { return JAXBUtils.createSchemaCompilerWithDefaultAllocator(typeClassNames); } private void addSchemas(List schemaElements, SchemaCompiler compiler) { for (int i = 0; i < schemaElements.size(); i++) { String key = Integer.toString(i); //For JAXB 2.1.8 InputSource is = new InputSource((InputStream)null); is.setSystemId(key); is.setPublicId(key); compiler.getOptions().addGrammar(is); compiler.parseSchema(key, schemaElements.get(i)); } } public void setImportsComparator(Comparator importsComparator) { this.importsComparator = importsComparator; } private Set createImports() { return importsComparator == null ? new TreeSet() : new TreeSet(importsComparator); } public void setGenerateInterfaces(boolean generateInterfaces) { this.generateInterfaces = generateInterfaces; } private static class GrammarInfo { private Map nsMap; private Map elementTypeMap; public GrammarInfo(Map nsMap, Map elementTypeMap) { this.nsMap = nsMap; this.elementTypeMap = elementTypeMap; } public Map getNsMap() { return nsMap; } public Map getElementTypeMap() { return elementTypeMap; } } static class InnerErrorListener { public void error(SAXParseException ex) { throw new RuntimeException("Error compiling schema from WADL : " + ex.getMessage(), ex); } public void fatalError(SAXParseException ex) { throw new RuntimeException("Fatal error compiling schema from WADL : " + ex.getMessage(), ex); } public void info(SAXParseException ex) { // ignore } public void warning(SAXParseException ex) { // ignore } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy