Search in sources :

Example 1 with Artifact

use of com.webcohesion.enunciate.artifacts.Artifact in project enunciate by stoicflame.

the class Enunciate method run.

@Override
public void run() {
    if (this.modules != null && !this.modules.isEmpty()) {
        // scan for any included types.
        List<File> classpath = this.classpath == null ? new ArrayList<File>() : this.classpath;
        List<File> sourcepath = this.sourcepath == null ? new ArrayList<File>() : this.sourcepath;
        List<URL> scanpath = new ArrayList<URL>(classpath.size() + sourcepath.size());
        for (File entry : classpath) {
            if (isValidScanpathEntry(entry)) {
                try {
                    scanpath.add(entry.toURI().toURL());
                } catch (MalformedURLException e) {
                    throw new EnunciateException(e);
                }
            }
        }
        for (File entry : sourcepath) {
            if (isValidScanpathEntry(entry)) {
                try {
                    scanpath.add(entry.toURI().toURL());
                } catch (MalformedURLException e) {
                    throw new EnunciateException(e);
                }
            }
        }
        Reflections reflections = loadApiReflections(scanpath);
        Set<String> scannedEntries = reflections.getStore().get(EnunciateReflectionsScanner.class.getSimpleName()).keySet();
        Set<String> includedTypes = new HashSet<String>();
        Set<String> scannedSourceFiles = new HashSet<String>();
        for (String entry : scannedEntries) {
            int innerClassSeparatorIndex = entry.lastIndexOf('$');
            if (innerClassSeparatorIndex > 0) {
                // inner class; convert the name to its "canonical" name.
                String simpleName = entry.substring(innerClassSeparatorIndex + 1);
                if (!Character.isDigit(simpleName.charAt(0))) {
                    // if the inner class isn't an anonymous inner class, add it to the included types, too.
                    String innerClass = entry.replace('$', '.');
                    includedTypes.add(innerClass);
                }
                String outerClass = entry.substring(0, entry.indexOf('$'));
                includedTypes.add(outerClass);
            } else if (entry.endsWith(".java")) {
                // java source file; add it to the scanned source files.
                scannedSourceFiles.add(entry);
            } else if (!entry.endsWith("package-info")) {
                // if it's not a package-info file, it should be a standard java class.
                includedTypes.add(entry);
            }
        }
        // only include the source files of the types that are on the classpath.
        Iterator<String> sourceFilesIt = scannedSourceFiles.iterator();
        while (sourceFilesIt.hasNext()) {
            String sourceFile = sourceFilesIt.next();
            String typeName = sourceFile.substring(0, sourceFile.length() - 5).replace('/', '.');
            if (!includedTypes.contains(typeName)) {
                sourceFilesIt.remove();
            }
        }
        getLogger().debug("Detected API Types: %s", new EnunciateLogger.ListWriter(includedTypes));
        // gather all the java source files.
        List<URL> sourceFiles = getSourceFileURLs();
        URLClassLoader apiClassLoader = new URLClassLoader(scanpath.toArray(new URL[scanpath.size()]));
        for (String javaFile : scannedSourceFiles) {
            Enumeration<URL> resources;
            try {
                resources = apiClassLoader.findResources(javaFile);
            } catch (IOException e) {
                getLogger().debug("Unable to load java source file %s: %s", javaFile, e.getMessage());
                continue;
            }
            if (!resources.hasMoreElements()) {
                getLogger().debug("Unable to find java source file %s on the classpath.", javaFile);
            } else {
                URL resource = resources.nextElement();
                if (!resources.hasMoreElements()) {
                    sourceFiles.add(resource);
                } else {
                    StringBuilder locations = new StringBuilder("[").append(resource.toString());
                    while (resources.hasMoreElements()) {
                        resource = resources.nextElement();
                        locations.append(", ").append(resource);
                    }
                    getLogger().warn("Java source file %s will not be included on the classpath because it is found in multiple locations: %s", javaFile, locations);
                }
            }
        }
        if (sourceFiles.isEmpty()) {
            // Java compiler needs _something_ to compile, so we'll provide an dummy class.
            sourceFiles.add(Enunciate.class.getResource("/com/webcohesion/enunciate/Nothing.java"));
        }
        // invoke the processor.
        List<String> options = new ArrayList<String>();
        // don't compile the classes; only run the annotation processing engine.
        options.add("-proc:only");
        // don't generate class files for implicit classes
        options.add("-implicit:none");
        // set the processor path to empty so the engine won't automatically find annotation processors
        options.addAll(Arrays.asList("-processorpath", ""));
        String cp = writeClasspath(classpath);
        getLogger().debug("Compiler classpath: %s", new EnunciateLogger.ListWriter(classpath));
        options.addAll(Arrays.asList("-classpath", cp));
        String sp = writeClasspath(sourcepath);
        getLogger().debug("Compiler sourcepath: %s", new EnunciateLogger.ListWriter(sourcepath));
        options.addAll(Arrays.asList("-sourcepath", sp));
        List<String> compilerArgs = getCompilerArgs();
        getLogger().debug("Compiler args: %s", compilerArgs);
        options.addAll(compilerArgs);
        getLogger().debug("Compiler sources: %s", new EnunciateLogger.ListWriter(sourceFiles));
        List<JavaFileObject> sources = new ArrayList<JavaFileObject>(sourceFiles.size());
        String encoding = findEncoding(compilerArgs);
        for (URL sourceFile : sourceFiles) {
            sources.add(new URLFileObject(sourceFile, encoding));
        }
        JavaCompiler compiler = JavacTool.create();
        StringWriter compilerOutput = new StringWriter();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        JavaCompiler.CompilationTask task = compiler.getTask(compilerOutput, null, diagnostics, options, null, sources);
        EnunciateAnnotationProcessor processor = new EnunciateAnnotationProcessor(this, includedTypes);
        task.setProcessors(Collections.singletonList(processor));
        Boolean javacSuccess = task.call();
        if (!javacSuccess || !processor.processed) {
            String outputText = compilerOutput.toString();
            try {
                if (!outputText.isEmpty()) {
                    BufferedReader reader = new BufferedReader(new StringReader(outputText));
                    String line = reader.readLine();
                    while (line != null) {
                        getLogger().warn("[javac] %s", line);
                        line = reader.readLine();
                    }
                }
            } catch (IOException e) {
            // fall through...
            }
            for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                BufferedReader message = new BufferedReader(new StringReader(diagnostic.toString()));
                try {
                    String line = message.readLine();
                    boolean duplicateClassErrorDetected = line != null && line.contains(DUPLICATE_CLASS_ERROR_MESSAGE_ENGLISH);
                    getLogger().warn("[javac] [%s] %s:%s:%s %s", diagnostic.getKind(), diagnostic.getSource(), diagnostic.getLineNumber(), diagnostic.getColumnNumber(), line == null ? "" : line);
                    while (line != null) {
                        getLogger().warn("[javac] %s", line);
                        line = message.readLine();
                    }
                    if (duplicateClassErrorDetected) {
                        getLogger().warn("");
                        getLogger().warn("It appears you ran into the infamous \"duplicate class\" bug in the Java compiler. Bummer.");
                        getLogger().warn("This usually happens when you've got two source files on your source path that declare types of the same name, even if they're in different packages.");
                        getLogger().warn("This a bug in the Java compiler, and is being tracked at https://github.com/stoicflame/enunciate/issues/117.");
                        getLogger().warn("The only known workaround is to exclude the offending source jar(s) from your source path.");
                        getLogger().warn("If you're using Maven, you can do so using the 'sourcepathExcludes' configuration element as described at https://github.com/stoicflame/enunciate/wiki/Multi-Module-Projects.");
                        getLogger().warn("");
                    }
                } catch (IOException e) {
                    getLogger().warn("[javac] %s", diagnostic);
                }
            }
            if (javacSuccess && !processor.processed) {
                getLogger().error("");
                getLogger().error("The Java compiler has crashed! This is likely due to some anomalies in your classpath or your source path (e.g. duplicate source files for the same class). The fact that there isn't more information available is a bug in the Java compiler.");
                getLogger().error("");
                getLogger().error("Please see https://github.com/stoicflame/enunciate/wiki/Java-Compiler-Crash for some tips on what to do about this.");
                getLogger().error("");
            }
            throw new EnunciateException("Enunciate compile failed.");
        }
        getLogger().debug("[javac] %s", compilerOutput);
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
            getLogger().debug("[javac] [%s] %s:%s:%s %s", diagnostic.getKind(), diagnostic.getSource(), diagnostic.getLineNumber(), diagnostic.getColumnNumber(), diagnostic);
        }
        HashSet<String> exportedArtifacts = new HashSet<String>();
        for (Artifact artifact : artifacts) {
            String artifactId = artifact.getId();
            Map.Entry<String, File> export = null;
            for (Map.Entry<String, File> entry : this.exports.entrySet()) {
                if (artifactId.equals(entry.getKey()) || artifact.getAliases().contains(entry.getKey())) {
                    export = entry;
                }
            }
            if (export != null) {
                File dest = export.getValue();
                getLogger().debug("Exporting artifact %s to %s.", export.getKey(), dest);
                try {
                    artifact.exportTo(dest, this);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                exportedArtifacts.add(export.getKey());
            }
        }
        for (String export : this.exports.keySet()) {
            if (!exportedArtifacts.remove(export)) {
                getLogger().warn("Unknown artifact '%s'.  Artifact will not be exported.", export);
            }
        }
    } else {
        this.logger.warn("No Enunciate modules have been loaded. No work was done.");
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) ArrayList(java.util.ArrayList) URL(java.net.URL) SimpleJavaFileObject(javax.tools.SimpleJavaFileObject) JavaFileObject(javax.tools.JavaFileObject) StringWriter(java.io.StringWriter) StringReader(java.io.StringReader) DiagnosticCollector(javax.tools.DiagnosticCollector) Reflections(org.reflections.Reflections) HashSet(java.util.HashSet) JavaCompiler(javax.tools.JavaCompiler) IOException(java.io.IOException) Artifact(com.webcohesion.enunciate.artifacts.Artifact) URLClassLoader(java.net.URLClassLoader) BufferedReader(java.io.BufferedReader) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 2 with Artifact

