Java tutorial
/* * Copyright 2006 Wyona * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.wyona.org/licenses/APACHE-LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wyona.yanel.impl.resources; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.OutputStream; import java.util.Calendar; import java.util.Enumeration; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.dom.DOMSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.tools.ant.Project; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.types.PatternSet; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.ZipFileSet; import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask; import org.apache.tools.ant.taskdefs.optional.junit.BatchTest; import org.apache.xml.resolver.tools.CatalogResolver; import org.apache.xml.serializer.Serializer; import org.wyona.yanel.core.Resource; import org.wyona.yanel.core.api.attributes.ViewableV2; import org.wyona.yanel.core.attributes.viewable.View; import org.wyona.yanel.core.attributes.viewable.ViewDescriptor; import org.wyona.yanel.core.serialization.SerializerFactory; import org.wyona.yanel.core.source.ResourceResolver; import org.wyona.yanel.core.transformation.I18nTransformer2; import org.wyona.yanel.core.transformation.XIncludeTransformer; import org.wyona.yanel.core.util.PathUtil; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; /** * Resource in order to run tests */ public class TestingControlResource extends Resource implements ViewableV2 { private static final String JUNIT_JAR = "yanel-JunitTests.jar"; private static final String HTMLUNIT_JAR = "yanel-HtmlUnitTests.jar"; private static Logger log = LogManager.getLogger(TestingControlResource.class); private boolean ajaxBrowser = false; private File JunitJarLocation; private File HtmlunitJarLocation; private File tmpResultDir; public TestingControlResource() { } /** * */ public boolean exists() { return true; } /** * */ public long getSize() { return -1; } /** * */ public String getMimeType(String viewId) { if (viewId != null && viewId.equals("source")) return "application/xml"; return "application/xhtml+xml"; } /** * */ public View getView(String viewId) { if (request.getHeader("User-Agent").indexOf("rv:1.7") < 0) { ajaxBrowser = true; } try { setLocations(); } catch (Exception e) { // sb.append("<p>Could not get the Locations: " + e + "</p>"); log.error(e.getMessage(), e); } View view = new View(); String mimeType = getMimeType(viewId); view.setMimeType(mimeType); try { org.wyona.yarep.core.Repository repo = getRealm().getRepository(); if (viewId != null && viewId.equals("source")) { view.setInputStream(new java.io.StringBufferInputStream(getScreen())); view.setMimeType("application/xml"); return view; } String[] xsltPath = getXSLTPath(getPath()); if (xsltPath != null) { // create reader: XMLReader xmlReader = XMLReaderFactory.createXMLReader(); CatalogResolver catalogResolver = new CatalogResolver(); xmlReader.setEntityResolver(catalogResolver); // create xslt transformer: SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance(); TransformerHandler[] xsltHandlers = new TransformerHandler[xsltPath.length]; for (int i = 0; i < xsltPath.length; i++) { xsltHandlers[i] = tf .newTransformerHandler(new StreamSource(repo.getNode(xsltPath[i]).getInputStream())); xsltHandlers[i].getTransformer().setParameter("yanel.path.name", org.wyona.commons.io.PathUtil.getName(getPath())); xsltHandlers[i].getTransformer().setParameter("yanel.path", getPath()); xsltHandlers[i].getTransformer().setParameter("yanel.back2context", PathUtil.backToContext(realm, getPath())); xsltHandlers[i].getTransformer().setParameter("yarep.back2realm", PathUtil.backToRealm(getPath())); xsltHandlers[i].getTransformer().setParameter("language", getRequestedLanguage()); } // create i18n transformer: I18nTransformer2 i18nTransformer = new I18nTransformer2("global", getRequestedLanguage(), getRealm().getDefaultLanguage()); i18nTransformer.setEntityResolver(catalogResolver); // create xinclude transformer: XIncludeTransformer xIncludeTransformer = new XIncludeTransformer(); ResourceResolver resolver = new ResourceResolver(this); xIncludeTransformer.setResolver(resolver); // create serializer: Serializer serializer = SerializerFactory.getSerializer(SerializerFactory.XHTML_STRICT); ByteArrayOutputStream baos = new ByteArrayOutputStream(); // chain everything together (create a pipeline): xmlReader.setContentHandler(xsltHandlers[0]); for (int i = 0; i < xsltHandlers.length - 1; i++) { xsltHandlers[i].setResult(new SAXResult(xsltHandlers[i + 1])); } xsltHandlers[xsltHandlers.length - 1].setResult(new SAXResult(xIncludeTransformer)); xIncludeTransformer.setResult(new SAXResult(i18nTransformer)); i18nTransformer.setResult(new SAXResult(serializer.asContentHandler())); serializer.setOutputStream(baos); // execute pipeline: xmlReader.parse(new InputSource(new java.io.StringBufferInputStream(getScreen()))); // write result into view: view.setInputStream(new ByteArrayInputStream(baos.toByteArray())); return view; } log.debug("Mime-Type: " + mimeType); view.setInputStream(new java.io.StringBufferInputStream(getScreen())); return view; } catch (Exception e) { log.error(e + " (" + getPath() + ", " + getRealm() + ")", e); } view.setInputStream(new java.io.StringBufferInputStream(getScreen())); return view; } /** * */ public ViewDescriptor[] getViewDescriptors() { ViewDescriptor[] vd = new ViewDescriptor[2]; vd[0] = new ViewDescriptor("default"); vd[0].setMimeType(getMimeType(null)); vd[1] = new ViewDescriptor("source"); vd[1].setMimeType(getMimeType("source")); return vd; } /** * Flow */ private String getScreen() { StringBuffer sbContent = new StringBuffer(); Enumeration parameters = request.getParameterNames(); if (request.getSession().getAttribute("tmpResultDir") != null) { if (request.getParameterValues("ajaxshowprogress") != null) return showProgress().toString(); sbContent.append(showProgress()); } else if (!parameters.hasMoreElements()) { sbContent.append(getPlainRequest()); } else { if (request.getParameterValues("testnames") != null) { if (request.getParameterValues("ajaxexecutetest") != null) return executeTests().toString(); sbContent.append(executeTests()); } else { log.info("Fallback ..."); sbContent.append(getPlainRequest()); } } StringBuffer sb = new StringBuffer("<?xml version=\"1.0\"?>"); sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">"); sb.append("<head><title>Testing Control</title>"); if (request.getSession().getAttribute("tmpResultDir") != null && !ajaxBrowser) { sb.append("<meta http-equiv=\"refresh\" content=\"5; URL=\"/>"); } sb.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + PathUtil.getGlobalHtdocsPath(this) + "yanel-css/progressBar.css\"/>"); sb.append("<script src=\"" + PathUtil.getGlobalHtdocsPath(this) + "yanel-js/prototype.js\" type=\"text/javascript\"></script>"); sb.append("<script src=\"" + PathUtil.getGlobalHtdocsPath(this) + "yanel-js/progressBar.js\" type=\"text/javascript\"></script>"); sb.append("<script src=\"" + PathUtil.getResourcesHtdocsPath(this) + "js/ajaxexecutetests.js\" type=\"text/javascript\"></script>"); sb.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + PathUtil.getResourcesHtdocsPath(this) + "css/testingcontroler.css\"/>"); sb.append("</head>"); sb.append("<body>"); sb.append("<span id=\"yanelprogressbarph\"/>"); sb.append("<div id=\"ajaxreplace\">"); sb.append(sbContent); sb.append("</div>"); sb.append("</body>"); sb.append("</html>"); return sb.toString(); } private StringBuffer getPlainRequest() { StringBuffer sb = new StringBuffer(); sb.append("<form method=\"post\">"); sb.append("<h3>HtmlUnit Tests</h3>"); String[] allHtmlUnitTestNames = getAllTestNames("htmlunit"); if (allHtmlUnitTestNames != null) { sb.append("<ul id=\"htmlunit\">"); for (int i = 0; i < allHtmlUnitTestNames.length; i++) { String title = allHtmlUnitTestNames[i].substring(allHtmlUnitTestNames[i].lastIndexOf("/") + 1) .replaceAll(".class", ""); sb.append("<li title=\"" + "\">"); sb.append(title); sb.append( "<input type=\"checkbox\" name=\"testnames\" value=\"" + allHtmlUnitTestNames[i] + "\"/>"); sb.append("</li>"); } sb.append("</ul>"); } else { sb.append("<p>Retrieving HtmlUnit test names failed!</p>"); } sb.append("<hr/>"); sb.append("<h3>JUnit Tests</h3>"); String[] allJUnitTestNames = getAllTestNames("junit"); if (allJUnitTestNames != null) { sb.append("<ul id=\"junit\">"); for (int i = 0; i < allJUnitTestNames.length; i++) { String title = allJUnitTestNames[i].substring(allJUnitTestNames[i].lastIndexOf("/") + 1) .replaceAll(".class", ""); sb.append("<li title=\"" + title + "\">"); sb.append(title); sb.append("<input type=\"checkbox\" name=\"testnames\" value=\"" + allJUnitTestNames[i] + "\"/>"); sb.append("</li>"); } sb.append("</ul>"); } else { sb.append("<p>Retrieving JUnit test names failed!</p>"); } if (ajaxBrowser) { sb.append("<input type=\"hidden\" name=\"yanel.resource.viewid\" value=\"source\"/>"); sb.append("<input type=\"hidden\" name=\"ajaxexecutetest\" value=\"true\"/>"); sb.append("<input type=\"button\" name=\"submit\" value=\"Test\" onclick=\"ajaxexecutetests();\" />"); } else { sb.append("<input type=\"submit\" name=\"submit\" value=\"Test\"/>"); } sb.append("</form>"); return sb; } private StringBuffer executeTests() { StringBuffer sb = new StringBuffer(); String[] testnames = request.getParameterValues("testnames"); // prepare tmpResultDir if (request.getSession().getAttribute("tmpResultDir") == null) { String uuid = new java.rmi.server.UID().toString().replaceAll(":", ""); tmpResultDir = new File(request.getSession().getServletContext() .getRealPath("tmp" + File.separator + "test-results-" + uuid)); request.getSession().setAttribute("tmpResultDir", tmpResultDir); } else { tmpResultDir = (File) request.getSession().getAttribute("tmpResultDir"); } request.getSession().setAttribute("exectime", getTime()); request.getSession().setAttribute("numberOfTests", "" + testnames.length); // delete the resultdir before making new tests tmpResultDir.mkdir(); Runnable runtest = new ExecuteTests(testnames, JunitJarLocation, HtmlunitJarLocation, tmpResultDir); new Thread(runtest).start(); sb.append(showProgress()); return sb; } private StringBuffer showProgress() { StringBuffer sb = new StringBuffer(); // get tmpResultDir from session tmpResultDir = (File) request.getSession().getAttribute("tmpResultDir"); // number of executed tests int numberOfTests = Integer.parseInt((String) request.getSession().getAttribute("numberOfTests")); String resultName = request.getSession().getAttribute("exectime") + "-tests.xml"; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); if (tmpResultDir.list().length < numberOfTests) { // geting the test results // aggregate all tests in the tmp dir try { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document result = builder.newDocument(); Project project = new Project(); ResultAggregator junitreport = new ResultAggregator(); junitreport.setTaskName("JUnitReport"); junitreport.setProject(project); FileSet fs_report = new FileSet(); fs_report.setDir(tmpResultDir); fs_report.setProject(project); PatternSet.NameEntry ne = fs_report.createInclude(); ne.setName("**/TEST-*.xml"); junitreport.addFileSet(fs_report); junitreport.init(); // get the result to show for this request result = junitreport.getDocument(); File result2htmlXsltFile = org.wyona.commons.io.FileUtil.file( rtd.getConfigFile().getParentFile().getAbsolutePath(), "xslt" + File.separator + "result2html.xsl"); Transformer transResult2html = TransformerFactory.newInstance() .newTransformer(new StreamSource(result2htmlXsltFile)); transResult2html.setParameter("testing.result.title", "stillTesting"); transResult2html.setParameter("testing.number.requested.tests", "" + numberOfTests); transResult2html.transform(new DOMSource(result), new StreamResult(byteArrayOutputStream)); } catch (Exception e) { sb.append("<p>Could not create folder. Exception: " + e + "</p>"); log.error(e.getMessage(), e); } } else { request.getSession().removeAttribute("tmpResultDir"); request.getSession().removeAttribute("exectime"); request.getSession().removeAttribute("numberOfTests"); try { // geting the test results DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document result = builder.newDocument(); Project aggregatorproject = new Project(); // aggregate all tests in the tmp dir ResultAggregator junitreport = new ResultAggregator(); junitreport.setTaskName("JUnitReport"); junitreport.setProject(aggregatorproject); FileSet fs_report = new FileSet(); fs_report.setDir(tmpResultDir); fs_report.setProject(aggregatorproject); PatternSet.NameEntry ne = fs_report.createInclude(); ne.setName("**/TEST-*.xml"); junitreport.addFileSet(fs_report); junitreport.init(); // get the result to show for this request result = junitreport.getDocument(); // write test result to repo org.wyona.yarep.core.Repository Repo = this.getRealm().getRepository(); org.wyona.commons.io.Path newPath = new org.wyona.commons.io.Path( "/test-results-archive/" + resultName); log.debug("" + newPath); org.wyona.yanel.core.util.YarepUtil.addNodes(Repo, newPath.toString(), org.wyona.yarep.core.NodeType.RESOURCE); OutputStream out = Repo.getNode(newPath.toString()).getOutputStream(); javax.xml.transform.TransformerFactory.newInstance().newTransformer().transform( new javax.xml.transform.dom.DOMSource(result), new javax.xml.transform.stream.StreamResult(out)); out.close(); // delete the test dir FileUtils.deleteDirectory(tmpResultDir); File result2htmlXsltFile = org.wyona.commons.io.FileUtil.file( rtd.getConfigFile().getParentFile().getAbsolutePath(), "xslt" + File.separator + "result2html.xsl"); Transformer transResult2html = TransformerFactory.newInstance() .newTransformer(new StreamSource(result2htmlXsltFile)); transResult2html.setParameter("testing.result.title", "testDone"); transResult2html.transform(new DOMSource(result), new StreamResult(byteArrayOutputStream)); } catch (Exception e) { sb.append("<p>Could not create folder. Exception: " + e + "</p>"); log.error(e.getMessage(), e); } } sb.append(byteArrayOutputStream); return sb; } private void setLocations() throws Exception { String WEBINFPath = request.getSession().getServletContext().getRealPath("WEB-INF"); HtmlunitJarLocation = new File(WEBINFPath + File.separator + "lib" + File.separator + HTMLUNIT_JAR); JunitJarLocation = new File(WEBINFPath + File.separator + "lib" + File.separator + JUNIT_JAR); if (!HtmlunitJarLocation.exists()) { throw new Exception("HtmlUnit-Tests not found"); } if (!JunitJarLocation.exists()) { throw new Exception("JUnit-Tests not found"); } // create tmp-directory to write the tests if (!new File(request.getSession().getServletContext().getRealPath("tmp")).exists()) { if (!new File(request.getSession().getServletContext().getRealPath("tmp")).mkdir()) { throw new Exception("Creation of tmp directory faild."); } } } /** * get Tests. * @param htmlOrJunit type of tests should be selected. can be htmlunit or junit. * @return an array with the aviable tests. */ private String[] getAllTestNames(String htmlOrJunit) { Project project = new Project(); try { JUnitTask junit = new JUnitTask(); ZipFileSet zipfileset = new ZipFileSet(); zipfileset.setProject(project); if (htmlOrJunit.equals("htmlunit")) { zipfileset.setSrc(HtmlunitJarLocation); } else { zipfileset.setSrc(JunitJarLocation); } zipfileset.setIncludes("**/*Test.class"); zipfileset.setExcludes("**/Abstract*.class"); BatchTest batchTest = junit.createBatchTest(); batchTest.addFileSet(zipfileset); DirectoryScanner directoryscanner = zipfileset.getDirectoryScanner(project); return directoryscanner.getIncludedFiles(); } catch (Exception e) { log.error(e); } return null; } /** * get time as string * @return timestamp (yyyy-MM-dd-HH-mm-ss) */ private String getTime() { Calendar cal = Calendar.getInstance(java.util.TimeZone.getDefault()); String dateFormat = "yyyy-MM-dd-HH-mm-ss"; java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(dateFormat); sdf.setTimeZone(java.util.TimeZone.getDefault()); return sdf.format(cal.getTime()); } /** * Get XSLT path */ private String[] getXSLTPath(String path) throws Exception { String[] xsltPath = getResourceConfigProperties("xslt"); if (xsltPath != null) return xsltPath; log.info("No XSLT Path within: " + path); return null; } }