1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package no.sesat.search.view.velocity;
18
19 import java.io.*;
20
21 import javax.xml.parsers.DocumentBuilderFactory;
22 import javax.xml.parsers.ParserConfigurationException;
23 import javax.xml.transform.OutputKeys;
24 import javax.xml.transform.Transformer;
25 import javax.xml.transform.TransformerConfigurationException;
26 import javax.xml.transform.TransformerException;
27 import javax.xml.transform.TransformerFactory;
28 import javax.xml.transform.dom.DOMSource;
29 import javax.xml.transform.stream.StreamResult;
30 import org.apache.log4j.Logger;
31
32 import org.apache.velocity.exception.ResourceNotFoundException;
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35
36
37
38
39
40
41
42
43
44
45
46 public class URLVelocityTemplateLoader extends URLResourceLoader {
47
48 private static final Logger LOG = Logger.getLogger(URLVelocityTemplateLoader.class);
49
50 private static final String DIV_TAG = "div";
51 private static final String STYLE_ATTRIB = "style";
52 private static final String STYLE_BORDER = "margin:3px;border:1px solid #C0C0C0";
53 private static final String STYLE_HEADING="text-decoration:underline;font-size:10px";
54 private static final String ONMOUSEOVER = "this.style.border='1px solid #C0C0C0';this.style.margin='4px'";
55 private static final String ONMOUSEOUT = "this.style.border='none'";
56
57
58
59
60
61
62 @Override
63 public InputStream getResourceStream(final String url) throws ResourceNotFoundException {
64
65
66 final boolean velocityDebug = Boolean.getBoolean("VELOCITY_DEBUG");
67
68 final boolean velocityDebugOn = Boolean.getBoolean("VELOCITY_DEBUG_ON");
69
70 final boolean styleOnmouseover ="onmouseover".equals(System.getProperty("VELOCITY_DEBUG_STYLE"));
71
72 final boolean styleSilent ="silent".equals(System.getProperty("VELOCITY_DEBUG_STYLE"));
73
74 boolean foundLocal = false;
75
76 if(velocityDebug) {
77
78 final String templatesDir = System.getProperty("VELOCITY_DEVELOP_BASEDIR");
79
80
81 final String filePath = url.replaceAll("http://(.*?)/[^/]+/", "/").replace("localhost/", "");
82 final File file = getFile(templatesDir, filePath);
83
84 foundLocal = file.exists();
85
86 final InputStream stream = file.exists() ? getStream(file) : super.getResourceStream(url);
87
88 if(velocityDebugOn && -1 == url.indexOf("rss")){
89 StringBuilder content = this.readTemplateFrom(stream);
90
91
92 final StringBuilder template= new StringBuilder();
93 template.append("\n");
94 template.append(content);
95 template.append("\n");
96
97 final StringWriter writer = new StringWriter();
98 final Document doc = createDocument();
99
100 final Element div = doc.createElement(DIV_TAG);
101
102 if(styleOnmouseover) {
103
104 div.setAttribute("onmouseover", ONMOUSEOVER);
105 div.setAttribute("onmouseout", ONMOUSEOUT);
106
107 }else if(styleSilent){
108
109
110 }else {
111
112 final Element divHeader = doc.createElement(DIV_TAG);
113 divHeader.setAttribute(STYLE_ATTRIB, STYLE_HEADING);
114 divHeader.appendChild(doc.createTextNode(filePath));
115 div.appendChild(divHeader);
116 div.setAttribute("style", STYLE_BORDER);
117 }
118
119 div.setAttribute("title", file.getName() + (foundLocal ? "(Editable)" : "(Not editable)"));
120 div.appendChild(doc.createCDATASection(template.toString()));
121 doc.appendChild(div);
122
123 internalWriteDocument(doc, writer);
124
125 final String result = writer.getBuffer().toString()
126 .replace("<![CDATA[", "")
127 .replace("]]>", "");
128
129 return new ByteArrayInputStream(result.getBytes());
130
131 }else{
132
133 return stream;
134 }
135 }
136 return super.getResourceStream(url);
137 }
138
139
140
141
142
143
144 private StringBuilder readTemplateFrom(final InputStream is) {
145 StringBuilder builder = new StringBuilder();
146
147 try {
148 InputStreamReader isr = new InputStreamReader(is, "UTF8");
149 Reader in = new BufferedReader(isr);
150 int ch;
151 while ((ch = in.read()) > -1) {
152 builder.append((char)ch);
153 }
154 in.close();
155 } catch (IOException e) {
156 LOG.error(e);
157 }
158 return builder;
159 }
160
161
162
163
164 private File getFile(final String templatesDir, final String filePath) {
165
166 File result = null;
167
168 if(null == templatesDir) {
169 result = new File("null" + filePath);
170
171 }else{
172 for(String p : templatesDir.split(",")) {
173
174 final File file = new File(p + filePath);
175 if(file.exists()) {
176 result = file;
177 break;
178 }
179 }
180 }
181
182 return null == result ? new File(filePath) : result;
183 }
184
185
186
187
188 private InputStream getStream(final File file) {
189
190 if (file.exists()) {
191
192 try {
193 FileInputStream fileStream = new FileInputStream(file);
194 return fileStream;
195
196 } catch (FileNotFoundException ignore) {
197 throw new IllegalStateException("File exist but filenotfoundexception thrown: " + ignore);
198 }
199
200 } else {
201 throw new IllegalArgumentException("File does not exist");
202 }
203 }
204
205
206 private void internalWriteDocument(final Document d, final Writer w) {
207
208 final DOMSource source = new DOMSource(d);
209 final StreamResult result = new StreamResult(w);
210
211 final TransformerFactory factory = TransformerFactory.newInstance();
212
213 try {
214 final Transformer transformer = factory.newTransformer();
215 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
216 transformer.transform(source, result);
217
218 } catch (TransformerConfigurationException e) {
219 throw new RuntimeException("Xml Parser: " + e);
220
221 } catch (TransformerException ignore) {
222 LOG.debug("Ingoring the following ", ignore);
223 }
224 }
225
226
227 private Document createDocument() {
228
229 final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
230
231 try {
232 return docFactory.newDocumentBuilder().newDocument();
233
234 } catch (ParserConfigurationException e) {
235 throw new RuntimeException(e);
236 }
237 }
238 }