use of com.webcohesion.enunciate.artifacts.Artifact in project enunciate by stoicflame.

the class DocsModule method copyDocumentationArtifacts.

protected List<Download> copyDocumentationArtifacts(Set<Artifact> artifacts, File outputDir) throws IOException {
    ArrayList<Download> downloads = new ArrayList<Download>();
    for (Artifact artifact : artifacts) {
        debug("Exporting %s to directory %s.", artifact.getId(), outputDir);
        artifact.exportTo(outputDir, this.enunciate);
        if (artifact instanceof SpecifiedArtifact && !((SpecifiedArtifact) artifact).isShowLink()) {
            continue;
        }
        Download download = new Download();
        download.setSlug("artifact_" + artifact.getId().replace('.', '_'));
        download.setName(artifact.getName());
        download.setDescription(artifact.getDescription());
        download.setCreated(artifact.getCreated());
        if (artifact instanceof ClientLibraryJavaArtifact) {
            download.setGroupId(((ClientLibraryJavaArtifact) artifact).getGroupId());
            download.setArtifactId(((ClientLibraryJavaArtifact) artifact).getArtifactId());
            download.setVersion(((ClientLibraryJavaArtifact) artifact).getVersion());
        }
        Collection<? extends Artifact> childArtifacts = (artifact instanceof ClientLibraryArtifact) ? ((ClientLibraryArtifact) artifact).getArtifacts() : (artifact instanceof SpecifiedArtifact) ? Arrays.asList(((SpecifiedArtifact) artifact).getFile()) : Arrays.asList(artifact);
        ArrayList<DownloadFile> downloadFiles = new ArrayList<DownloadFile>();
        for (Artifact childArtifact : childArtifacts) {
            DownloadFile downloadFile = new DownloadFile();
            downloadFile.setDescription(childArtifact.getDescription());
            downloadFile.setName(childArtifact.getName());
            downloadFile.setSize(getDisplaySize(childArtifact.getSize()));
            downloadFiles.add(downloadFile);
        }
        download.setFiles(downloadFiles);
        downloads.add(download);
    }
    return downloads;
}
Also used : ClientLibraryJavaArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryJavaArtifact) ClientLibraryArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryArtifact) FileArtifact(com.webcohesion.enunciate.artifacts.FileArtifact) ClientLibraryJavaArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryJavaArtifact) Artifact(com.webcohesion.enunciate.artifacts.Artifact) ClientLibraryArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryArtifact)

