001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2013-2014 ForgeRock AS 015 */ 016 017package org.forgerock.doc.maven.pre; 018 019import org.apache.commons.io.FileUtils; 020import org.apache.commons.io.FilenameUtils; 021import org.apache.maven.plugin.MojoExecutionException; 022import org.codehaus.plexus.util.xml.Xpp3Dom; 023import org.forgerock.doc.maven.AbstractDocbkxMojo; 024import org.forgerock.doc.maven.utils.FilteredFileCopier; 025import org.twdata.maven.mojoexecutor.MojoExecutor; 026 027import java.io.File; 028import java.io.IOException; 029 030/** 031 * Use <a href="http://arrenbrecht.ch/jcite/">JCite</a> to quote Java code. 032 * 033 * <p> 034 * 035 * This class generates source including the citations. 036 * For example, if your DocBook source file includes 037 * the following <programlisting>: 038 * 039 * <pre> 040 * <programlisting language="java" 041 * >[jcp:org.forgerock.doc.jcite.test.Test:--- mainMethod]</programlisting> 042 * </pre> 043 * 044 * <p> 045 * 046 * Then this class replaces the citation with the code 047 * in between {@code // --- mainMethod} comments, 048 * suitable for inclusion in XML, 049 * and leaves the new file with the modifiable copy of the sources 050 * for further processing. 051 */ 052public class JCite { 053 054 /** 055 * The Mojo that holds configuration and related methods. 056 */ 057 private AbstractDocbkxMojo m; 058 059 /** 060 * The Executor to run JCite. 061 */ 062 private final Executor executor; 063 064 /** 065 * Constructor setting the Mojo that holds the configuration. 066 * 067 * @param mojo The Mojo that holds the configuration. 068 */ 069 public JCite(final AbstractDocbkxMojo mojo) { 070 m = mojo; 071 this.executor = new Executor(); 072 sourceDir = m.path(m.getDocbkxModifiableSourcesDirectory()); 073 tempOutputDirectory = new File(m.getBuildDirectory(), "docbkx-jcite"); 074 outputDir = m.path(tempOutputDirectory); 075 } 076 077 // JCite the sources in the modifiable copy. 078 private final String sourceDir; 079 080 // JCite to a temporary directory. 081 private final File tempOutputDirectory; 082 private final String outputDir; 083 084 /** 085 * Run JCite on the XML source files. 086 * 087 * @throws MojoExecutionException Failed to run JCite. 088 */ 089 public void execute() throws MojoExecutionException { 090 091 // JCite to a temporary directory... 092 executor.runJCite(); 093 094 // ...and then overwrite the copy of sources with the new files. 095 try { 096 FilteredFileCopier.copyOthers( 097 ".xml", m.getDocbkxModifiableSourcesDirectory(), tempOutputDirectory); 098 FileUtils.copyDirectory(tempOutputDirectory, m.getDocbkxModifiableSourcesDirectory()); 099 FileUtils.deleteDirectory(tempOutputDirectory); 100 } catch (IOException e) { 101 throw new MojoExecutionException(e.getMessage(), e); 102 } 103 } 104 105 /** 106 * Enclose methods to run plugins. 107 */ 108 class Executor extends MojoExecutor { 109 110 /** 111 * Run JCite on the DocBook XML source files. 112 * 113 * @throws MojoExecutionException Failed to run JCite. 114 */ 115 void runJCite() throws MojoExecutionException { 116 117 // mojo-executor lacks fluent support for element attributes. 118 // You can hack around this by including attributes 119 // in the name of elements without children. 120 // But the hack does not work for elements with children: 121 // SAX barfs on closing tags containing a bunch of attributes. 122 Xpp3Dom mkdir = new Xpp3Dom("mkdir"); 123 mkdir.setAttribute("dir", outputDir); 124 125 Xpp3Dom taskdef = new Xpp3Dom("taskdef"); 126 taskdef.setAttribute("name", "jcite"); 127 taskdef.setAttribute("classname", "ch.arrenbrecht.jcite.JCiteTask"); 128 taskdef.setAttribute("classpathref", "maven.plugin.classpath"); 129 130 Xpp3Dom jcite = new Xpp3Dom("jcite"); 131 jcite.setAttribute("srcdir", sourceDir); 132 jcite.setAttribute("destdir", outputDir); 133 134 // Might have multiple paths to sources. 135 Xpp3Dom sourcepath = new Xpp3Dom("sourcepath"); 136 if (m.getJCiteSourcePaths() != null && !m.getJCiteSourcePaths().isEmpty()) { 137 for (File sourcePath : m.getJCiteSourcePaths()) { 138 String location = FilenameUtils 139 .separatorsToSystem(sourcePath.getPath()); 140 Xpp3Dom pathelement = new Xpp3Dom("pathelement"); 141 pathelement.setAttribute("location", location); 142 sourcepath.addChild(pathelement); 143 } 144 } else { // No source path defined. Try src/main/java. 145 Xpp3Dom pathelement = new Xpp3Dom("pathelement"); 146 pathelement.setAttribute("location", "src/main/java"); 147 sourcepath.addChild(pathelement); 148 } 149 jcite.addChild(sourcepath); 150 151 Xpp3Dom include = new Xpp3Dom("include"); 152 include.setAttribute("name", "**/*.xml"); 153 jcite.addChild(include); 154 155 Xpp3Dom target = new Xpp3Dom("target"); 156 target.addChild(mkdir); 157 target.addChild(taskdef); 158 target.addChild(jcite); 159 160 Xpp3Dom configuration = new Xpp3Dom("configuration"); 161 configuration.addChild(target); 162 163 executeMojo( 164 plugin( 165 groupId("org.apache.maven.plugins"), 166 artifactId("maven-antrun-plugin"), 167 version("1.7"), 168 dependencies( 169 dependency( 170 // See https://code.google.com/r/markcraig-jcite/. 171 groupId("org.mcraig"), 172 artifactId("jcite"), 173 version(m.getJCiteVersion())))), 174 goal("run"), 175 configuration, 176 executionEnvironment(m.getProject(), m.getSession(), m.getPluginManager())); 177 } 178 } 179}