/*
 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.internal.jxc;

import com.sun.tools.internal.jxc.ap.Options;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.SchemaOutputResolver;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.ValidatorHandler;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
import com.sun.tools.internal.jxc.gen.config.Config;
import com.sun.tools.internal.jxc.gen.config.Schema;
import com.sun.tools.internal.xjc.SchemaCache;
import com.sun.tools.internal.xjc.api.Reference;
import com.sun.tools.internal.xjc.util.ForkContentHandler;

import com.sun.xml.internal.bind.v2.util.XmlFactory;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;


This reads the config files passed by the user to annotation processing and obtains a list of classes that need to be included for a particular config from the set of classes passed by the user to annotation processing.
Author:Bhakti Mehta (bhakti.mehta@sun.com)
/** * This reads the config files passed by the user to annotation processing * and obtains a list of classes that need to be included * for a particular config from the set of classes passed * by the user to annotation processing. * * @author Bhakti Mehta (bhakti.mehta@sun.com) */
public final class ConfigReader {
The set of classes to be passed to XJC
/** * The set of classes to be passed to XJC * */
private final Set<Reference> classesToBeIncluded = new HashSet<Reference>();
The SchemaOutputResolver used to generate the schemas
/** * The SchemaOutputResolver used to generate the schemas */
private final SchemaOutputResolver schemaOutputResolver; private final ProcessingEnvironment env;
Params:
  • classes – The set of classes passed to the AnnotationProcessor
  • xmlFile – The configuration file.
Throws:
/** * * @param classes * The set of classes passed to the AnnotationProcessor * @param xmlFile * The configuration file. * @throws SAXException * If this is thrown, the error has already been reported. * @throws IOException * If any IO errors occur. */
public ConfigReader(ProcessingEnvironment env, Collection<? extends TypeElement> classes, File xmlFile, ErrorHandler errorHandler) throws SAXException, IOException { this.env = env; Config config = parseAndGetConfig(xmlFile, errorHandler, env.getOptions().containsKey(Options.DISABLE_XML_SECURITY)); checkAllClasses(config,classes); String path = xmlFile.getAbsolutePath(); String xmlPath = path.substring(0,path.lastIndexOf(File.separatorChar)); schemaOutputResolver = createSchemaOutputResolver(config,xmlPath); }
This creates a regular expression for the user pattern , matches the input classes passed by the user and returns the final list of classes that need to be included for a config file after applying those patterns
/** * This creates a regular expression * for the user pattern , matches the input classes * passed by the user and returns the final * list of classes that need to be included for a config file * after applying those patterns * */
public Collection<Reference> getClassesToBeIncluded() { return classesToBeIncluded; } private void checkAllClasses(Config config, Collection<? extends TypeElement> rootClasses) { List<Pattern> includeRegexList = config.getClasses().getIncludes(); List<Pattern> excludeRegexList = config.getClasses().getExcludes(); OUTER: for (TypeElement typeDecl : rootClasses) { String qualifiedName = typeDecl.getQualifiedName().toString(); for (Pattern pattern : excludeRegexList) { boolean match = checkPatternMatch(qualifiedName, pattern); if (match) continue OUTER; // excluded } for (Pattern pattern : includeRegexList) { boolean match = checkPatternMatch(qualifiedName, pattern); if (match) { classesToBeIncluded.add(new Reference(typeDecl,env)); break; } } } }
This returns the SchemaOutputResolver to generate the schemas
/** * This returns the SchemaOutputResolver to generate the schemas */
public SchemaOutputResolver getSchemaOutputResolver(){ return schemaOutputResolver; } private SchemaOutputResolver createSchemaOutputResolver(Config config, String xmlpath) { File baseDir = new File(xmlpath, config.getBaseDir().getPath()); SchemaOutputResolverImpl outResolver = new SchemaOutputResolverImpl (baseDir); for( Schema schema : (List<Schema>)config.getSchema() ) { String namespace = schema.getNamespace(); File location = schema.getLocation(); outResolver.addSchemaInfo(namespace,location); } return outResolver; }
This will check if the qualified name matches the pattern
Params:
  • qualifiedName – The qualified name of the TypeDeclaration
  • pattern – The pattern obtained from the users input
/** * This will check if the qualified name matches the pattern * * @param qualifiedName * The qualified name of the TypeDeclaration * @param pattern * The pattern obtained from the users input * */
private boolean checkPatternMatch(String qualifiedName, Pattern pattern) { Matcher matcher = pattern.matcher(qualifiedName); return matcher.matches(); }
Lazily parsed schema for the binding file.
/** * Lazily parsed schema for the binding file. */
private static SchemaCache configSchema = new SchemaCache("config.xsd", Config.class, true);
Parses an xml config file and returns a Config object.
Params:
  • xmlFile – The xml config file which is passed by the user to annotation processing
Returns: A non null Config object
/** * Parses an xml config file and returns a Config object. * * @param xmlFile * The xml config file which is passed by the user to annotation processing * @return * A non null Config object */
private Config parseAndGetConfig (File xmlFile, ErrorHandler errorHandler, boolean disableSecureProcessing) throws SAXException, IOException { XMLReader reader; try { SAXParserFactory factory = XmlFactory.createParserFactory(disableSecureProcessing); reader = factory.newSAXParser().getXMLReader(); } catch (ParserConfigurationException e) { // in practice this will never happen throw new Error(e); } NGCCRuntimeEx runtime = new NGCCRuntimeEx(errorHandler); // set up validator ValidatorHandler validator = configSchema.newValidator(); validator.setErrorHandler(errorHandler); // the validator will receive events first, then the parser. reader.setContentHandler(new ForkContentHandler(validator,runtime)); reader.setErrorHandler(errorHandler); Config config = new Config(runtime); runtime.setRootHandler(config); reader.parse(new InputSource(xmlFile.toURL().toExternalForm())); runtime.reset(); return config; }
Controls where the JAXB RI puts the generates schema files.
Author: Bhakti Mehta (bhakti.mehta@sun.com)
/** * Controls where the JAXB RI puts the generates * schema files. * @author * Bhakti Mehta (bhakti.mehta@sun.com) */
private static final class SchemaOutputResolverImpl extends SchemaOutputResolver{
Directory to which we put the rest of the files. Never be null.
/** * Directory to which we put the rest of the files. * Never be null. */
private final File baseDir;
Namespace URI to the location of the schema. This captures what the user specifies.
/** * Namespace URI to the location of the schema. * This captures what the user specifies. */
private final Map<String,File> schemas = new HashMap<String,File>();
Decides where the schema file (of the given namespace URI) will be written, and return it as a Result object.
/** * Decides where the schema file (of the given namespace URI) * will be written, and return it as a {@link Result} object. * */
public Result createOutput( String namespaceUri, String suggestedFileName ) { // the user's preference takes a precedence if(schemas.containsKey(namespaceUri)) { File loc = schemas.get(namespaceUri); if(loc==null) return null; // specifically not to generate a schema // create directories if necessary. we've already checked that the baseDir // exists, so this should be no surprise to users. loc.getParentFile().mkdirs(); return new StreamResult(loc); // generate into a file the user specified. } // if the user didn't say anything about this namespace, // generate it into the default directory with a default name. File schemaFile = new File (baseDir, suggestedFileName); // The systemId for the result will be schemaFile return new StreamResult(schemaFile); } public SchemaOutputResolverImpl(File baseDir) { assert baseDir!=null; this.baseDir = baseDir; } public void addSchemaInfo(String namespaceUri, File location) { if (namespaceUri == null ) //generate elements in no namespace namespaceUri = ""; schemas.put(namespaceUri, location); } } }