Example 3 with Artifact

use of com.webcohesion.enunciate.artifacts.Artifact in project enunciate by stoicflame.

the class DocsModule method findDocumentationArtifacts.

private TreeSet<Artifact> findDocumentationArtifacts() {
    HashSet<String> explicitArtifacts = new HashSet<String>();
    TreeSet<Artifact> artifacts = new TreeSet<Artifact>();
    for (ExplicitDownloadConfig download : getExplicitDownloads()) {
        if (download.getArtifact() != null) {
            explicitArtifacts.add(download.getArtifact());
        } else if (download.getFile() != null) {
            File downloadFile = resolveFile(download.getFile());
            debug("File %s to be added as an extra download.", downloadFile.getAbsolutePath());
            SpecifiedArtifact artifact = new SpecifiedArtifact(getName(), downloadFile.getName(), downloadFile);
            if (download.getName() != null) {
                artifact.setName(download.getName());
            }
            if (download.getDescription() != null) {
                artifact.setDescription(download.getDescription());
            }
            artifact.setShowLink(!"false".equals(download.getShowLink()));
            artifacts.add(artifact);
        }
    }
    for (Artifact artifact : this.enunciate.getArtifacts()) {
        if (artifact.isPublic() || explicitArtifacts.contains(artifact.getId())) {
            artifacts.add(artifact);
            debug("Artifact %s to be added as an extra download.", artifact.getId());
            explicitArtifacts.remove(artifact.getId());
        }
    }
    if (explicitArtifacts.size() > 0) {
        for (String artifactId : explicitArtifacts) {
            warn("WARNING: Unknown artifact '%s'.  Will not be available for download.", artifactId);
        }
    }
    return artifacts;
}
Also used : FileArtifact(com.webcohesion.enunciate.artifacts.FileArtifact) ClientLibraryJavaArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryJavaArtifact) Artifact(com.webcohesion.enunciate.artifacts.Artifact) ClientLibraryArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryArtifact)

