001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2003-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or 1any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: AbsDeploymentTest.java 7463 2005-10-04 11:35:36Z sauthieg $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_lib.deployment.tests;
025:
026: // java
027: import java.io.Reader;
028: import java.io.StringReader;
029: import java.io.File;
030: import java.io.FileReader;
031: import java.lang.reflect.Method;
032: import java.util.Hashtable;
033: import java.util.StringTokenizer;
034: import javax.xml.namespace.QName;
035:
036: // jonas
037: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
038: import org.objectweb.jonas_lib.deployment.xml.AbsElement;
039: import org.objectweb.jonas_lib.deployment.xml.Element;
040: import org.objectweb.jonas_lib.deployment.xml.Qname;
041:
042: /**
043: * Defines an abstract class for testing the classes built with Digester
044: * @author Florent Benoit
045: */
046: public abstract class AbsDeploymentTest {
047:
048: /**
049: * Counter for each kind of element
050: */
051: private Hashtable elementsCounter = null;
052:
053: /**
054: * Build a new Test
055: */
056: protected AbsDeploymentTest() {
057: elementsCounter = new Hashtable();
058: }
059:
060: /**
061: * Create an xml structure and then parse the resulting xml and check the
062: * result No validation is done if random is set to true
063: * @throws Exception if the stress test is not successfull
064: */
065: public void stress() throws Exception {
066:
067: startTest(false);
068:
069: for (int i = 0; i < 100; i++) {
070: startTest(true);
071: }
072: }
073:
074: // Abstract Methods used by startTest implemented in subclasses
075:
076: public abstract AbsElement getTopLevelElement() throws Exception;
077:
078: public abstract String parse(Reader reader, String name,
079: boolean validation) throws Exception;
080:
081: /**
082: * Defines the function for the specific test
083: * @param random use random or not to fill elements
084: * @throws Exception if the test failed
085: */
086: public void startTest(boolean random) throws Exception {
087: AbsElement ae = getTopLevelElement();
088: fill(ae, random);
089: String xmlOriginal = ae.toXML();
090: String xmlParsed = parse(new StringReader(xmlOriginal), "test",
091: false);
092: checkDiff(xmlOriginal, xmlParsed);
093:
094: }
095:
096: /**
097: * Gets the xml after digester parsing
098: * @throws Exception if the parsing fail
099: */
100: public void parseElement() throws Exception {
101: AbsElement ae = getTopLevelElement();
102: fill(ae, false);
103: System.out.println("Parsing xml :");
104: System.out.println(ae);
105: String xmlOriginal = ae.toXML();
106: String xmlParsed = parse(new StringReader(xmlOriginal), "test",
107: false);
108: System.out.println("Result = ");
109: System.out.println(xmlParsed);
110: }
111:
112: /**
113: * parse with validation from an xml file
114: * @throws Exception if the parsing fail
115: */
116: public void parseXmlfromFile(String fileName) throws Exception {
117: FileReader fileReader = null;
118:
119: // Check if the file exists.
120: if (!new File(fileName).exists()) {
121: throw new DeploymentDescException("The file '" + fileName
122: + "' was not found.");
123: }
124: fileReader = new FileReader(fileName);
125: System.out.println("Parsing xml : " + fileName);
126: String xmlParsed = parse(fileReader, fileName, true);
127: System.out.println("Parsing OK Result = ");
128: System.out.println(xmlParsed);
129: }
130:
131: /**
132: * Check the difference between original xml and parsed xml
133: * @param xmlOriginal original XML
134: * @param xmlParsed parsed XML
135: * @throws Exception if there is a difference between original and parsed
136: * XML
137: */
138: protected void checkDiff(String xmlOriginal, String xmlParsed)
139: throws Exception {
140: StringTokenizer stOri = new StringTokenizer(xmlOriginal, "\n");
141: StringTokenizer stPardsed = new StringTokenizer(xmlParsed, "\n");
142:
143: // Compare line by line
144: while (stOri.hasMoreTokens() && stPardsed.hasMoreTokens()) {
145: String lineOri = stOri.nextToken();
146: String lineparsed = stPardsed.nextToken();
147: if (!lineOri.equals(lineparsed)) {
148: System.err.println("Failure in xml :");
149: System.err.println(xmlOriginal);
150: throw new Exception("Line : " + lineOri
151: + " is different than parsed value: "
152: + lineparsed);
153: }
154: }
155: }
156:
157: /**
158: * Fill the structure of the given element. Fill randomly if random is set
159: * to true
160: * @param element element to fill
161: * @param random determines if the element must be filled randomly or not
162: * @throws Exception if the element can not be filled
163: */
164: public void fill(Element element, boolean random) throws Exception {
165:
166: // Get setters of the element
167: Method[] methods = element.getClass().getMethods();
168:
169: // Analyze if it is Set or Add Method
170: for (int i = 0; i < methods.length; i++) {
171: // Get name
172: Method method = methods[i];
173: String name = method.getName();
174: Class[] argsMethod = null;
175: argsMethod = method.getParameterTypes();
176:
177: // One argument method
178: if ((argsMethod.length == 1)
179: && (((name.startsWith("set") && (!name
180: .equalsIgnoreCase("setHeader"))) || name
181: .startsWith("add")))) {
182: Class cl = argsMethod[0];
183: if (cl.getName().equals("java.lang.String")) {
184: // Test if it's one argument with String type :
185: fillString(element, method, random);
186: } else if (cl.getName().equals(
187: "javax.xml.namespace.QName")) {
188: fillQName(element, method, random);
189: } else {
190: // It's a subelement
191: if (name.startsWith("set")) {
192: setElement(element, method, argsMethod, random);
193: } else {
194: addElement(element, method, argsMethod, random);
195: }
196: }
197: }
198:
199: }
200:
201: }
202:
203: /**
204: * Random for returning true or false
205: * @return true or false with random
206: */
207: protected boolean aleatOK() {
208: return (Math.random() > 0.5);
209: }
210:
211: /**
212: * Gives a number between 0 and 5
213: * @return a random intger number between 0 and 5
214: */
215: protected int nbAleat() {
216: return (int) (Math.random() * 5);
217: }
218:
219: /**
220: * Add to an element its sub element Add many times a sub-element if random
221: * is not set to true
222: * @param element element on which we have to add sub elements
223: * @param method method of the element (determine type of the sub element
224: * @param argsMethod arguments of the method
225: * @param random use random or not
226: * @throws Exception if the subelement can not be added
227: */
228: protected void addElement(Element element, Method method,
229: Class[] argsMethod, boolean random) throws Exception {
230: int nb = 1;
231: if (random) {
232: nb = nbAleat();
233: }
234: for (int i = 0; i < nb; i++) {
235: setElement(element, method, argsMethod, random);
236: }
237: }
238:
239: /**
240: * Set the subelement of an element The subelement may not be set if random
241: * is used
242: * @param element element on which we have to add sub elements
243: * @param method method of the element (determine type of the sub element
244: * @param argsMethod arguments of the method
245: * @param random use random or not
246: * @throws Exception if the subelement can not be set
247: */
248: protected void setElement(Element element, Method method,
249: Class[] argsMethod, boolean random) throws Exception {
250: if (random && !aleatOK()) {
251: return;
252: }
253:
254: String name = method.getName();
255:
256: Class cl = argsMethod[0];
257: String className = cl.getName();
258:
259: // Element object ?
260: if (Element.class.isAssignableFrom(cl)) {
261: // Create required object
262: Object subElement = cl.newInstance();
263:
264: // Add object on top level object
265: method.invoke(element, new Object[] { subElement });
266:
267: // Fill values of this element
268: fill((Element) subElement, random);
269:
270: // Qname is a particular type, need to set the name
271: if (cl.isAssignableFrom(Qname.class)) {
272: // Transform name into Qname
273: String qNameElement = convertUpperCaseToXml(name
274: .substring(3, name.length()));
275: ((Qname) subElement).setName(qNameElement);
276: }
277:
278: }
279: }
280:
281: /**
282: * Set the string attribute of the given element
283: * @param element element on which we have to set the string
284: * @param method method of the element (determine type of the sub element
285: * @param random use random or not
286: * @throws Exception if the String attribute can not be added
287: */
288: protected void fillString(Element element, Method method,
289: boolean random) throws Exception {
290: if (random && !aleatOK()) {
291: return;
292: }
293: method.invoke(element,
294: (Object[]) new String[] { getNameCounterForElement(
295: element, method) });
296: }
297:
298: /**
299: * Set the QName attribute of the given element
300: * @param element element on which we have to set the string
301: * @param method method of the element (determine type of the sub element
302: * @param random use random or not
303: * @throws Exception if the QName can not be set
304: */
305: protected void fillQName(Element element, Method method,
306: boolean random) throws Exception {
307: if (random && !aleatOK()) {
308: return;
309: }
310: QName qName = new QName("prefix:Test",
311: getNameCounterForElement(element, method));
312: method.invoke(element, (Object[]) new QName[] { qName });
313: }
314:
315: /**
316: * Gives a Name + counter for a type of an element This is used to add
317: * counter when adding xml attributes Only use in order to make easier the
318: * read of the parsed XML file
319: * @param element the given element for which we want a counter
320: * @param method the name of the string to add
321: * @return the Name + counter for the specified element type
322: */
323: protected String getNameCounterForElement(Element element,
324: Method method) {
325: StringBuffer sb = new StringBuffer();
326:
327: // Extract package.classname
328: String name = method.getName().substring(3,
329: method.getName().length());
330: String packageClassname = element.getClass().getPackage()
331: .getName();
332: String fullClass = packageClassname + "." + name;
333:
334: // Existing counter ?
335: Integer counter = (Integer) elementsCounter.get(fullClass);
336: if (counter == null) {
337: // init counter as it don't already exist
338: counter = new Integer(0);
339: } else {
340: // Increment
341: counter = new Integer(counter.intValue() + 1);
342: }
343: elementsCounter.put(fullClass, counter);
344:
345: // return value
346: return name + counter.intValue();
347: }
348:
349: /**
350: * Convert the name of an element into its xml string representation example :
351: * WebApp --> web-app
352: * @param name the name of the element to convert
353: * @return the xml string representation of an element
354: */
355: protected String convertUpperCaseToXml(String name) {
356: StringBuffer sb = new StringBuffer();
357: sb.append(Character.toLowerCase(name.charAt(0)));
358:
359: for (int i = 1; i < name.length(); i++) {
360: if (Character.isUpperCase(name.charAt(i))) {
361: sb.append("-");
362: }
363: sb.append(Character.toLowerCase(name.charAt(i)));
364:
365: }
366: return sb.toString();
367:
368: }
369:
370: }
|