ohair@286: /* ohair@286: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: ohair@286: ohair@286: package com.sun.tools.internal.jxc.ap; ohair@286: alanb@368: import com.sun.tools.internal.jxc.api.JXC; ohair@286: import com.sun.tools.internal.xjc.api.J2SJAXBModel; ohair@286: import com.sun.tools.internal.xjc.api.Reference; ohair@286: ohair@286: import javax.annotation.processing.AbstractProcessor; ohair@286: import javax.annotation.processing.Processor; ohair@286: import javax.annotation.processing.RoundEnvironment; ohair@286: import javax.annotation.processing.SupportedAnnotationTypes; ohair@286: import javax.lang.model.SourceVersion; ohair@286: import javax.lang.model.element.Element; ohair@286: import javax.lang.model.element.ElementKind; ohair@286: import javax.lang.model.element.TypeElement; ohair@286: import javax.lang.model.util.ElementFilter; ohair@286: import javax.tools.Diagnostic; ohair@286: import javax.tools.StandardLocation; ohair@286: import javax.xml.bind.SchemaOutputResolver; ohair@286: import javax.xml.namespace.QName; ohair@286: import javax.xml.transform.Result; ohair@286: import javax.xml.transform.stream.StreamResult; ohair@286: import java.io.File; ohair@286: import java.io.FileOutputStream; ohair@286: import java.io.IOException; ohair@286: import java.io.OutputStream; ohair@286: import java.util.ArrayList; ohair@286: import java.util.Collection; ohair@286: import java.util.Collections; ohair@286: import java.util.HashMap; ohair@286: import java.util.List; ohair@286: import java.util.Map; ohair@286: import java.util.Set; ohair@286: ohair@286: /** ohair@286: * {@link Processor} that implements the schema generator ohair@286: * command line tool. ohair@286: * ohair@286: * @author Kohsuke Kawaguchi ohair@286: */ ohair@286: @SupportedAnnotationTypes("*") ohair@286: public class SchemaGenerator extends AbstractProcessor { ohair@286: ohair@286: /** ohair@286: * User-specified schema locations, if any. ohair@286: */ ohair@286: private final Map schemaLocations = new HashMap(); ohair@286: ohair@286: private File episodeFile; ohair@286: ohair@286: public SchemaGenerator() { ohair@286: } ohair@286: ohair@286: public SchemaGenerator( Map m ) { ohair@286: schemaLocations.putAll(m); ohair@286: } ohair@286: ohair@286: public void setEpisodeFile(File episodeFile) { ohair@286: this.episodeFile = episodeFile; ohair@286: } ohair@286: ohair@286: @Override ohair@286: public boolean process(Set annotations, RoundEnvironment roundEnv) { ohair@286: final ErrorReceiverImpl errorListener = new ErrorReceiverImpl(processingEnv); ohair@286: ohair@286: List classes = new ArrayList(); ohair@286: // simply ignore all the interface definitions, ohair@286: // so that users won't have to manually exclude interfaces, which is silly. ohair@286: filterClass(classes, roundEnv.getRootElements()); ohair@286: alanb@368: J2SJAXBModel model = JXC.createJavaCompiler().bind(classes, Collections.emptyMap(), null, processingEnv); ohair@286: if (model == null) ohair@286: return false; // error ohair@286: ohair@286: try { ohair@286: model.generateSchema( ohair@286: new SchemaOutputResolver() { ohair@286: public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { ohair@286: File file; ohair@286: OutputStream out; ohair@286: if (schemaLocations.containsKey(namespaceUri)) { ohair@286: file = schemaLocations.get(namespaceUri); ohair@286: if (file == null) return null; // don't generate ohair@286: out = new FileOutputStream(file); ohair@286: } else { ohair@286: // use the default ohair@286: file = new File(suggestedFileName); ohair@286: out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", suggestedFileName) ohair@286: .openOutputStream(); ohair@286: file = file.getAbsoluteFile(); ohair@286: } ohair@286: ohair@286: StreamResult ss = new StreamResult(out); ohair@286: processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing "+file); ohair@286: ss.setSystemId(file.toURL().toExternalForm()); ohair@286: return ss; ohair@286: } ohair@286: }, errorListener); ohair@286: ohair@286: if (episodeFile != null) { ohair@286: processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing "+episodeFile); ohair@286: model.generateEpisodeFile(new StreamResult(episodeFile)); ohair@286: } ohair@286: } catch (IOException e) { ohair@286: errorListener.error(e.getMessage(), e); ohair@286: } ohair@286: return false; ohair@286: } ohair@286: ohair@286: private void filterClass(List classes, Collection elements) { ohair@286: for (Element element : elements) { ohair@286: if (element.getKind().equals(ElementKind.CLASS)) { ohair@286: classes.add(new Reference((TypeElement) element, processingEnv)); ohair@286: filterClass(classes, ElementFilter.typesIn(element.getEnclosedElements())); ohair@286: } ohair@286: } ohair@286: } alanb@368: alanb@368: @Override alanb@368: public SourceVersion getSupportedSourceVersion() { alanb@368: if (SourceVersion.latest().compareTo(SourceVersion.RELEASE_6) > 0) alanb@368: return SourceVersion.valueOf("RELEASE_7"); alanb@368: else alanb@368: return SourceVersion.RELEASE_6; alanb@368: } ohair@286: }