Example 4 with Artifact

use of com.webcohesion.enunciate.artifacts.Artifact in project enunciate by stoicflame.

the class DocsModule method call.

@Override
public void call(EnunciateContext context) {
    try {
        File docsDir = getDocsDir();
        String subDir = getDocsSubdir();
        if (subDir != null) {
            docsDir = new File(docsDir, subDir);
        }
        if (!isUpToDateWithSources(docsDir)) {
            Set<String> facetIncludes = new TreeSet<String>(this.enunciate.getConfiguration().getFacetIncludes());
            facetIncludes.addAll(getFacetIncludes());
            Set<String> facetExcludes = new TreeSet<String>(this.enunciate.getConfiguration().getFacetExcludes());
            facetExcludes.addAll(getFacetExcludes());
            FacetFilter facetFilter = new FacetFilter(facetIncludes, facetExcludes);
            ApiRegistrationContext registrationContext = new DocsRegistrationContext(this.apiRegistry, facetFilter);
            List<ResourceApi> resourceApis = this.apiRegistry.getResourceApis(registrationContext);
            Set<Syntax> syntaxes = this.apiRegistry.getSyntaxes(registrationContext);
            List<ServiceApi> serviceApis = this.apiRegistry.getServiceApis(registrationContext);
            Set<Artifact> documentationArtifacts = findDocumentationArtifacts();
            if (syntaxes.isEmpty() && serviceApis.isEmpty() && resourceApis.isEmpty() && documentationArtifacts.isEmpty()) {
                warn("No documentation generated: there are no data types, services, or resources to document.");
                return;
            }
            // make sure the docs dir exists.
            docsDir.mkdirs();
            Map<String, Object> model = new HashMap<String, Object>();
            String intro = this.enunciate.getConfiguration().readDescription(context, false, registrationContext.getTagHandler());
            if (intro != null) {
                model.put("apiDoc", intro);
            }
            String copyright = this.enunciate.getConfiguration().getCopyright();
            if (copyright != null) {
                model.put("copyright", copyright);
            }
            String title = this.enunciate.getConfiguration().getTitle();
            model.put("title", title == null ? "Web Service API" : title);
            // extract out the documentation base
            String cssPath = buildBase(docsDir);
            if (cssPath != null) {
                model.put("cssFile", cssPath);
            }
            model.put("file", new FileDirective(docsDir, this.enunciate.getLogger()));
            model.put("apiRelativePath", getRelativePathToRootDir());
            model.put("includeApplicationPath", isIncludeApplicationPath());
            model.put("includeDataTypesHomeIndex", isIncludeDataTypesHomeIndex());
            model.put("favicon", getFavicon());
            // iterate through schemas and make sure the schema is copied to the docs dir
            for (Syntax syntax : syntaxes) {
                for (Namespace namespace : syntax.getNamespaces()) {
                    if (namespace.getSchemaFile() != null) {
                        namespace.getSchemaFile().writeTo(docsDir);
                    }
                }
            }
            model.put("data", syntaxes);
            for (ResourceApi resourceApi : resourceApis) {
                if (resourceApi.getWadlFile() != null) {
                    resourceApi.getWadlFile().writeTo(docsDir);
                }
            }
            model.put("resourceApis", resourceApis);
            InterfaceDescriptionFile swaggerUI = this.apiRegistry.getSwaggerUI();
            if (swaggerUI != null) {
                swaggerUI.writeTo(docsDir);
                model.put("swaggerUI", swaggerUI);
            }
            // iterate through wsdls and make sure the wsdl is copied to the docs dir
            for (ServiceApi serviceApi : serviceApis) {
                for (ServiceGroup serviceGroup : serviceApi.getServiceGroups()) {
                    if (serviceGroup.getWsdlFile() != null) {
                        serviceGroup.getWsdlFile().writeTo(docsDir);
                    }
                }
            }
            model.put("serviceApis", serviceApis);
            model.put("downloads", copyDocumentationArtifacts(documentationArtifacts, docsDir));
            model.put("indexPageName", getIndexPageName());
            model.put("disableMountpoint", isDisableRestMountpoint());
            model.put("additionalCssFiles", getAdditionalCss());
            model.put("disableResourceLinks", isDisableResourceLinks());
            processTemplate(getDocsTemplateURL(), model);
        } else {
            info("Skipping documentation source generation as everything appears up-to-date...");
        }
        this.enunciate.addArtifact(new FileArtifact(getName(), "docs", docsDir));
    } catch (IOException e) {
        throw new EnunciateException(e);
    } catch (TemplateException e) {
        throw new EnunciateException(e);
    }
}
Also used : ServiceGroup(com.webcohesion.enunciate.api.services.ServiceGroup) FacetFilter(com.webcohesion.enunciate.facets.FacetFilter) ServiceApi(com.webcohesion.enunciate.api.services.ServiceApi) EnunciateException(com.webcohesion.enunciate.EnunciateException) FileDirective(com.webcohesion.enunciate.util.freemarker.FileDirective) TemplateException(freemarker.template.TemplateException) FileArtifact(com.webcohesion.enunciate.artifacts.FileArtifact) ClientLibraryJavaArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryJavaArtifact) Artifact(com.webcohesion.enunciate.artifacts.Artifact) ClientLibraryArtifact(com.webcohesion.enunciate.artifacts.ClientLibraryArtifact) Namespace(com.webcohesion.enunciate.api.datatype.Namespace) ResourceApi(com.webcohesion.enunciate.api.resources.ResourceApi) FileArtifact(com.webcohesion.enunciate.artifacts.FileArtifact) Syntax(com.webcohesion.enunciate.api.datatype.Syntax)

