1
2 package net.sf.dtddoc.maven2;
3
4 import java.io.File;
5 import java.io.IOException;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Locale;
12 import java.util.Set;
13
14 import DTDDoc.DTDCommenter;
15
16 import org.apache.maven.doxia.sink.Sink;
17 import org.apache.maven.doxia.siterenderer.Renderer;
18 import org.apache.maven.project.MavenProject;
19 import org.apache.maven.reporting.AbstractMavenReport;
20 import org.apache.maven.reporting.MavenReportException;
21 import org.codehaus.plexus.util.FileUtils;
22 import org.codehaus.plexus.util.StringUtils;
23
24 /**
25 * DTDDoc Maven2 plugin.
26 * @goal dtddoc
27 * @description Generates DTDDoc report
28 * @version $Id: DTDDocReport.java,v 1.12 2006/10/28 08:30:45 hboutemy Exp $
29 */
30 public class DTDDocReport extends AbstractMavenReport {
31 /**
32 * Specifies the destination directory where DTDDoc saves the generated HTML files.
33 *
34 * @parameter expression="${project.build.directory}/dtddoc/"
35 */
36 private File outputDirectory;
37
38 /**
39 * Specifies the source directory where DTDDoc searches for DTDs.
40 *
41 * @parameter expression="src/main/resources"
42 */
43 private File sourceDirectory;
44
45 /**
46 * List of patterns used to specify the files that should be included in DTD documentation.
47 * When not specified, the default includes will be <code>**/*.dtd</code>.
48 *
49 * @parameter
50 */
51 private String[] includes;
52
53 /**
54 * List of patterns used to specify the files that should be excluded in DTD documentation.
55 * When not specified, the default excludes will be empty.
56 *
57 * @parameter
58 */
59 private String[] excludes;
60
61 /**
62 * Tells if the content of the <code>@hidden</code> tags must be part of the documentation
63 * @parameter expression="${dtddoc.hidden}" default-value="false"
64 */
65 private boolean showHiddenTags = false;
66
67 /**
68 * Tells if the content of the <code>@fixme</code> tags must be part of the documentation
69 * @parameter expression="${dtddoc.fixme}" default-value="true"
70 */
71 private boolean showFixmeTags = true;
72
73 /**
74 * In case you have comments that start with three hyphens, this option will tell DTDDoc
75 * to interpret them as regular double hyphens. This was introduced to support NetBeans comments.
76 * @parameter expression="${dtddoc.getAroundNetBeansComments}" default-value="true"
77 */
78 private boolean getAroundNetBeansComments = true;
79
80 /**
81 * Name of the documentation: it will appear at the top of the index.
82 * @parameter expression="${dtddoc.title}" default-value=""
83 */
84 private String docTitle = "";
85
86 /**
87 * The stylesheet to use to render the documentation. This stylesheet will be copied into the documentation.
88 * If not specified, DTDDoc's default stylesheet is used.
89 * @parameter expression="${dtddoc.styleSheet}"
90 */
91 private File styleSheet = null;
92
93 /**
94 * Doxia Site Renderer.
95 *
96 * @component
97 */
98 protected Renderer siteRenderer;
99
100 /**
101 * Maven project
102 * @parameter expression="${project}"
103 * @required
104 * @readonly
105 */
106 private MavenProject project;
107
108 public String getName(Locale locale) {
109 return "DTDDoc";
110 }
111
112 public String getDescription(Locale locale) {
113 return "DTD documentation";
114 }
115
116 /**
117 * @see org.apache.maven.reporting.MavenReport#getOutputName()
118 */
119 public String getOutputName() {
120 return "dtddoc/index";
121 }
122
123 /**
124 * @see org.apache.maven.reporting.AbstractMavenReport#getOutputDirectory()
125 */
126 protected String getOutputDirectory() {
127 return outputDirectory.getAbsoluteFile().toString();
128 }
129
130 /**
131 * @see org.apache.maven.reporting.AbstractMavenReport#getProject()
132 */
133 protected MavenProject getProject() {
134 return project;
135 }
136
137 /**
138 * @see org.apache.maven.reporting.AbstractMavenReport#getSiteRenderer()
139 */
140 protected Renderer getSiteRenderer() {
141 return siteRenderer;
142 }
143
144 /**
145 * @see org.apache.maven.reporting.MavenReport#generate(org.codehaus.doxia.sink.Sink, java.util.Locale)
146 */
147 public void generate(Sink sink, Locale locale) throws MavenReportException {
148 executeReport(locale);
149 }
150
151 private List getDtdFiles() {
152 if (! (sourceDirectory.exists() && sourceDirectory.isDirectory())) {
153 return new ArrayList();
154 }
155
156 String includesAsString = "**/*.dtd";
157 if (includes != null) {
158 includesAsString = StringUtils.join(includes, "," );
159 }
160
161 String excludesAsString = "";
162 if (excludes != null) {
163 excludesAsString = StringUtils.join(excludes, "," );
164 }
165
166 try {
167 return FileUtils.getFiles(sourceDirectory, includesAsString, excludesAsString, true);
168 } catch (IOException ioe) {
169 getLog().warn("unable to determine which DTDs to process", ioe);
170 }
171 return new ArrayList();
172 }
173
174 protected void executeReport(Locale locale) throws MavenReportException {
175 Set dtds = new HashSet(getDtdFiles());
176
177 File dtddocDirectory = getReportOutputDirectory();
178 if (!dtddocDirectory.getAbsolutePath().equals(getOutputDirectory())) {
179
180
181 dtddocDirectory = new File(dtddocDirectory, "dtddoc");
182 }
183 dtddocDirectory.mkdirs();
184
185 try {
186 getLog().info("documenting " + dtds.size() + " DTD(s), show @hidden tags: " + showHiddenTags + ", show @fixme tags: " + showFixmeTags);
187 File commonBase = getCommonBase(sourceDirectory, dtds);
188 if (! sourceDirectory.equals(commonBase)) {
189 getLog().info("sourceDirectory optimized as " + commonBase.getPath());
190 }
191 DTDCommenter commenter = new DTDCommenter(new MavenLogger(getLog()));
192 commenter
193 .commentDTDs(dtds, commonBase, dtddocDirectory, showHiddenTags, showFixmeTags, getAroundNetBeansComments, docTitle, styleSheet);
194 } catch (IOException ioe) {
195 throw new MavenReportException("error while generating DTDDoc reports : " + ioe.getMessage(), ioe);
196 } catch (Exception e) {
197 throw new MavenReportException("error while generating DTDDoc reports : " + e.getMessage(), e);
198 }
199 }
200
201 public boolean isExternalReport() {
202 return true;
203 }
204
205 /**
206 * @see org.apache.maven.reporting.MavenReport#canGenerateReport()
207 */
208 public boolean canGenerateReport() {
209 return getDtdFiles().size() > 0;
210 }
211
212 protected static File[] getFileHierarchy(File from, File to) {
213 List hierarchy = new ArrayList();
214 hierarchy.add(to);
215 while (! to.equals(from)) {
216 to = to.getParentFile();
217 hierarchy.add(to);
218 }
219 Collections.reverse(hierarchy);
220 File[] files = new File[hierarchy.size()];
221 return (File[])hierarchy.toArray(files);
222 }
223
224 protected File getCommonBase(File sourceDirectory, Set files) {
225 if (files.size() == 1) {
226
227 return ((File)files.iterator().next()).getParentFile();
228 }
229
230 File[] base = null;
231 for (Iterator iter = files.iterator(); iter.hasNext(); ) {
232 File current = ((File)iter.next()).getParentFile();
233 File[] currentHierarchy = getFileHierarchy(sourceDirectory, current);
234 if (base == null) {
235 base = currentHierarchy;
236 } else {
237
238 int len = Math.min(base.length, currentHierarchy.length);
239 List newHierarchy = new ArrayList();
240 for (int i = 0; i < len; i++) {
241 File a = base[i];
242 File b = currentHierarchy[i];
243 if (a.equals(b)) {
244
245 newHierarchy.add(a);
246 } else {
247
248 if (newHierarchy.size() == 1) {
249
250 return sourceDirectory;
251 }
252 base = new File[newHierarchy.size()];
253 newHierarchy.toArray(base);
254 break;
255 }
256 }
257 }
258 }
259
260 return base[base.length - 1];
261 }
262 }