| /* Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed 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.xmlbeans.impl.tool; |
| |
| import org.apache.maven.model.Resource; |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.apache.maven.plugins.annotations.LifecyclePhase; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.xmlbeans.XmlError; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.*; |
| import java.util.*; |
| import java.util.regex.Pattern; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| import static org.apache.xmlbeans.impl.tool.SchemaCompiler.parsePartialMethods; |
| |
| @SuppressWarnings("unused") |
| @Mojo(name = "compile", defaultPhase = LifecyclePhase.GENERATE_SOURCES) |
| public class MavenPlugin extends AbstractMojo { |
| // ****************************************************************************************** |
| // As we don't use the maven plugin-plugin, the defaultValues and others need to be manually |
| // copied into resources/maven/plugin.xml |
| // ****************************************************************************************** |
| |
| /** The maven project */ |
| @Parameter( readonly = true, defaultValue = "${project}" ) |
| private MavenProject project; |
| |
| /** sourceDir is a base directory for the list in sourceschema */ |
| @Parameter( defaultValue = "${project.basedir}/src/main/schema" ) |
| private String sourceDir; |
| |
| /** sourceSchemas is a comma-delimited list of all the schemas you want to compile */ |
| @Parameter( defaultValue = "*.xsd,*.wsdl,*.java" ) |
| private String sourceSchemas; |
| |
| /** xmlConfigs points to your xmlconfig.xml file */ |
| @Parameter( defaultValue = "${project.basedir}/src/schema/xmlconfig.xml" ) |
| private String xmlConfigs; |
| |
| /** javaTargetdir is where you want generated java source to appear */ |
| @Parameter( defaultValue = "${project.basedir}/target/generated-sources" ) |
| private String javaTargetDir; |
| |
| /** classTargetDir is where you want compiled class files to appear */ |
| @Parameter( defaultValue = "${project.basedir}/target/generated-resources" ) |
| private String classTargetDir; |
| |
| /** catalogLocation is the location of an entity resolver catalog to use for resolving namespace to schema locations. */ |
| @Parameter |
| private String catalogLocation; |
| |
| @Parameter |
| private String classPath; |
| |
| @Parameter |
| private List<Resource> resources; |
| |
| /** buildSchemas sets build process of the generated sources */ |
| @Parameter(defaultValue = "true") |
| private boolean buildSchemas; |
| |
| /** destination directory of the copied xsd files - default: schemaorg_apache_xmlbeans/src */ |
| @Parameter( defaultValue = "schemaorg_apache_xmlbeans/src" ) |
| private String baseSchemaLocation; |
| |
| /** schema system name - default: ${project.artifactId} */ |
| @Parameter( defaultValue = "${project.artifactId}" ) |
| private String name; |
| |
| /** verbose output - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean verbose; |
| |
| /** no output - default: true */ |
| @Parameter( defaultValue = "true" ) |
| private boolean quite; |
| |
| /** deactivate unique particle attribution - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean noUpa; |
| |
| /** deactivate particle valid (restriction) - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean noPvr; |
| |
| /** deactivate annotation generation - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean noAnn; |
| |
| /** do not validate contents of documentation-tags - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean noVDoc; |
| |
| /** Metadata package name. If explicitly set empty, generates to org.apache.xmlbeans.metadata - default: ${project.groupId}.${project.artifactId}.metadata */ |
| @Parameter( defaultValue = "${project.groupId}.${project.artifactId}.metadata" ) |
| private String repackage; |
| |
| /** |
| * If this option is set, then the schema compiler will permit and |
| * ignore multiple definitions of the same component (element, attribute, |
| * type, etc) names in the given namespaces. If multiple definitions |
| * with the same name appear, the definitions that happen to be processed |
| * last will be ignored. |
| * |
| * a list of namespace URIs |
| */ |
| @Parameter |
| private List<String> mdefNamespaces; |
| |
| /** |
| * Only generate a subset of the bean methods. Comma-seperated list of the following method types: |
| * GET, XGET, IS_SET, IS_NIL, IS_NIL_IDX, SET, SET_NIL, SET_NIL_IDX, XSET, UNSET, |
| * GET_ARRAY, XGET_ARRAY, GET_IDX, XGET_IDX, XSET_ARRAY, XSET_IDX, |
| * SIZE_OF_ARRAY, SET_ARRAY, SET_IDX, |
| * INSERT_IDX, INSERT_NEW_IDX, |
| * ADD, ADD_NEW, REMOVE_IDX, |
| * GET_LIST, XGET_LIST, SET_LIST, |
| * INSTANCE_TYPE |
| * |
| * Example: "ALL,-GET_LIST,-XGET_LIST" excludes GET_LIST and XGET_LIST methods |
| */ |
| @Parameter |
| private String partialMethods; |
| |
| @Parameter( defaultValue = "false" ) |
| private boolean download; |
| |
| @Parameter( defaultValue = "true" ) |
| private boolean sourceOnly; |
| |
| @Parameter |
| private File basedir; |
| |
| @Parameter |
| private String compiler; |
| |
| @Parameter( defaultValue = CodeGenUtil.DEFAULT_MEM_START ) |
| private String memoryInitialSize; |
| |
| @Parameter( defaultValue = CodeGenUtil.DEFAULT_MEM_MAX ) |
| private String memoryMaximumSize; |
| |
| @Parameter( defaultValue = "${project.basedir}/target/${project.artifactId}-${project.version}-xmltypes.jar" ) |
| private File outputJar; |
| |
| @Parameter( defaultValue = "false" ) |
| private boolean debug; |
| |
| /** copy annotations to javadoc of generated sources - default: false */ |
| @Parameter( defaultValue = "false" ) |
| private boolean copyAnn; |
| |
| @Parameter |
| private List<Extension> extensions; |
| |
| public void execute() throws MojoExecutionException, MojoFailureException { |
| if (sourceDir == null || sourceDir.isEmpty() || !new File(sourceDir).isDirectory()) { |
| throw new MojoFailureException("Set configuration <sourceDir> (='"+sourceDir+"') to a valid directory containing *.xsd,*.wsdl files."); |
| } |
| |
| if (baseSchemaLocation == null || baseSchemaLocation.isEmpty()) { |
| throw new MojoFailureException("baseSchemaLocation is empty"); |
| } |
| |
| if (sourceSchemas == null) { |
| getLog().debug("sourceSchemas is null"); |
| } |
| |
| if (classPath == null) { |
| getLog().debug("classPath is null"); |
| } |
| |
| final List<File> xsds = new ArrayList<>(); |
| final List<File> wsdls = new ArrayList<>(); |
| final List<File> javas = new ArrayList<>(); |
| File base = new File(sourceDir); |
| Resource resource = new Resource(); |
| resource.setDirectory(sourceDir); |
| resource.setTargetPath(baseSchemaLocation); |
| |
| // if sourceSchemas is not specified use all found schemas |
| // otherwise convert comma-separated string to regex including glob parameter |
| Pattern pat = Pattern.compile(sourceSchemas == null ? ".*" : |
| "(" + sourceSchemas |
| .replace(",","|") |
| .replace(".", "\\.") |
| .replace("*",".*") + |
| ")"); |
| |
| File[] schemaFiles = Objects.requireNonNull(base.listFiles((dir, name) -> |
| !name.endsWith(".xsdconfig") && pat.matcher(name).matches())); |
| for (File sf : schemaFiles) { |
| String name = sf.getName(); |
| switch (name.replaceAll(".*\\.", "")) { |
| case "wsdl": |
| wsdls.add(sf); |
| break; |
| case "java": |
| javas.add(sf); |
| break; |
| default: |
| xsds.add(sf); |
| break; |
| } |
| resource.addInclude(name); |
| } |
| |
| resources = Collections.singletonList(resource); |
| |
| if (buildSchemas) { |
| List<File> configs = (xmlConfigs == null || xmlConfigs.isEmpty()) ? Collections.emptyList() |
| : Stream.of(xmlConfigs.split(",")).flatMap(s -> |
| Stream.of(new File(s), new File(base, s)).filter(File::exists) |
| ).collect(Collectors.toList()); |
| |
| List<File> classPathList = new ArrayList<>(); |
| List<URL> urls = new ArrayList<>(); |
| if (classPath != null) { |
| for (String classpathElement : classPath.split(",")) { |
| File file = new File(classpathElement); |
| classPathList.add(file); |
| try { |
| urls.add(file.toURI().toURL()); |
| } catch (MalformedURLException e) { |
| throw new MojoFailureException("invalid classpath: "+file, e); |
| } |
| } |
| } |
| ClassLoader cl = new URLClassLoader(urls.toArray(new URL[0])); |
| EntityResolver entityResolver = MavenPluginResolver.getResolver(catalogLocation); |
| URI sourceDirURI = new File(sourceDir).toURI(); |
| entityResolver = new PassThroughResolver(cl, entityResolver, sourceDirURI, baseSchemaLocation); |
| |
| Parameters params = new Parameters(); |
| params.setXsdFiles(files(xsds)); |
| params.setWsdlFiles(files(wsdls)); |
| params.setJavaFiles(files(javas)); |
| params.setConfigFiles(files(configs)); |
| params.setClasspath(files(classPathList)); |
| params.setName(name); |
| params.setSrcDir(new File(javaTargetDir)); |
| params.setClassesDir(new File(classTargetDir)); |
| params.setNojavac(sourceOnly); |
| params.setVerbose(verbose); |
| params.setEntityResolver(entityResolver); |
| params.setQuiet(quite); |
| params.setNoUpa(noUpa); |
| params.setNoPvr(noPvr); |
| params.setNoAnn(noAnn); |
| params.setCopyAnn(copyAnn); |
| params.setNoVDoc(noVDoc); |
| if (repackage != null && !repackage.isEmpty()) { |
| params.setRepackage("org.apache.xmlbeans.metadata:"+repackage); |
| } |
| if (mdefNamespaces != null && !mdefNamespaces.isEmpty()) { |
| params.setMdefNamespaces(new HashSet<>(mdefNamespaces)); |
| } |
| List<XmlError> errorList = new ArrayList<>(); |
| params.setErrorListener(errorList); |
| |
| if (partialMethods != null && !partialMethods.isEmpty()) { |
| params.setPartialMethods(parsePartialMethods(partialMethods)); |
| } |
| params.setDownload(download); |
| params.setBaseDir(basedir); |
| params.setCompiler(compiler); |
| params.setMemoryInitialSize(memoryInitialSize); |
| params.setMemoryMaximumSize(memoryMaximumSize); |
| params.setOutputJar(outputJar); |
| params.setDebug(debug); |
| params.setExtensions(extensions); |
| |
| boolean result = SchemaCompiler.compile(params); |
| |
| if (!result) { |
| throw new MojoFailureException("Schema compilation failed!\n"+ |
| errorList.stream().map(XmlError::toString).collect(Collectors.joining("\n")) |
| ); |
| } |
| |
| Resource genResource = new Resource(); |
| genResource.setDirectory(classTargetDir); |
| project.addResource(genResource); |
| project.addCompileSourceRoot(javaTargetDir); |
| } |
| |
| } |
| |
| private static File[] files(List<File> files) { |
| return (files == null || files.isEmpty()) ? null : files.toArray(new File[0]); |
| } |
| |
| private static class PassThroughResolver implements EntityResolver { |
| private final ClassLoader cl; |
| private final EntityResolver delegate; |
| private final URI sourceDir; |
| //this copy has an / appended |
| private final String baseSchemaLocation; |
| |
| public PassThroughResolver(ClassLoader cl, EntityResolver delegate, URI sourceDir, String baseSchemaLocation) { |
| this.cl = cl; |
| this.delegate = delegate; |
| this.sourceDir = sourceDir; |
| this.baseSchemaLocation = baseSchemaLocation + "/"; |
| } |
| |
| public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { |
| if (delegate != null) { |
| InputSource is = delegate.resolveEntity(publicId, systemId); |
| if (is != null) { |
| return is; |
| } |
| } |
| System.out.println("Could not resolve publicId: " + publicId + ", systemId: " + systemId + " from catalog"); |
| String localSystemId; |
| try { |
| localSystemId = sourceDir.relativize(new URI(systemId)).toString(); |
| } catch (URISyntaxException e) { |
| throw new IOException("Could not relativeize systemId", e); |
| } |
| InputStream in = cl.getResourceAsStream(localSystemId); |
| if (in != null) { |
| System.out.println("found in classpath at: " + localSystemId); |
| return new InputSource(in); |
| } |
| in = cl.getResourceAsStream(baseSchemaLocation + localSystemId); |
| if (in != null) { |
| System.out.println("found in classpath at: META-INF/" + localSystemId); |
| return new InputSource(in); |
| } |
| System.out.println("Not found in classpath, looking in current directory: " + systemId); |
| return new InputSource(systemId); |
| } |
| } |
| |
| } |