001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.camel.maven;
019
020 import org.apache.maven.plugin.AbstractMojo;
021 import org.apache.maven.plugin.MojoExecutionException;
022
023 import java.io.File;
024 import java.io.FileOutputStream;
025 import java.io.IOException;
026 import java.io.BufferedInputStream;
027 import java.io.BufferedOutputStream;
028 import java.io.FileWriter;
029 import java.io.ByteArrayOutputStream;
030 import java.io.InputStream;
031 import java.io.PrintWriter;
032 import java.util.ArrayList;
033 import java.util.Iterator;
034 import java.util.List;
035 import java.util.StringTokenizer;
036 import java.net.URL;
037 import java.net.URLConnection;
038
039 import javax.xml.transform.Transformer;
040 import javax.xml.transform.TransformerFactory;
041 import javax.xml.transform.dom.DOMSource;
042 import javax.xml.transform.stream.StreamResult;
043 import javax.xml.transform.stream.StreamSource;
044
045 import org.w3c.dom.Element;
046 import org.w3c.dom.NodeList;
047 import org.w3c.dom.Document;
048 import org.w3c.dom.Node;
049 import org.w3c.dom.NamedNodeMap;
050
051 import org.w3c.tidy.DOMElementImpl;
052 import org.w3c.tidy.Tidy;
053
054 /**
055 * Goal which extracts the content of a wiki page and converts it to docbook
056 * format
057 *
058 * @goal htmlToDocbook
059 * @phase process-sources
060 */
061 public class GenerateDocBookMojo extends AbstractMojo {
062
063 /**
064 * Base URL.
065 *
066 * @parameter expression="${baseURL}"
067 * default-value="http://activemq.apache.org/camel/"
068 * @required
069 */
070 private String baseURL;
071
072 /**
073 * List of resources
074 *
075 * @parameter
076 */
077 private String[] resources;
078
079 /**
080 * List of author's fullname
081 *
082 * @parameter
083 */
084 private String[] authors;
085
086 /**
087 * Location of the xsl file.
088 *
089 * @parameter expression="${configDirectory}"
090 * default-value="${basedir}/src/styles/docbook.xsl"
091 * @required
092 */
093 private String xslFile;
094
095 /**
096 * Location of the output directory.
097 *
098 * @parameter expression="${project.build.directory}/docbkx/docbkx-source"
099 */
100 private String outputPath;
101
102 /**
103 * Location of the output directory for wiki source.
104 *
105 * @parameter expression="${project.build.directory}/docbkx/wiki-source"
106 */
107 private String wikiOutputPath;
108
109 /**
110 * @parameter expression="${title}"
111 * @required
112 */
113 private String title;
114
115 /**
116 * @parameter expression="${subtitle}"
117 */
118 private String subtitle;
119
120 /**
121 * @parameter expression="${mainFilename}" default-value="manual"
122 * @required
123 */
124 private String mainFilename;
125
126 /**
127 * @parameter expression="${version}" default-value="${project.version}"
128 */
129 private String version;
130
131 /**
132 * @parameter expression="${legalNotice}"
133 */
134 private String legalNotice;
135
136 /**
137 * Location of image files.
138 *
139 * @parameter expression="${project.build.directory}/site/book/images"
140 *
141 */
142 private String imageLocation;
143
144 private String chapterId;
145
146
147 public void execute() throws MojoExecutionException {
148 File outputDir = new File(outputPath);
149 File wikiOutputDir = new File(wikiOutputPath);
150 File imageDir = new File(imageLocation);
151 if (!outputDir.exists()) {
152 outputDir.mkdirs();
153 imageDir.mkdirs();
154 wikiOutputDir.mkdirs();
155 }
156 this.createMainXML();
157
158 for (int i = 0; i < resources.length; ++i) {
159 this.setChapterId( removeExtension(resources[i]));
160
161 process(resources[i]);
162 }
163
164 }
165
166
167 /**
168 * Extract the wiki content and tranform it into docbook format
169 *
170 * @param resource
171 */
172 public void process(String resource) {
173
174 Tidy tidy = new Tidy();
175 ByteArrayOutputStream out = null;
176 BufferedOutputStream output = null;
177 BufferedOutputStream wikiOutput = null;
178
179 tidy.setXmlOut(true);
180 try {
181 out = new ByteArrayOutputStream();
182 URL u = new URL(baseURL + resource);
183 Document doc = tidy.parseDOM(
184 new BufferedInputStream(u.openStream()), out);
185 out.close();
186 // let's extract the div element with class="wiki-content
187 // maincontent"
188 NodeList nodeList = doc.getElementsByTagName("div");
189 for (int i = 0; i < nodeList.getLength(); ++i) {
190 Node node = nodeList.item(i);
191
192 NamedNodeMap nm = node.getAttributes();
193 Node attr = nm.getNamedItem("class");
194
195 if (attr != null
196 && attr.getNodeValue().equalsIgnoreCase(
197 "wiki-content maincontent")) {
198 downloadImages(node);
199 // These attributes will be used by xsl to
200 Element element = (Element) node;
201 element.setAttribute("chapterId", chapterId);
202 element.setAttribute("baseURL", baseURL);
203 element.setAttribute("imageLocation", "../images/");
204
205 DOMSource source = new DOMSource(node);
206
207
208 output = new BufferedOutputStream(
209 new FileOutputStream(outputPath + File.separator
210 + removeExtension(resource) + ".xml"));
211 StreamResult result = new StreamResult(output);
212 TransformerFactory tFactory = TransformerFactory
213 .newInstance();
214 Transformer transformer = tFactory
215 .newTransformer(new StreamSource(xslFile));
216 transformer.transform(source, result);
217
218 // generate the wiki source for debugging
219 wikiOutput = new BufferedOutputStream(
220 new FileOutputStream(wikiOutputPath + File.separator
221 + removeExtension(resource) + ".html"));
222 result = new StreamResult(wikiOutput);
223 transformer = tFactory.newTransformer();
224 transformer.transform(source, result);
225
226 break;
227 }
228
229 }
230
231 } catch (Exception e) {
232 e.printStackTrace();
233 }finally {
234 try {
235 if(output != null)
236 output.close();
237 } catch (IOException e) {
238 // TODO Auto-generated catch block
239 e.printStackTrace();
240 }
241 }
242 }
243
244
245 /*
246 * create the main docbook xml file
247 */
248 public void createMainXML() {
249 try {
250
251 PrintWriter out = new PrintWriter(new FileWriter(outputPath
252 + File.separator + mainFilename + ".xml"));
253
254 out
255 .println("<!DOCTYPE book PUBLIC \"-//OASIS//DTD DocBook XML V4.4//EN\" \"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd\" ");
256 out.println("[");
257
258 for (int i = 0; i < resources.length; ++i) {
259 out.println("<!ENTITY " + removeExtension(resources[i]) + " SYSTEM \"" + removeExtension(resources[i])
260 + ".xml\">");
261 }
262
263 out.println("]>");
264 out.println("<book>");
265 out.println("<bookinfo>");
266 out.println("<title>" + title + "</title>");
267 out.println("<subtitle>" + subtitle + "</subtitle>");
268 out.println("<releaseinfo>" + version + "</releaseinfo>");
269 out.println(" <authorgroup>");
270 if (authors != null) {
271 for (int i = 0; i < authors.length; ++i) {
272 StringTokenizer name = new StringTokenizer(authors[i]);
273 String fname = name.nextToken();
274 String lname = "";
275 if (name.hasMoreTokens()) {
276 lname = name.nextToken();
277 }
278 out.println("<author>");
279 out.println("<firstname>" + fname + "</firstname>");
280 out.println("<surname>" + lname + "</surname>");
281 out.println("</author>");
282
283 }
284 }
285
286 out.println("</authorgroup>");
287 out.println("<legalnotice>");
288 if (legalNotice != null && legalNotice.length() > 0) {
289 out.println("<para>");
290 out.println(legalNotice);
291 out.println("</para>");
292 } else {
293 out
294 .println("<para>Licensed to the Apache Software Foundation (ASF) under one or more");
295 out
296 .println("contributor license agreements. See the NOTICE file distributed with");
297 out
298 .println("this work for additional information regarding copyright ownership. The");
299 out
300 .println("ASF licenses this file to You under the Apache License, Version 2.0 (the");
301 out
302 .println("\"License\"); you may not use this file except in compliance with the");
303 out
304 .println("License. You may obtain a copy of the License at</para>");
305 out
306 .println("<para>http://www.apache.org/licenses/LICENSE-2.0</para>");
307 out
308 .println("<para>Unless required by applicable law or agreed to in writing,");
309 out
310 .println(" software distributed under the License is distributed on an \"AS IS\"");
311 out
312 .println("BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or");
313 out
314 .println("implied. See the License for the specific language governing permissions");
315 out.println("and limitations under the License.</para>");
316 }
317
318 out.println("</legalnotice>");
319 out.println("</bookinfo>");
320 out.println("<toc></toc>");
321
322 for (int i = 0; i < resources.length; ++i) {
323 out.println("&" + removeExtension(resources[i]) + ";");
324 }
325
326 out.println("</book>");
327 out.flush();
328 out.close();
329
330 } catch (IOException e) {
331 // TODO Auto-generated catch block
332 e.printStackTrace();
333 }
334 }
335
336
337 public void downloadImages(Node node) {
338 List imageList = getImageUrls(node);
339 Iterator iter = imageList.iterator();
340 while(iter.hasNext()) {
341 String imageUrl = (String)iter.next();
342 String imageFile = "imageFile";
343
344 //check if url path is relative
345 if (imageUrl.indexOf("http://") < 0) {
346 imageUrl = baseURL + imageUrl;
347 }
348 try {
349
350 URL url = new URL(imageUrl);
351 StringTokenizer st=new StringTokenizer(url.getFile(), "/");
352 while (st.hasMoreTokens()) {
353 imageFile=st.nextToken();
354 }
355
356 URLConnection connection = url.openConnection();
357 InputStream stream = connection.getInputStream();
358 BufferedInputStream in = new BufferedInputStream(stream);
359 FileOutputStream file = new FileOutputStream(imageLocation + File.separator + imageFile);
360 BufferedOutputStream out = new BufferedOutputStream(file);
361 int i;
362 while ((i = in.read()) != -1) {
363 out.write(i);
364 }
365 out.flush();
366 }catch(Exception e) {
367 e.printStackTrace();
368 }
369
370
371 }
372 }
373
374
375 public List getImageUrls(Node node) {
376 ArrayList list = new ArrayList();
377 DOMElementImpl doc = (DOMElementImpl)node;
378 NodeList imageList = doc.getElementsByTagName("img");
379
380 if (imageList != null) {
381 for (int i=0; i<imageList.getLength(); ++i) {
382 Node imageNode = imageList.item(i);
383
384 NamedNodeMap nm = imageNode.getAttributes();
385 Node attr = nm.getNamedItem("src");
386 if(attr != null) {
387 list.add(attr.getNodeValue());
388 }
389
390 }
391 }
392 return list;
393 }
394
395 public String getChapterId() {
396 return chapterId;
397 }
398
399 public void setChapterId(String chapterId) {
400 this.chapterId = chapterId;
401 }
402
403
404 public String removeExtension(String resource) {
405 int index = resource.indexOf('.');
406 return resource.substring(0, index);
407 }
408 }