Example 5 with Artifact

use of com.webcohesion.enunciate.artifacts.Artifact in project enunciate by stoicflame.

the class AssembleBaseMojo method postProcess.

@Override
protected void postProcess(Enunciate enunciate) {
    super.postProcess(enunciate);
    File webInfClasses = new File(new File(new File(this.webappDirectory), "WEB-INF"), "classes");
    webInfClasses.mkdirs();
    Set<com.webcohesion.enunciate.artifacts.Artifact> artifacts = enunciate.getArtifacts();
    for (Artifact artifact : artifacts) {
        if (artifact.isBelongsOnServerSideClasspath()) {
            try {
                artifact.exportTo(webInfClasses, enunciate);
            } catch (IOException e) {
                throw new EnunciateException(e);
            }
        }
    }
}
Also used : EnunciateException(com.webcohesion.enunciate.EnunciateException) IOException(java.io.IOException) File(java.io.File) Artifact(com.webcohesion.enunciate.artifacts.Artifact)

Aggregations

Artifact (com.webcohesion.enunciate.artifacts.Artifact)5 ClientLibraryArtifact (com.webcohesion.enunciate.artifacts.ClientLibraryArtifact)3 ClientLibraryJavaArtifact (com.webcohesion.enunciate.artifacts.ClientLibraryJavaArtifact)3 FileArtifact (com.webcohesion.enunciate.artifacts.FileArtifact)3 EnunciateException (com.webcohesion.enunciate.EnunciateException)2 File (java.io.File)2 IOException (java.io.IOException)2 Namespace (com.webcohesion.enunciate.api.datatype.Namespace)1 Syntax (com.webcohesion.enunciate.api.datatype.Syntax)1 ResourceApi (com.webcohesion.enunciate.api.resources.ResourceApi)1 ServiceApi (com.webcohesion.enunciate.api.services.ServiceApi)1 ServiceGroup (com.webcohesion.enunciate.api.services.ServiceGroup)1 FacetFilter (com.webcohesion.enunciate.facets.FacetFilter)1 FileDirective (com.webcohesion.enunciate.util.freemarker.FileDirective)1 TemplateException (freemarker.template.TemplateException)1 BufferedReader (java.io.BufferedReader)1 StringReader (java.io.StringReader)1 StringWriter (java.io.StringWriter)1 MalformedURLException (java.net.MalformedURLException)1 URL (java.net.URL)1