1 37 package net.sourceforge.cruisecontrol.taglib; 38 39 import java.io.BufferedReader ; 40 import java.io.File ; 41 import java.io.FileInputStream ; 42 import java.io.FileOutputStream ; 43 import java.io.IOException ; 44 import java.io.InputStream ; 45 import java.io.InputStreamReader ; 46 import java.io.OutputStream ; 47 import java.io.Reader ; 48 import java.io.Writer ; 49 import java.net.URL ; 50 import java.net.URLConnection ; 51 import java.util.Enumeration ; 52 import java.util.HashMap ; 53 import java.util.Iterator ; 54 import java.util.Map ; 55 56 import javax.servlet.ServletConfig ; 57 import javax.servlet.ServletContext ; 58 import javax.servlet.jsp.JspException ; 59 import javax.servlet.jsp.JspTagException ; 60 import javax.xml.transform.Transformer ; 61 import javax.xml.transform.TransformerException ; 62 import javax.xml.transform.TransformerFactory ; 63 import javax.xml.transform.stream.StreamResult ; 64 import javax.xml.transform.stream.StreamSource ; 65 66 import net.sourceforge.cruisecontrol.LogFile; 67 import net.sourceforge.cruisecontrol.util.CCTagException; 68 69 76 public class XSLTag extends CruiseControlTagSupport { 77 private static final String XSLT_PARAMETER_PREFIX = "xslt."; 78 private String xslFileName; 79 private static final String CACHE_DIR = "_cache"; 80 81 public void release() { 82 xslFileName = null; 83 } 84 85 86 93 protected void transform(LogFile xmlFile, URL style, OutputStream out) throws JspTagException { 94 InputStream in = null; 95 96 try { 97 TransformerFactory tFactory = TransformerFactory.newInstance(); 98 Transformer transformer = tFactory.newTransformer(new StreamSource (style.toExternalForm())); 99 Map parameters = getXSLTParameters(); 100 if (!parameters.isEmpty()) { 101 transformer.clearParameters(); 102 for (Iterator i = parameters.entrySet().iterator(); i.hasNext(); ) { 103 Map.Entry entry = (Map.Entry ) i.next(); 104 transformer.setParameter((String ) entry.getKey(), entry.getValue()); 105 } 106 } 107 108 try { 109 in = xmlFile.getInputStream(); 110 } catch (IOException ioex) { 111 err(ioex); 112 throw new CCTagException("Cannot read logfile: " 113 + ioex.getMessage(), ioex); 114 } 115 transformer.transform(new StreamSource (in), new StreamResult (out)); 116 } catch (ArrayIndexOutOfBoundsException e) { 117 err(e); 118 throw new CCTagException("Error transforming '" + xmlFile.getName() 119 + "'. You might be experiencing XML parser issues." 120 + " Are your xalan & xerces jar files mismatched? Check your JVM version. " 121 + e.getMessage(), e); 122 } catch (TransformerException e) { 123 err(e); 124 throw new CCTagException("Error transforming '" + xmlFile.getName() 125 + "': " + e.getMessage(), e); 126 } finally { 127 closeQuietly(in); 128 } 129 } 130 131 137 protected boolean isCacheFileCurrent(File xmlFile, File cacheFile) { 138 if (!cacheFile.exists() || cacheFile.length() == 0) { 139 return false; 140 } 141 boolean isCurrent = false; 142 long xmlLastModified = xmlFile.lastModified(); 143 long cacheLastModified = cacheFile.lastModified(); 144 try { 145 URL xslUrl = getPageContext().getServletContext().getResource(xslFileName); 146 URLConnection con = xslUrl.openConnection(); 147 long xslLastModified = con.getLastModified(); 148 isCurrent = (cacheLastModified > xmlLastModified) && (cacheLastModified > xslLastModified); 149 } catch (Exception e) { 150 err("Failed to retrieve lastModified of xsl file " + xslFileName); 151 } 152 return isCurrent; 153 } 154 155 161 protected void serveCachedCopy(File cacheFile, Writer out) throws JspTagException { 162 try { 163 InputStream input = new FileInputStream (cacheFile); 164 copy(input, out); 165 } catch (IOException e) { 166 err(e); 167 throw new CCTagException("Error reading file '" 168 + cacheFile.getName() + "': " + e.getMessage(), e); 169 } 170 } 171 172 private void copy(InputStream input, Writer out) throws IOException { 173 BufferedReader in; 174 in = new BufferedReader (new InputStreamReader (input, "UTF-8")); 175 176 try { 177 char[] cbuf = new char[8192]; 178 while (true) { 179 int charsRead = in.read(cbuf); 180 if (charsRead == -1) { 181 break; 182 } 183 out.write(cbuf, 0, charsRead); 184 } 185 } finally { 186 closeQuietly(in); 187 } 188 } 189 190 197 protected String getCachedCopyFileName(File xmlFile) { 198 String xmlFileName = xmlFile.getName().substring(0, xmlFile.getName().lastIndexOf(".")); 199 200 int slashIndex = xslFileName.lastIndexOf("/"); 203 String styleSheetName = xslFileName.substring(slashIndex + 1, xslFileName.lastIndexOf(".")); 204 return xmlFileName + "-" + styleSheetName + ".html"; 205 } 206 207 Map getXSLTParameters() { 208 Map xsltParameters = new HashMap (); 209 ServletConfig config = pageContext.getServletConfig(); 210 Enumeration names = config.getInitParameterNames(); 211 while (names.hasMoreElements()) { 212 String parameterName = (String ) names.nextElement(); 213 if (parameterName.startsWith(XSLT_PARAMETER_PREFIX)) { 214 String value = config.getInitParameter(parameterName); 215 String name = parameterName.substring(XSLT_PARAMETER_PREFIX.length()); 216 info("using XSLT parameter: " + name + "=" + value); 217 xsltParameters.put(name, value); 218 } 219 } 220 ServletContext context = config.getServletContext(); 221 names = context.getInitParameterNames(); 222 while (names.hasMoreElements()) { 223 String parameterName = (String ) names.nextElement(); 224 if (parameterName.startsWith(XSLT_PARAMETER_PREFIX)) { 225 String value = context.getInitParameter(parameterName); 226 String name = parameterName.substring(XSLT_PARAMETER_PREFIX.length()); 227 info("using XSLT parameter: " + name + "=" + value); 228 xsltParameters.put(name, value); 229 } 230 } 231 232 return xsltParameters; 233 } 234 235 241 public void setXslFile(String xslFile) { 242 xslFileName = xslFile; 243 } 244 245 251 File prepareContent() throws JspException { 252 LogFile xmlFile = findLogFile(); 253 File cacheFile = findCacheFile(xmlFile); 254 if (!isCacheFileCurrent(xmlFile.getFile(), cacheFile)) { 255 info("Updating cached copy: " + cacheFile.getAbsolutePath()); 256 updateCacheFile(xmlFile, cacheFile); 257 } else { 258 info("Using cached copy: " + cacheFile.getAbsolutePath()); 259 } 260 return cacheFile; 261 } 262 263 protected void updateCacheFile(LogFile xmlFile, File cacheFile) throws JspTagException { 264 OutputStream out = null; 265 try { 266 out = new FileOutputStream (cacheFile); 267 URL style = getPageContext().getServletContext().getResource(xslFileName); 268 transform(xmlFile, style, out); 269 } catch (IOException e) { 270 err(e); 271 throw new CCTagException("Error saving a cached transformation '" 272 + cacheFile.getName() + "': " + e.getMessage(), e); 273 } finally { 274 closeQuietly(out); 275 } 276 } 277 278 private File findCacheFile(LogFile xmlFile) { 279 String cacheRoot = getContextParam("cacheRoot"); 280 File cacheDir = cacheRoot == null 281 ? new File (xmlFile.getLogDirectory(), CACHE_DIR) 282 : new File (cacheRoot + File.separator + getProject()); 283 if (!cacheDir.exists()) { 284 cacheDir.mkdir(); 285 } 286 File cacheFile = new File (cacheDir, getCachedCopyFileName(xmlFile.getFile())); 287 return cacheFile; 288 } 289 290 public int doEndTag() throws JspException { 291 File cachedFile = prepareContent(); 292 serveCachedCopy(cachedFile, getPageContext().getOut()); 293 return EVAL_PAGE; 294 } 295 296 private void closeQuietly(InputStream in) { 297 if (in != null) { 298 try { 299 in.close(); 300 } catch (IOException ioex) { 301 info("Ignored " + ioex.getMessage() + " while closing stream"); 302 } 303 } 304 } 305 private void closeQuietly(Reader in) { 306 if (in != null) { 307 try { 308 in.close(); 309 } catch (IOException ioex) { 310 info("Ignored " + ioex.getMessage() + " while closing reader"); 311 } 312 } 313 } 314 private void closeQuietly(OutputStream out) { 315 if (out != null) { 316 try { 317 out.close(); 318 } catch (IOException ioex) { 319 info("Ignored " + ioex.getMessage() + " while closing stream"); 320 } 321 } 322 } 323 } 324 | Popular Tags |