/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.isis.tool.mavenplugin; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import com.google.common.base.Charsets; import com.google.common.base.Strings; import com.google.common.io.Files; 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.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.apache.isis.applib.services.jaxb.JaxbService; import org.apache.isis.core.commons.factory.InstanceUtil; import org.apache.isis.core.runtime.system.session.IsisSessionFactory; @Mojo( name = "xsd", defaultPhase = LifecyclePhase.GENERATE_RESOURCES, requiresProject = true, requiresDependencyResolution = ResolutionScope.COMPILE, requiresDependencyCollection = ResolutionScope.COMPILE ) public class IsisMojoXsd extends IsisMojoAbstract { protected IsisMojoXsd() { super(); } /** * List of JAXB-annotated classes to generate schema for. */ @Parameter(required = true, readonly = false, property = "jaxbClasses") private List<String> jaxbClasses; /** * Directory to generate XSD schemas; defaults to <code>target/generated-resources/isis-xsd</code> */ @Parameter(required = false, readonly = false, property = "output", defaultValue = "generated-resources/isis-xsd") private String output; /** * Whether a separate directory is created for each JAXB-class, or whether to generate all together (so that they * are created as a single bundle). */ @Parameter(required = false, readonly = false, property = "separate", defaultValue = "false") private boolean separate; /** * Whether to also generate the isis common schema(s). */ @Parameter(required = false, readonly = false, property = "commonSchemas", defaultValue = "false") private boolean commonSchemas; @Override protected void doExecute( final ContextForMojo context, final IsisSessionFactory isisSessionFactory) throws MojoFailureException, IOException { final JaxbService jaxbService = isisSessionFactory.getServicesInjector().lookupService(JaxbService.class); final MavenProject mavenProject = context.getMavenProject(); final File outputDir = determineOutputDir(mavenProject); for (String jaxbClass : jaxbClasses) { writeSchemas(jaxbService, jaxbClass, outputDir); } } private File determineOutputDir(final MavenProject mavenProject) { final String targetDir = mavenProject.getBuild().getDirectory(); final String outputDirStr = targetDir + File.separator + output; return new File(outputDirStr); } /** * to ensure that any schemas with no namespace are given unique file names when written out */ private int unnamed; private void writeSchemas( final JaxbService jaxbService, final String dtoClassName, final File outputDir) throws MojoFailureException { final Object instance = InstanceUtil.createInstance(dtoClassName); final Map<String, String> schemaByNamespace = jaxbService.toXsd( instance, commonSchemas ? JaxbService.IsisSchemas.INCLUDE: JaxbService.IsisSchemas.IGNORE); final File schemaDir = separate? new File(outputDir, dtoClassName): outputDir; unnamed = 0; for (Map.Entry<String, String> entry : schemaByNamespace.entrySet()) { final String namespaceUri = entry.getKey(); final String schemaText = entry.getValue(); final String xsdName = xsdDirNameFor(namespaceUri); final File schemaFile = new File(schemaDir, xsdName); try { Files.createParentDirs(schemaFile); } catch (IOException e) { throw new MojoFailureException( String.format("Failed to create dir: '%s'", schemaFile.getParent())); } try { Files.write(schemaText, schemaFile, Charsets.UTF_8); } catch (IOException e) { throw new MojoFailureException("Failed to write out " + schemaFile); } if(!xsdName.endsWith(".xsd")) { final File schemaFileWithXsdSuffix = new File(schemaDir, xsdName + ".xsd"); try { Files.copy(schemaFile, schemaFileWithXsdSuffix); } catch (IOException e) { throw new MojoFailureException("Failed to copy to " + schemaFileWithXsdSuffix); } } } } String xsdDirNameFor(final String namespaceUri) { final String sanitized = sanitize(namespaceUri); final String sanitizedElseUnnamed = Strings.isNullOrEmpty(sanitized) ? ("unnamed-" + (unnamed++)) : sanitized; return sanitizedElseUnnamed; } private static String sanitize(final String namespaceUri) { String sanitized = namespaceUri; sanitized = removePrefix(sanitized, "http://"); sanitized = removePrefix(sanitized, "https://"); sanitized = sanitized.replaceAll(":", "_"); return sanitized.replaceAll("[\\\\\\/]", File.separator + File.separator); } private static String removePrefix(final String str, final String prefix) { return str.startsWith(prefix)? str.substring(prefix.length()): str; } }