/* * Copyright 2002-2007 the original author or authors. * * 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.apache.org/licenses/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.springframework.web.servlet.view.xslt; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.ErrorListener; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import junit.framework.TestCase; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; import org.springframework.context.ApplicationContextException; import org.springframework.core.JdkVersion; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.web.servlet.ModelAndView; /** * Unit tests for the {@link AbstractXsltView} class. * * @author Darren Davison * @author Rick Evans * @author Juergen Hoeller * @since 11.03.2005 */ public class TestXsltViewTests extends TestCase { private TestXsltView view; private int warnings = 0; private int errors = 0; private int fatal = 0; public void setUp() { this.view = new TestXsltView(); } public void testNoSuchStylesheet() { view.setStylesheetLocation(new FileSystemResource("/does/not/exist.xsl")); try { view.initApplicationContext(); fail("Must have thrown ApplicationContextException"); } catch (ApplicationContextException expected) { } } public void testCustomErrorListener() { view.setErrorListener(new ErrorListener() { public void warning(TransformerException ex) { incWarnings(); } public void error(TransformerException ex) { incErrors(); } public void fatalError(TransformerException ex) { incFatals(); } }); // loaded stylesheet is not well formed view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/errors.xsl")); try { view.initApplicationContext(); } catch (ApplicationContextException ex) { // shouldn't really happen, but can be let through by XSLT engine assertTrue(ex.getCause() instanceof TransformerException); } assertEquals(1, fatal); assertEquals(1, errors); assertEquals(0, warnings); } public void testRender() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); AbstractXsltView view = new AbstractXsltView() { protected Source createXsltSource(Map model, String root, HttpServletRequest request, HttpServletResponse response) throws Exception { Hero hero = (Hero) model.get("hero"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement(root); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); return new DOMSource(node); } }; view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/sunnyDay.xsl")); view.setIndent(true); view.initApplicationContext(); view.render(new ModelAndView().addObject("hero", new Hero("Jet", 24, "BOOM")).getModel(), request, response); assertEquals("text/html;charset=ISO-8859-1", response.getContentType()); String text = response.getContentAsString(); assertEquals("<hero name=\"Jet\" age=\"24\" catchphrase=\"BOOM\" sex=\"Female\"/>", text.trim()); } public void testRenderWithCustomContentType() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); AbstractXsltView view = new AbstractXsltView() { protected Source createXsltSource(Map model, String root, HttpServletRequest request, HttpServletResponse response) throws Exception { Hero hero = (Hero) model.get("hero"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement(root); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); return new DOMSource(node); } }; view.setContentType("text/plain"); view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/sunnyDay.xsl")); view.setIndent(true); view.initApplicationContext(); view.render(new ModelAndView().addObject("hero", new Hero("Jet", 24, "BOOM")).getModel(), request, response); assertEquals("text/plain", response.getContentType()); String text = response.getContentAsString(); assertEquals("<hero name=\"Jet\" age=\"24\" catchphrase=\"BOOM\" sex=\"Female\"/>", text.trim()); } public void testRenderWithSingleSourceInModel() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); AbstractXsltView view = new AbstractXsltView() { protected Map getParameters(HttpServletRequest request) { Map parameters = new HashMap(); parameters.put("sex", "Male"); return parameters; } }; view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/sunnyDay.xsl")); Properties outputProperties = new Properties(); outputProperties.setProperty("indent", "false"); view.setOutputProperties(outputProperties); view.initApplicationContext(); Hero hero = new Hero("Jet", 24, "BOOM"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement("hero"); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); view.render(new ModelAndView().addObject("hero", new DOMSource(node)).getModel(), request, response); assertEquals("text/html;charset=ISO-8859-1", response.getContentType()); String text = response.getContentAsString(); assertEquals("<hero name=\"Jet\" age=\"24\" catchphrase=\"BOOM\" sex=\"Male\"/>", text.trim()); } public void testRenderWithSingleNodeInModel() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); response.setWriterAccessAllowed(false); AbstractXsltView view = new AbstractXsltView() { protected Map getParameters(HttpServletRequest request) { Map parameters = new HashMap(); parameters.put("sex", "Male"); return parameters; } }; view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/sunnyDay.xsl")); view.initApplicationContext(); Hero hero = new Hero("Jet", 24, "BOOM"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement("hero"); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); view.render(new ModelAndView().addObject("hero", node).getModel(), request, response); String text = response.getContentAsString(); assertEquals("<hero name=\"Jet\" age=\"24\" catchphrase=\"BOOM\" sex=\"Male\"/>", text.trim()); } public void testRenderWithNoStylesheetSpecified() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); AbstractXsltView view = new AbstractXsltView() { protected Map getParameters(HttpServletRequest request) { Map parameters = new HashMap(); parameters.put("sex", "Male"); return parameters; } }; Properties outputProperties = new Properties(); outputProperties.setProperty("indent", "false"); view.setOutputProperties(outputProperties); view.initApplicationContext(); Hero hero = new Hero("Jet", 24, "BOOM"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement("hero"); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); view.render(new ModelAndView().addObject("hero", new DOMSource(node)).getModel(), request, response); assertEquals("text/xml;charset=ISO-8859-1", response.getContentType()); String text = response.getContentAsString().trim(); assertTrue(text.startsWith("<?xml")); assertTrue(text.indexOf("<hero") != -1); assertTrue(text.indexOf("age=\"24\"") != -1); assertTrue(text.indexOf("catchphrase=\"BOOM\"") != -1); assertTrue(text.indexOf("name=\"Jet\"") != -1); } public void testRenderSingleNodeInModelWithExplicitDocRootName() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); response.setOutputStreamAccessAllowed(false); AbstractXsltView view = new AbstractXsltView() { protected Source createXsltSource(Map model, String root, HttpServletRequest request, HttpServletResponse response) throws Exception { Hero hero = (Hero) model.get("hero"); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element node = document.createElement(root); node.setAttribute("name", hero.getName()); node.setAttribute("age", hero.getAge() + ""); node.setAttribute("catchphrase", hero.getCatchphrase()); return new DOMSource(node); } protected Map getParameters(HttpServletRequest request) { Map parameters = new HashMap(); parameters.put("sex", "Male"); return parameters; } protected boolean useWriter() { return true; } }; view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/sunnyDayExplicitRoot.xsl")); view.setUseSingleModelNameAsRoot(false); view.setRoot("baddie"); view.initApplicationContext(); view.render(new ModelAndView().addObject("hero", new Hero("Jet", 24, "BOOM")).getModel(), request, response); String text = response.getContentAsString(); assertTrue(text.trim().startsWith("<baddie ")); } /** * Not a test per-se, but rather only here to validate the example * given in the reference documentation. */ public void testMyFirstWordsExampleFromTheReferenceDocumentation() throws Exception { // TODO: Why does this test not even work on JDK 1.4? // Maybe because of the Xalan version there? if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_15) { return; } MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); AbstractXsltView view = new AbstractXsltView() { protected Source createXsltSource( Map model, String rootName, HttpServletRequest request, HttpServletResponse response) throws Exception { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element root = document.createElement(rootName); List words = (List) model.get("wordList"); for (Iterator it = words.iterator(); it.hasNext();) { String nextWord = (String) it.next(); Element wordNode = document.createElement("word"); Text textNode = document.createTextNode(nextWord); wordNode.appendChild(textNode); root.appendChild(wordNode); } return new DOMSource(root); } }; view.setStylesheetLocation(new ClassPathResource("org/springframework/web/servlet/view/xslt/firstWords.xsl")); view.setIndent(true); view.initApplicationContext(); Map map = new HashMap(); List wordList = new ArrayList(); wordList.add("hello"); wordList.add("world"); map.put("wordList", wordList); view.render(new ModelAndView("home", map).getModel(), request, response); String text = response.getContentAsString(); assertTrue(text.trim().startsWith("<html")); } private void incWarnings() { warnings++; } private void incErrors() { errors++; } private void incFatals() { fatal++; } private static final class TestXsltView extends AbstractXsltView { } private static final class Hero { private String name; private int age; private String catchphrase; public Hero() { } public Hero(String name, int age, String catchphrase) { this.name = name; this.age = age; this.catchphrase = catchphrase; } public String getCatchphrase() { return catchphrase; } public void setCatchphrase(String catchphrase) { this.catchphrase = catchphrase; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } }