• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 
22 /*
23  *
24  * ExtensionTestlet.java
25  *
26  */
27 package org.apache.qetest.xsl;
28 
29 import java.io.File;
30 import java.lang.reflect.Method;
31 
32 import org.apache.qetest.Datalet;
33 import org.apache.qetest.Logger;
34 
35 /**
36  * Testlet for testing xsl stylesheet extensions.
37  *
38  * This class provides the testing algorithim used for verifying
39  * Xalan-specific extensions, primarily by transforming stylesheets
40  * that use extensions and optionally by allowing any Java-based
41  * extension classes to verify themselves and log out info.
42  *
43  * @author Shane_Curcuru@lotus.com
44  * @version $Id$
45  */
46 public class ExtensionTestlet extends StylesheetTestlet
47 {
48     // Initialize our classname for TestletImpl's main() method
49     static { thisClassName = "org.apache.qetest.xsl.ExtensionTestlet"; }
50 
51     // Initialize our defaultDatalet
52     { defaultDatalet = (Datalet)new StylesheetDatalet(); }
53 
54     /** Convenience constant: Property key for Java classnames.  */
55     public static final String JAVA_CLASS_NAME = "java.class.name";
56 
57     /** Convenience constant: Property key for TestableExtension objects.  */
58     public static final String TESTABLE_EXTENSION = "testable.extension";
59 
60     /**
61      * Accesor method for a brief description of this test.
62      * @return String describing what this ExtensionTestlet does.
63      */
getDescription()64     public String getDescription()
65     {
66         return "ExtensionTestlet";
67     }
68 
69 
70     /**
71      * Worker method to perform any pre-processing needed.
72      *
73      * This optionally does deleteOutFile, then attempts to load
74      * a matching TestableExtension class that matches the datalet's
75      * stylesheet.  If one is found, we call preCheck on that too.
76      *
77      * @param datalet to test with
78      */
testletInit(StylesheetDatalet datalet)79     protected void testletInit(StylesheetDatalet datalet)
80     {
81         // Simply grab any superclass functionality first
82         super.testletInit(datalet);
83 
84         // Now do custom initialization for extensions
85 
86         // See if we have a Java-based extension class
87         // Side effect: fills in datalet.options
88         findExtensionClass(datalet);
89 
90         // If found, ask the class to validate
91         Class extensionClazz = (Class)datalet.options.get(TESTABLE_EXTENSION);
92         if (null != extensionClazz)
93         {
94             boolean ignored = invokeMethodOn(extensionClazz, "preCheck", datalet);
95         }
96         else
97         {
98             logger.logMsg(Logger.TRACEMSG, "No extension class found");
99         }
100     }
101 
102 
103     /**
104      * Worker method to validate output file with gold.
105      *
106      * Logs out applicable info while validating output file.
107      * Most commonly will call the underlying TestableExtension's
108      * postCheck method to get validation done.
109      *
110      * @param datalet to test with
111      * @throws allows any underlying exception to be thrown
112      */
checkDatalet(StylesheetDatalet datalet)113     protected void checkDatalet(StylesheetDatalet datalet)
114             throws Exception
115     {
116         // If we have an associated extension class, call postCheck
117         // If found, ask the class to validate
118         Class extensionClazz = (Class)datalet.options.get(TESTABLE_EXTENSION);
119         if (null != extensionClazz)
120         {
121             boolean ignored = invokeMethodOn(extensionClazz, "postCheck", datalet);
122         }
123         else
124         {
125             // Have our parent class do it's own validation
126             super.checkDatalet(datalet);
127         }
128     }
129 
130 
131     /**
132      * Worker method: Try to find a matching .class file for this .xsl.
133      *
134      * Accesses our class member logger.
135      * @param d datalet to use for testing
136      */
findExtensionClass(StylesheetDatalet datalet)137     protected void findExtensionClass(StylesheetDatalet datalet)
138     {
139         // Find the basename of the stylesheet
140         String classname = null;
141         if (null != datalet.inputName)
142         {
143             classname = datalet.inputName.substring(0, datalet.inputName.indexOf(".xsl"));
144         }
145         else
146         {
147             classname = datalet.xmlName.substring(0, datalet.xmlName.indexOf(".xml"));
148         }
149 
150         // Also rip off any pathing info if it's found
151         classname = classname.substring(classname.lastIndexOf(File.separator) + 1);
152 
153         try
154         {
155             //@todo future work: since these Java extensions are all
156             //  packageless, figure out a better way to reduce name
157             //  collisions - perhaps allow as org.apache.qetest.something
158             Class extensionClazz = Class.forName(classname);
159             logger.logMsg(Logger.TRACEMSG, "findExtensionClass found for "
160                     + classname + " which is " + extensionClazz.getName());
161 
162             // Ensure the class is a TestableExtension
163             if ((TestableExtension.class).isAssignableFrom((Class)extensionClazz))
164             {
165                 // Store info about class in datalet
166                 datalet.options.put(JAVA_CLASS_NAME, extensionClazz.getName());
167                 datalet.options.put(TESTABLE_EXTENSION, extensionClazz);
168             }
169             else
170             {
171                 logger.logMsg(Logger.STATUSMSG, "findExtensionClass was not a TestableExtension, was: " + extensionClazz);
172             }
173         }
174         catch (Exception e)
175         {
176             logger.logMsg(Logger.INFOMSG, "findExtensionClass not found for " + classname);
177         }
178     }
179 
180 
181     /**
182      * Worker method: Call a method on this extension.
183      * Only works for preCheck/postCheck, since they have the
184      * proper method signatures.
185      *
186      * Accesses our class member logger.
187      * @param extensionClazz Class that's assumed to be a TestableExtension
188      * @param methodName method to invoke
189      * @param datalet to pass to method
190      */
invokeMethodOn(Class extensionClazz, String methodName, StylesheetDatalet datalet)191     protected boolean invokeMethodOn(Class extensionClazz,
192             String methodName, StylesheetDatalet datalet)
193     {
194         try
195         {
196             Class[] parameterTypes = new Class[2];
197             parameterTypes[0] = Logger.class;
198             parameterTypes[1] = StylesheetDatalet.class;
199             Method method = extensionClazz.getMethod(methodName, parameterTypes);
200 
201             // Call static method to perform pre-transform validation
202             // Pass on the datalet's options in case it uses them
203             Object[] parameters = new Object[2];
204             parameters[0] = logger;
205             parameters[1] = datalet;
206             Object returnValue = method.invoke(null, parameters);
207             // If the method returned something, return that ..
208             if ((null != returnValue)
209                 && (returnValue instanceof Boolean))
210             {
211                 return ((Boolean)returnValue).booleanValue();
212             }
213             else
214             {
215                 // .. otherwise just return true by default
216                 return true;
217             }
218         }
219         catch (Exception e)
220         {
221             logger.logThrowable(Logger.WARNINGMSG, e, "invokeMethodOn(" + methodName + ") threw");
222             logger.checkErr("invokeMethodOn(" + methodName + ") threw: " + e.toString());
223             return false;
224         }
225     }
226 
227 }  // end of class ExtensionTestlet
228 
229