1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* $Id: TestAssistant.java 1884907 2020-12-29 13:33:34Z ssteiner $ */ 19 20 package org.apache.fop.intermediate; 21 22 import java.io.File; 23 import java.io.IOException; 24 25 import javax.xml.parsers.DocumentBuilder; 26 import javax.xml.parsers.DocumentBuilderFactory; 27 import javax.xml.transform.Result; 28 import javax.xml.transform.Source; 29 import javax.xml.transform.Templates; 30 import javax.xml.transform.Transformer; 31 import javax.xml.transform.TransformerConfigurationException; 32 import javax.xml.transform.TransformerException; 33 import javax.xml.transform.dom.DOMResult; 34 import javax.xml.transform.dom.DOMSource; 35 import javax.xml.transform.sax.SAXTransformerFactory; 36 import javax.xml.transform.stream.StreamResult; 37 import javax.xml.transform.stream.StreamSource; 38 39 import org.w3c.dom.Document; 40 import org.w3c.dom.Element; 41 42 import org.apache.xpath.XPathAPI; 43 import org.apache.xpath.objects.XObject; 44 45 import org.apache.fop.apps.EnvironmentProfile; 46 import org.apache.fop.apps.EnvironmentalProfileFactory; 47 import org.apache.fop.apps.FopFactory; 48 import org.apache.fop.apps.FopFactoryBuilder; 49 import org.apache.fop.apps.io.ResourceResolverFactory; 50 51 /** 52 * Helper class for running FOP tests. 53 */ 54 public class TestAssistant { 55 56 // configure fopFactory as desired 57 protected final File testDir = new File("test/layoutengine/standard-testcases"); 58 59 private SAXTransformerFactory tfactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); 60 61 private DocumentBuilderFactory domBuilderFactory; 62 63 private Templates testcase2fo; 64 private Templates testcase2checks; 65 66 /** 67 * Main constructor. 68 */ TestAssistant()69 public TestAssistant() { 70 domBuilderFactory = DocumentBuilderFactory.newInstance(); 71 domBuilderFactory.setNamespaceAware(true); 72 domBuilderFactory.setValidating(false); 73 } 74 75 /** 76 * Returns the stylesheet for convert extracting the XSL-FO part from the test case. 77 * @return the stylesheet 78 * @throws TransformerConfigurationException if an error occurs loading the stylesheet 79 */ getTestcase2FOStylesheet()80 public Templates getTestcase2FOStylesheet() throws TransformerConfigurationException { 81 if (testcase2fo == null) { 82 //Load and cache stylesheet 83 Source src = new StreamSource(new File("test/layoutengine/testcase2fo.xsl")); 84 testcase2fo = tfactory.newTemplates(src); 85 } 86 return testcase2fo; 87 } 88 89 /** 90 * Returns the stylesheet for convert extracting the checks from the test case. 91 * @return the stylesheet 92 * @throws TransformerConfigurationException if an error occurs loading the stylesheet 93 */ getTestcase2ChecksStylesheet()94 private Templates getTestcase2ChecksStylesheet() throws TransformerConfigurationException { 95 if (testcase2checks == null) { 96 //Load and cache stylesheet 97 Source src = new StreamSource(new File("test/layoutengine/testcase2checks.xsl")); 98 testcase2checks = tfactory.newTemplates(src); 99 } 100 return testcase2checks; 101 } 102 103 /** 104 * Returns the element from the given XML file that encloses the tests. 105 * 106 * @param testFile a test case 107 * @return the parent element of the group(s) of checks 108 * @throws TransformerException if an error occurs while extracting the test element 109 */ getTestRoot(File testFile)110 public Element getTestRoot(File testFile) throws TransformerException { 111 Transformer transformer = getTestcase2ChecksStylesheet().newTransformer(); 112 DOMResult res = new DOMResult(); 113 transformer.transform(new StreamSource(testFile), res); 114 Document doc = (Document) res.getNode(); 115 return doc.getDocumentElement(); 116 } 117 getFopFactory(Document testDoc)118 public FopFactory getFopFactory(Document testDoc) { 119 EnvironmentProfile envProfile = EnvironmentalProfileFactory.createRestrictedIO( 120 testDir.getParentFile().toURI(), 121 ResourceResolverFactory.createDefaultResourceResolver()); 122 FopFactoryBuilder builder = new FopFactoryBuilder(envProfile); 123 builder.setStrictFOValidation(isStrictValidation(testDoc)); 124 builder.getFontManager().setBase14KerningEnabled(isBase14KerningEnabled(testDoc)); 125 builder.setTableBorderOverpaint(isTableBorderOverpaint(testDoc)); 126 return builder.build(); 127 } 128 isBase14KerningEnabled(Document testDoc)129 private boolean isBase14KerningEnabled(Document testDoc) { 130 try { 131 XObject xo = XPathAPI.eval(testDoc, "/testcase/cfg/base14kerning"); 132 String s = xo.str(); 133 return ("true".equalsIgnoreCase(s)); 134 } catch (TransformerException e) { 135 throw new RuntimeException("Error while evaluating XPath expression", e); 136 } 137 } 138 isStrictValidation(Document testDoc)139 private boolean isStrictValidation(Document testDoc) { 140 try { 141 XObject xo = XPathAPI.eval(testDoc, "/testcase/cfg/strict-validation"); 142 return !("false".equalsIgnoreCase(xo.str())); 143 } catch (TransformerException e) { 144 throw new RuntimeException("Error while evaluating XPath expression", e); 145 } 146 } 147 isTableBorderOverpaint(Document testDoc)148 private boolean isTableBorderOverpaint(Document testDoc) { 149 try { 150 XObject xo = XPathAPI.eval(testDoc, "/testcase/cfg/table-border-overpaint"); 151 String s = xo.str(); 152 return "true".equalsIgnoreCase(s); 153 } catch (TransformerException e) { 154 throw new RuntimeException("Error while evaluating XPath expression", e); 155 } 156 } 157 158 /** 159 * Loads a test case into a DOM document. 160 * @param testFile the test file 161 * @return the loaded test case 162 * @throws IOException if an I/O error occurs loading the test case 163 */ loadTestCase(File testFile)164 public Document loadTestCase(File testFile) 165 throws IOException { 166 try { 167 DocumentBuilder builder = domBuilderFactory.newDocumentBuilder(); 168 Document testDoc = builder.parse(testFile); 169 return testDoc; 170 } catch (Exception e) { 171 throw new IOException("Error while loading test case: " + e.getMessage()); 172 } 173 } 174 175 /** 176 * Serialize the DOM for later inspection. 177 * @param doc the DOM document 178 * @param target target file 179 * @throws TransformerException if a problem occurs during serialization 180 */ saveDOM(Document doc, File target)181 public void saveDOM(Document doc, File target) throws TransformerException { 182 Transformer transformer = getTransformerFactory().newTransformer(); 183 Source src = new DOMSource(doc); 184 Result res = new StreamResult(target); 185 transformer.transform(src, res); 186 } 187 188 /** 189 * Returns the SAXTransformerFactory. 190 * @return the SAXTransformerFactory 191 */ getTransformerFactory()192 public SAXTransformerFactory getTransformerFactory() { 193 return tfactory; 194 } 195 } 196