/** {@inheritDoc} */ @Override protected boolean performExecution() throws MojoExecutionException, MojoFailureException { boolean updateStaleFileTimestamp = false; try { // Setup the Tool's execution environment ToolExecutionEnvironment environment = null; try { // Create a LocaleFacet if the user has configured an explicit Locale for the tool. final LocaleFacet localeFacet = locale == null ? null : LocaleFacet.createFor(locale, getLog()); // Create the ToolExecutionEnvironment environment = new ToolExecutionEnvironment( getLog(), ThreadContextClassLoaderBuilder.createFor(this.getClass(), getLog()) .addPaths(getClasspath()), LoggingHandlerEnvironmentFacet.create(getLog(), getClass(), getEncoding(false)), localeFacet); // Add any extra configured EnvironmentFacets, as configured in the POM. if (extraFacets != null) { for (EnvironmentFacet current : extraFacets) { environment.add(current); } } // Setup the environment. environment.setup(); // Compile the XJC arguments final String[] xjcArguments = getXjcArguments(environment.getClassPathAsArgument(), STANDARD_EPISODE_FILENAME); // Ensure that the outputDirectory exists, but only clear it if does not already FileSystemUtilities.createDirectory(getOutputDirectory(), clearOutputDir); // Do we need to re-create the episode file's parent directory. final boolean reCreateEpisodeFileParentDirectory = generateEpisode && clearOutputDir; if (reCreateEpisodeFileParentDirectory) { getEpisodeFile(STANDARD_EPISODE_FILENAME); } // Check the system properties. logSystemPropertiesAndBasedir(); // Fire XJC if (XJC_COMPLETED_OK != Driver.run(xjcArguments, new XjcLogAdapter(getLog()))) { final StringBuilder errorMsgBuilder = new StringBuilder(); errorMsgBuilder.append("\n+=================== [XJC Error]\n"); errorMsgBuilder.append("|\n"); final List<URL> sourceXSDs = getSources(); for (int i = 0; i < sourceXSDs.size(); i++) { errorMsgBuilder .append("| " + i + ": ") .append(sourceXSDs.get(i).toString()) .append("\n"); } errorMsgBuilder.append("|\n"); errorMsgBuilder.append("+=================== [End XJC Error]\n"); throw new MojoExecutionException(errorMsgBuilder.toString()); } // Indicate that the output directory was updated. getBuildContext().refresh(getOutputDirectory()); // Update the modification timestamp of the staleFile. updateStaleFileTimestamp = true; } finally { if (environment != null) { environment.restore(); } } // Add the generated source root to the project, enabling tooling and other plugins to see // them. addGeneratedSourcesToProjectSourceRoot(); // Copy all source XSDs to the resulting artifact? if (xsdPathWithinArtifact != null) { final String buildOutputDirectory = getProject().getBuild().getOutputDirectory(); final File targetXsdDirectory = new File(buildOutputDirectory, xsdPathWithinArtifact); FileUtils.forceMkdir(targetXsdDirectory); for (URL current : getSources()) { String fileName = null; if ("file".equalsIgnoreCase(current.getProtocol())) { fileName = new File(current.getPath()).getName(); } else if ("jar".equalsIgnoreCase(current.getProtocol())) { // Typical JAR path // jar:file:/path/to/aJar.jar!/some/path/xsd/aResource.xsd final int bangIndex = current.toString().indexOf("!"); if (bangIndex == -1) { throw new MojoExecutionException( "Illegal JAR URL [" + current.toString() + "]: lacks a '!'"); } final String internalPath = current.toString().substring(bangIndex + 1); fileName = new File(internalPath).getName(); } else { throw new MojoExecutionException( "Could not extract FileName from URL [" + current + "]"); } final File targetFile = new File(targetXsdDirectory, fileName); if (targetFile.exists()) { // TODO: Should we throw an exception here instead? getLog() .warn( "File [" + FileSystemUtilities.getCanonicalPath(targetFile) + "] already exists. Not copying XSD file [" + current.getPath() + "] to it."); } IOUtil.copy(current.openStream(), new FileWriter(targetFile)); } // Refresh the BuildContext getBuildContext().refresh(targetXsdDirectory); } } catch (MojoExecutionException e) { throw e; } catch (NoSchemasException e) { if (failOnNoSchemas) { throw new MojoExecutionException("", e); } } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } // All done. return updateStaleFileTimestamp; }
private String[] getXjcArguments(final String classPath, final String episodeFileNameOrNull) throws MojoExecutionException, NoSchemasException { final ArgumentBuilder builder = new ArgumentBuilder(); // Add all flags on the form '-flagName' builder.withFlag(true, sourceType.getXjcArgument()); builder.withFlag(noPackageLevelAnnotations, "npa"); builder.withFlag(laxSchemaValidation, "nv"); builder.withFlag(verbose, "verbose"); builder.withFlag(quiet, "quiet"); builder.withFlag(enableIntrospection, "enableIntrospection"); builder.withFlag(extension, "extension"); builder.withFlag(readOnly, "readOnly"); builder.withFlag(noGeneratedHeaderComments, "no-header"); builder.withFlag(addGeneratedAnnotation, "mark-generated"); // Add all arguments on the form '-argumentName argumentValue' // (i.e. in 2 separate elements of the returned String[]) builder.withNamedArgument("httpproxy", getProxyString(settings.getActiveProxy())); builder.withNamedArgument("encoding", getEncoding(false)); builder.withNamedArgument("p", packageName); builder.withNamedArgument("target", target); builder.withNamedArgument("d", getOutputDirectory().getAbsolutePath()); builder.withNamedArgument("classpath", classPath); if (generateEpisode) { // We must use the -extension flag for the episode to work. if (!extension) { if (getLog().isInfoEnabled()) { getLog() .info( "Adding 'extension' flag to XJC arguments, since the 'generateEpisode' argument is " + "given. (XJCs 'episode' argument requires that the 'extension' argument is provided)."); } builder.withFlag(true, "extension"); } final File episodeFile = getEpisodeFile(episodeFileNameOrNull); builder.withNamedArgument("episode", FileSystemUtilities.getCanonicalPath(episodeFile)); } if (catalog != null) { builder.withNamedArgument("catalog", FileSystemUtilities.getCanonicalPath(catalog)); } if (arguments != null) { builder.withPreCompiledArguments(arguments); } for (File current : getSourceXJBs()) { // Shorten the argument? // final String strippedXjbPath = FileSystemUtilities.relativize( // current.getAbsolutePath(), getProject().getBasedir()); // Each XJB must be given as a separate argument. builder.withNamedArgument("-b", current.getAbsolutePath()); } final List<URL> sourceXSDs = getSources(); if (sourceXSDs.isEmpty()) { // If we have no XSDs, we are not going to be able to run XJC. getLog().warn("No XSD files found. Please check your plugin configuration."); throw new NoSchemasException(); } else { final List<String> unwrappedSourceXSDs = new ArrayList<String>(); for (URL current : sourceXSDs) { // Shorten the argument if possible. if ("file".equalsIgnoreCase(current.getProtocol())) { unwrappedSourceXSDs.add( FileSystemUtilities.relativize( current.getPath(), new File(System.getProperty("user.dir")))); } else { unwrappedSourceXSDs.add(current.toString()); } } builder.withPreCompiledArguments(unwrappedSourceXSDs); } // All done. return logAndReturnToolArguments(builder.build(), "XJC"); }
/** Java generation is required if any of the file products is outdated/stale. {@inheritDoc} */ @Override protected boolean isReGenerationRequired() { // // Use the stale flag method to identify if we should re-generate the java source code from the // supplied // Xml Schema. Basically, we should regenerate the JAXB code if: // // a) The staleFile does not exist // b) The staleFile exists and is older than one of the sources (XSD or XJB files). // "Older" is determined by comparing the modification timestamp of the staleFile and the // source files. // final File staleFile = getStaleFile(); final String debugPrefix = "StaleFile [" + FileSystemUtilities.getCanonicalPath(staleFile) + "]"; boolean stale = !staleFile.exists(); if (stale) { getLog().debug(debugPrefix + " not found. JAXB (re-)generation required."); } else { final List<URL> sourceXSDs = getSources(); final List<File> sourceXJBs = getSourceXJBs(); if (getLog().isDebugEnabled()) { getLog() .debug( debugPrefix + " found. Checking timestamps on source XSD and XJB " + "files to determine if JAXB (re-)generation is required."); } final long staleFileLastModified = staleFile.lastModified(); for (URL current : sourceXSDs) { final URLConnection sourceXsdConnection; try { sourceXsdConnection = current.openConnection(); sourceXsdConnection.connect(); } catch (Exception e) { // Can't determine if the staleFile is younger than this sourceXSD. // Re-generate to be on the safe side. stale = true; break; } try { if (sourceXsdConnection.getLastModified() > staleFileLastModified) { if (getLog().isDebugEnabled()) { getLog().debug(current.toString() + " is newer than the stale flag file."); } stale = true; } } finally { if (sourceXsdConnection instanceof HttpURLConnection) { ((HttpURLConnection) sourceXsdConnection).disconnect(); } } } for (File current : sourceXJBs) { if (current.lastModified() > staleFileLastModified) { if (getLog().isDebugEnabled()) { getLog() .debug( FileSystemUtilities.getCanonicalPath(current) + " is newer than the stale flag file."); } stale = true; break; } } } // All done. return stale; }