1/* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.internal.jxc.ap; 27 28import com.sun.tools.internal.jxc.api.JXC; 29import com.sun.tools.internal.xjc.api.J2SJAXBModel; 30import com.sun.tools.internal.xjc.api.Reference; 31 32import javax.annotation.processing.AbstractProcessor; 33import javax.annotation.processing.Processor; 34import javax.annotation.processing.RoundEnvironment; 35import javax.annotation.processing.SupportedAnnotationTypes; 36import javax.lang.model.SourceVersion; 37import javax.lang.model.element.Element; 38import javax.lang.model.element.ElementKind; 39import javax.lang.model.element.TypeElement; 40import javax.lang.model.util.ElementFilter; 41import javax.tools.Diagnostic; 42import javax.tools.StandardLocation; 43import javax.xml.bind.SchemaOutputResolver; 44import javax.xml.namespace.QName; 45import javax.xml.transform.Result; 46import javax.xml.transform.stream.StreamResult; 47import java.io.File; 48import java.io.FileOutputStream; 49import java.io.IOException; 50import java.io.OutputStream; 51import java.util.ArrayList; 52import java.util.Collection; 53import java.util.Collections; 54import java.util.HashMap; 55import java.util.List; 56import java.util.Map; 57import java.util.Set; 58 59/** 60 * {@link Processor} that implements the schema generator 61 * command line tool. 62 * 63 * @author Kohsuke Kawaguchi 64 */ 65@SupportedAnnotationTypes("*") 66public class SchemaGenerator extends AbstractProcessor { 67 68 /** 69 * User-specified schema locations, if any. 70 */ 71 private final Map<String,File> schemaLocations = new HashMap<String, File>(); 72 73 private File episodeFile; 74 75 public SchemaGenerator() { 76 } 77 78 public SchemaGenerator( Map<String,File> m ) { 79 schemaLocations.putAll(m); 80 } 81 82 public void setEpisodeFile(File episodeFile) { 83 this.episodeFile = episodeFile; 84 } 85 86 @Override 87 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 88 final ErrorReceiverImpl errorListener = new ErrorReceiverImpl(processingEnv); 89 90 List<Reference> classesToBeBound = new ArrayList<Reference>(); 91 // simply ignore all the interface definitions, 92 // so that users won't have to manually exclude interfaces, which is silly. 93 filterClass(classesToBeBound, roundEnv.getRootElements()); 94 95 J2SJAXBModel model = JXC.createJavaCompiler().bind(classesToBeBound, Collections.<QName, Reference>emptyMap(), null, processingEnv); 96 if (model == null) 97 return false; // error 98 99 try { 100 model.generateSchema( 101 new SchemaOutputResolver() { 102 public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { 103 File file; 104 OutputStream out; 105 if (schemaLocations.containsKey(namespaceUri)) { 106 file = schemaLocations.get(namespaceUri); 107 if (file == null) return null; // don't generate 108 out = new FileOutputStream(file); 109 } else { 110 // use the default 111 file = new File(suggestedFileName); 112 out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", suggestedFileName) 113 .openOutputStream(); 114 file = file.getAbsoluteFile(); 115 } 116 117 StreamResult ss = new StreamResult(out); 118 processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing "+file); 119 ss.setSystemId(file.toURL().toExternalForm()); 120 return ss; 121 } 122 }, errorListener); 123 124 if (episodeFile != null) { 125 processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Writing "+episodeFile); 126 model.generateEpisodeFile(new StreamResult(episodeFile)); 127 } 128 } catch (IOException e) { 129 errorListener.error(e.getMessage(), e); 130 } 131 return false; 132 } 133 134 /** 135 * Filter classes (note that enum is kind of class) from elements tree 136 * @param result list of found classes 137 * @param elements tree to be filtered 138 */ 139 private void filterClass(List<Reference> result, Collection<? extends Element> elements) { 140 for (Element element : elements) { 141 final ElementKind kind = element.getKind(); 142 if (ElementKind.CLASS.equals(kind) || ElementKind.ENUM.equals(kind)) { 143 result.add(new Reference((TypeElement) element, processingEnv)); 144 filterClass(result, ElementFilter.typesIn(element.getEnclosedElements())); 145 } 146 } 147 } 148 149 @Override 150 public SourceVersion getSupportedSourceVersion() { 151 if (SourceVersion.latest().compareTo(SourceVersion.RELEASE_6) > 0) 152 return SourceVersion.valueOf("RELEASE_7"); 153 else 154 return SourceVersion.RELEASE_6; 155 } 156} 157