1 37 package net.sourceforge.cruisecontrol.publishers; 38 39 import java.io.CharArrayWriter ; 40 import java.io.File ; 41 import java.io.FileNotFoundException ; 42 import java.io.IOException ; 43 import java.util.Iterator ; 44 import java.util.LinkedList ; 45 import java.util.List ; 46 import java.util.StringTokenizer ; 47 48 import javax.mail.Message ; 49 import javax.mail.MessagingException ; 50 import javax.mail.internet.MimeBodyPart ; 51 import javax.mail.internet.MimeMultipart ; 52 import javax.xml.transform.Source ; 53 import javax.xml.transform.Transformer ; 54 import javax.xml.transform.TransformerException ; 55 import javax.xml.transform.TransformerFactory ; 56 import javax.xml.transform.stream.StreamResult ; 57 import javax.xml.transform.stream.StreamSource ; 58 59 import net.sourceforge.cruisecontrol.CruiseControlException; 60 import net.sourceforge.cruisecontrol.builders.Property; 61 import net.sourceforge.cruisecontrol.util.ValidationHelper; 62 import net.sourceforge.cruisecontrol.util.XMLLogHelper; 63 import net.sourceforge.cruisecontrol.util.Util; 64 65 import org.apache.log4j.Logger; 66 import org.apache.tools.ant.launch.Locator; 67 68 75 public class HTMLEmailPublisher extends EmailPublisher { 76 77 private static final Logger LOG = Logger.getLogger(HTMLEmailPublisher.class); 78 79 private String xslFile; 80 private String xslDir; 81 private String css; 82 private String logDir; 83 private String messageMimeType = "text/html"; 84 private String charset; 85 86 private String [] xslFileNames = 89 { 90 "header.xsl", 91 "buildresults.xsl" 92 }; 93 94 private List xsltParameters = new LinkedList (); 95 96 102 public void validate() throws CruiseControlException { 103 super.validate(); 104 105 if (logDir != null) { 106 verifyDirectory("HTMLEmailPublisher.logDir", logDir); 107 } else { 108 LOG.debug("Using default logDir \"logs/<projectname>\""); 109 } 110 111 if (xslFile == null) { 112 if (xslDir == null) { 113 xslDir = getXslDirFromClasspath(); 115 } 116 verifyDirectory("HTMLEmailPublisher.xslDir", xslDir); 117 if (css == null) { 118 css = getCssFromClasspath(); 120 } 121 verifyFile("HTMLEmailPublisher.css", css); 122 123 String [] fileNames = getXslFileNames(); 124 125 if (fileNames == null) { 126 throw new CruiseControlException("HTMLEmailPublisher.getXslFileNames() can't return null"); 127 } 128 129 for (int i = 0; i < fileNames.length; i++) { 130 String fileName = fileNames[i]; 131 verifyFile( 132 "HTMLEmailPublisher.xslDir/" + fileName, 133 new File (xslDir, fileName)); 134 } 135 } else { 136 verifyFile("HTMLEmailPublisher.xslFile", xslFile); 137 } 138 } 139 140 142 public Property createParameter() { 143 Property param = new Property(); 144 xsltParameters.add(param); 145 return param; 146 } 147 148 152 private String getCssFromClasspath() { 153 File cssFile = new File (getCruiseRootDir(), "reporting/jsp/webcontent/css/cruisecontrol.css"); 154 if (cssFile.exists()) { 155 return cssFile.getAbsolutePath(); 156 } 157 return null; 158 } 159 160 164 private String getXslDirFromClasspath() { 165 File xsl = new File (getCruiseRootDir(), "reporting/jsp/webcontent/xsl"); 166 if (xsl.isDirectory()) { 167 return xsl.getAbsolutePath(); 168 } 169 return null; 170 } 171 172 176 private File getCruiseRootDir() { 177 File classDir = Locator.getClassSource(getClass()); 178 if (classDir != null) { 179 try { 180 File rootDir = classDir.getParentFile().getParentFile().getParentFile(); 182 if (LOG.isDebugEnabled()) { 183 LOG.debug("rootDir seems to be " + rootDir.getAbsolutePath() 184 + " (classDir = " + classDir.getAbsolutePath() + ")"); 185 } 186 return rootDir; 187 } catch (NullPointerException npe) { 188 return null; 190 } 191 } 192 return null; 193 } 194 195 private void verifyDirectory(String dirName, String dir) throws CruiseControlException { 196 ValidationHelper.assertFalse(dir == null, dirName + " not specified in configuration file"); 197 File dirFile = new File (dir); 198 ValidationHelper.assertTrue(dirFile.exists(), dirFile + " does not exist: " + dirFile.getAbsolutePath()); 199 ValidationHelper.assertTrue(dirFile.isDirectory(), 200 dirFile + " is not a directory: " + dirFile.getAbsolutePath()); 201 } 202 203 private void verifyFile(String fileName, String file) throws CruiseControlException { 204 ValidationHelper.assertFalse(file == null, fileName + " not specified in configuration file"); 205 verifyFile(fileName, new File (file)); 206 } 207 208 private void verifyFile(String fileName, File file) throws CruiseControlException { 209 ValidationHelper.assertTrue(file.exists(), fileName + " does not exist: " + file.getAbsolutePath()); 210 ValidationHelper.assertTrue(file.isFile(), fileName + " is not a file: " + file.getAbsolutePath()); 211 } 212 213 216 protected void addContentToMessage(String htmlContent, Message msg) throws MessagingException { 217 MimeMultipart attachments = new MimeMultipart (); 218 MimeBodyPart textbody = new MimeBodyPart (); 219 String contentType = getContentType(); 220 textbody.setContent(htmlContent, contentType); 221 attachments.addBodyPart(textbody); 222 223 msg.setContent(attachments); 224 } 225 226 String getContentType() { 227 if (charset != null) { 228 return messageMimeType + "; charset=\"" + charset + "\""; 229 } else { 230 return messageMimeType; 231 } 232 } 233 234 235 244 public void setXSLFileList(String relativePathToXslFile) { 245 if (relativePathToXslFile == null || relativePathToXslFile.equals("")) { 246 throw new IllegalArgumentException ("xslFileList shouldn't be null or empty"); 247 } 248 249 relativePathToXslFile = relativePathToXslFile.trim(); 250 boolean appending = relativePathToXslFile.startsWith("+"); 251 252 if (appending) { 253 relativePathToXslFile = relativePathToXslFile.substring(1); 254 } 255 256 StringTokenizer st = new StringTokenizer (relativePathToXslFile, " ,"); 257 int numTokens = st.countTokens(); 258 259 int i; 260 if (appending) { 261 i = xslFileNames.length; 262 } else { 263 i = 0; 264 } 265 String [] newXSLFileNames = new String [i + numTokens]; 266 System.arraycopy(xslFileNames, 0, newXSLFileNames, 0, i); 267 268 while (st.hasMoreTokens()) { 269 newXSLFileNames[i++] = st.nextToken(); 270 } 271 272 setXSLFileNames(newXSLFileNames); 273 } 274 275 280 public void setXSLFile(String fullPathToXslFile) { 281 xslFile = fullPathToXslFile; 282 } 283 284 287 public void setXSLDir(String xslDirectory) { 288 xslDir = xslDirectory; 289 } 290 291 305 protected void setXSLFileNames(String [] fileNames) { 306 if (fileNames == null) { 307 throw new IllegalArgumentException ("xslFileNames can't be null (but can be empty)"); 308 } 309 xslFileNames = fileNames; 310 } 311 312 317 protected String [] getXslFileNames() { 318 return xslFileNames; 319 } 320 321 324 public void setCSS(String cssFilename) { 325 css = cssFilename; 326 } 327 328 332 public void setLogDir(String directory) { 333 if (directory == null) { 334 throw new IllegalArgumentException ("logDir cannot be null!"); 335 } 336 337 logDir = directory; 338 } 339 340 public void setCharset(String characterSet) { 341 charset = characterSet; 342 } 343 344 350 351 protected String createMessage(XMLLogHelper logHelper) { 354 String message = ""; 355 356 File inFile = null; 357 try { 358 if (logDir == null) { 359 logDir = "logs" + File.separator + logHelper.getProjectName(); 361 } 362 inFile = new File (logDir, logHelper.getLogFileName()); 363 message = transform(inFile); 364 } catch (Exception ex) { 365 LOG.error("error transforming " + (inFile == null ? null : inFile.getAbsolutePath()), ex); 366 try { 367 String logFileName = logHelper.getLogFileName(); 368 message = createLinkLine(logFileName); 369 } catch (CruiseControlException ccx) { 370 LOG.error("exception getting logfile name", ccx); 371 } 372 } 373 374 return message; 375 } 376 377 protected String transform(File inFile) throws TransformerException , FileNotFoundException , IOException { 378 StringBuffer messageBuffer = new StringBuffer (); 379 380 TransformerFactory tFactory = TransformerFactory.newInstance(); 381 382 if (xslFile != null) { 383 File xslFileAsFile = new File (xslFile); 384 appendTransform(inFile, messageBuffer, tFactory, xslFileAsFile); 385 } else { 386 appendHeader(messageBuffer); 387 messageBuffer.append(createLinkLine(inFile.getName())); 388 389 File xslDirectory = new File (xslDir); 390 String [] fileNames = getXslFileNames(); 391 for (int i = 0; i < fileNames.length; i++) { 392 String fileName = fileNames[i]; 393 File xsl = new File (xslDirectory, fileName); 394 messageBuffer.append("<p>\n"); 395 appendTransform(inFile, messageBuffer, tFactory, xsl); 396 } 397 398 appendFooter(messageBuffer); 399 } 400 401 return messageBuffer.toString(); 402 } 403 404 protected String createLinkLine(String logFileName) { 405 StringBuffer linkLine = new StringBuffer (""); 406 String buildResultsURL = getBuildResultsURL(); 407 408 if (buildResultsURL == null) { 409 return ""; 410 } 411 412 int startName = logFileName.lastIndexOf(File.separator) + 1; 413 int endName = logFileName.lastIndexOf("."); 414 String baseLogFileName = logFileName.substring(startName, endName); 415 StringBuffer url = new StringBuffer (buildResultsURL); 416 if (buildResultsURL.indexOf("?") == -1) { 417 url.append("?"); 418 } else { 419 url.append("&"); 420 } 421 url.append("log="); 422 url.append(baseLogFileName); 423 424 linkLine.append("View results here -> <a HREF=\""); 426 linkLine.append(url.toString()); 427 linkLine.append("\">"); 428 linkLine.append(url.toString()); 429 linkLine.append("</a>"); 430 431 return linkLine.toString(); 432 } 433 434 protected void appendTransform(File inFile, StringBuffer messageBuffer, TransformerFactory tFactory, File xsl) { 435 try { 436 String result = transformFile(new StreamSource (inFile), tFactory, new StreamSource (xsl)); 437 messageBuffer.append(result); 438 } catch (Exception e) { 439 LOG.error("error transforming with xslFile " + xsl.getName(), e); 440 } 441 } 442 protected String transformFile(Source logFile, TransformerFactory tFactory, Source xsl) 443 throws IOException , TransformerException { 444 Transformer transformer = tFactory.newTransformer(xsl); 445 CharArrayWriter writer = new CharArrayWriter (); 446 if (!xsltParameters.isEmpty()) { 447 Iterator i = xsltParameters.iterator(); 448 while (i.hasNext()) { 449 Property param = (Property) i.next(); 450 transformer.setParameter(param.getName(), param.getValue()); 451 } 452 } 453 transformer.transform(logFile, new StreamResult (writer)); 454 return writer.toString(); 455 } 456 457 protected void appendHeader(StringBuffer messageBuffer) throws IOException { 458 messageBuffer.append("<html><head>\n"); 459 String baseUrl = getBuildResultsURL(); 460 if (baseUrl != null) { 461 messageBuffer.append("<base HREF=\"").append(baseUrl).append("\">\n"); 462 } 463 messageBuffer.append("<style>\n"); 464 465 Util.appendFileToBuffer(css, messageBuffer); 466 467 messageBuffer.append("\n</style>\n</head><body>\n"); 468 } 469 470 protected void appendFooter(StringBuffer messageBuffer) { 471 messageBuffer.append("\n</body></html>"); 472 } 473 } 474 | Popular Tags |