View Javadoc

1   package net.sf.jlayercheck.out.html;
2   
3   
4   import java.io.File;
5   import java.io.IOException;
6   import java.net.URL;
7   import java.util.ArrayList;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  import java.util.StringTokenizer;
12  
13  import net.sf.jlayercheck.util.io.IOHelper;
14  import de.java2html.Java2Html;
15  import de.java2html.options.JavaSourceConversionOptions;
16  
17  /**
18   * Generates the decorated source code as HTML.
19   */
20  public class SourceCodeDecorator {
21  	
22  	/** Name of this package */
23  	public static final String PACKAGE = SourceCodeDecorator.class.getPackage().getName();
24  	
25  	/** Template to use */
26  	public static final String TEMPLATENAME = PACKAGE + ".decoratedSource";
27  	
28  	// fields
29  	// ----------------------------------------------------------------------
30  	
31  	/** The generator to use */
32  	protected VelocityGenerator generator;
33  	
34  	/** The output directory */
35  	protected File outputDir;
36  	
37  	/** The output file, not necessarily in {@link #outputDir} */
38  	protected File outputFile;
39  
40  	// construction
41  	// ----------------------------------------------------------------------
42  
43  	public SourceCodeDecorator(File outputDir, File outputFile) {
44  		super();
45  		setOutputDir(outputDir);
46  		setOutputFile(outputFile);
47  		
48  		generator = new VelocityGenerator();
49  		prepareContext();
50  	}
51  	
52  	// methods
53  	// ----------------------------------------------------------------------
54  
55  	public void setOutputFile(File outputFile) {
56  		this.outputFile = outputFile;
57  	}
58  
59  	public File getOutputFile() {
60  		return outputFile;
61  	}
62  
63  	public void setOutputDir(File outputDir) {
64  		this.outputDir = outputDir;
65  	}
66  
67  	public File getOutputDir() {
68  		return outputDir;
69  	}
70  
71  	// template methods
72  	// ----------------------------------------------------------------------
73  	
74  	/**
75  	 * Prepare velocity context for generator and template.
76  	 */
77  	protected void prepareContext() {
78  		Map<String, Object> addCtx = new HashMap<String, Object>();
79  		
80  		// make this object available in template
81  		addCtx.put("tool", this); //$NON-NLS-1$
82  		
83  		addCtx.put("outputDir", getOutputDir());
84  		addCtx.put("outputFile", getOutputFile());
85  		addCtx.put("filename", getOutputFile().getName());
86  		
87  		generator.addToContext(addCtx);
88  	}
89  
90  	/**
91  	 * Use java2html to parse the source.
92  	 * 
93  	 * @param sourcefile
94  	 *            The {@link URL} of the java source file
95  	 * @return The source as HTML
96  	 */
97  	public String convert2HTML(URL sourcefile) throws IOException {
98  		String ret = null;
99  		// read source file completely into String
100 		String content = IOHelper.readContent(sourcefile);
101 		JavaSourceConversionOptions options = JavaSourceConversionOptions
102 				.getDefault();
103 		options.setShowLineNumbers(true);
104 		// convert source code to html 
105 		ret = Java2Html.convertToHtml(content, options);
106 		return ret;
107 	}
108 	
109 	/**
110 	 * Separates source lines from java2html's HTML code.
111 	 * @param htmlCode the HTML code
112 	 * @return A list of source lines as HTML fragments
113 	 */
114 	public List<String> parseHTML(String htmlCode) {
115 		if (htmlCode == null) {
116 			throw new NullPointerException("htmlCode must not be null!");
117 		}
118 		if ("".equals(htmlCode)) {
119 			throw new IllegalArgumentException("htmlCode must be set properly!");
120 		}
121 		
122 		List<String> ret = new ArrayList<String>();
123 		
124 		// All source code lines are embraced by <code>
125 		String content = htmlCode;
126 		int startPos = content.indexOf("<code"); //$NON-NLS-1$
127 		int endPos = content.lastIndexOf("</code", startPos + 1); //$NON-NLS-1$
128 		if (startPos < 0 || endPos < 0 || endPos <= startPos) {
129 			throw new IllegalArgumentException("Cannot parse htmlCode!");
130 		}
131 		// start after closing <code ... > tag
132 		startPos = content.indexOf('>', startPos);
133 		
134 		// parse source code lines only
135 		content = content.substring(startPos, endPos - 1);
136 		// lines are split by <br />
137 		StringTokenizer tokens = new StringTokenizer(content, "<br"); //$NON-NLS-1$
138 		while (tokens.hasMoreTokens()) {
139 			String token = tokens.nextToken();
140 			// use fragment after closed tag
141 			int bPos = token.indexOf('>');
142 			if (bPos < 0) {
143 				throw new IllegalArgumentException("Cannot parse htmlCode in line " + ret.size());
144 			}
145 			token = token.substring(bPos);
146 			ret.add(token);
147 		}
148 		
149 		return ret;
150 	}
151 	
152 	public void generate() {
153 		
154 	}
155 
156 	// template methods
157 	// ----------------------------------------------------------------------
158 
159 	/**
160 	 * Copy resource to {@link #outputDir}.
161 	 * @param resourcename the resource
162 	 * @return always <code>null</code>
163 	 */
164 	public Object copyResource(String resourcename) {
165 		File out = new File(outputDir, resourcename);
166 		IOHelper.copy(getClass().getResource(resourcename), out);
167 		return null;
168 	}
169 }