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 package org.apache.qetest.dtm;
24
25 import java.io.FileOutputStream;
26 import java.io.StringReader;
27
28 import javax.xml.transform.Source;
29 import javax.xml.transform.stream.StreamSource;
30
31 import org.apache.qetest.Reporter;
32 import org.apache.xml.dtm.DTM;
33 import org.apache.xml.dtm.DTMAxisIterator;
34 import org.apache.xml.dtm.DTMAxisTraverser;
35 import org.apache.xml.dtm.DTMManager;
36 import org.apache.xml.dtm.ref.DTMManagerDefault;
37 import org.apache.xpath.objects.XMLStringFactoryImpl;
38
39 /**
40 * Static utility class for both general-purpose testing methods
41 * and a few XML-specific methods.
42 * Also provides a simplistic Test/Testlet launching helper
43 * functionality. Simply execute this class from the command
44 * line with a full or partial classname (in the org.apache.qetest
45 * area, obviously) and we'll load and execute that class instead.
46 * @author paul_dick@us.ibm.com
47 * @version $Id$
48 */
49 public abstract class QeDtmUtils
50 {
51 // abstract class cannot be instantiated
52
53
54 /** Subdirectory under test\tests\api for our xsl/xml files. */
55 public static final String DTM_SUBDIR = "dtm";
56 public static final String DTM_Prefix = "DTM_";
57 public static final String deepFile = "./tests/perf/xtestdata/elem10kdeep.xml";
58 public static final String flatFile = "./tests/perf/xtestdata/words-repeat.xml";
59
60
61 public static final String defaultSource=
62 "<?xml version=\"1.0\"?>\n"+
63 "<Document xmlns:d=\"www.d.com\" a1=\"hello\" a2=\"goodbye\">"+
64 "<!-- Default test document -->"+
65 "<?api a1=\"yes\" a2=\"no\"?>"+
66 "<A><!-- A Subtree --><B><C><D><E><F xmlns:f=\"www.f.com\" a1=\"down\" a2=\"up\"/></E></D></C></B></A>"+
67 "<Aa/><Ab/><Ac><Ac1/></Ac>"+
68 "<Ad xmlns:Ad=\"www.Ad.com\" xmlns:y=\"www.y.com\" xmlns:z=\"www.z.com\">"+
69 "<Ad1/></Ad>"+
70 "</Document>";
71
72 public static final String defaultSource2=
73 "<?xml version=\"1.0\"?>\n"+
74 " <bdd:dummyDocument xmlns:bdd=\"www.bdd.org\" version=\"99\">\n"+
75 " <!-- Default test document -->	&"+
76 " <?api attrib1=\"yes\" attrib2=\"no\"?>"+
77 " <A>\n"+
78 " <B hat=\"new\" car=\"Honda\" dog=\"Boxer\">Life is good</B>\n"+
79 " </A>\n"+
80 " <C>My Anaconda<xyz:D xmlns:xyz=\"www.xyz.org\"/>Words</C>\n"+
81 " Want a more interesting docuent, provide the URI on the command line!\n"+
82 " <Sub-Doc xmlns:d=\"www.d.com\" a1=\"hello\" a2=\"goodbye\">"+
83 " <!-- Default test Subdocument -->"+
84 " <?api a1=\"yes\" a2=\"no\"?>"+
85 " <A><!-- A Subtree --><B><C><D><E><f:F xmlns:f=\"www.f.com\" a1=\"down\" a2=\"up\"/></E></D></C></B></A>"+
86 " <Aa/><Ab/><Ac><Ac1/></Ac>"+
87 " <Ad:Ad xmlns:Ad=\"www.Ad.com\" xmlns:y=\"www.y.com\" xmlns:z=\"www.z.com\">"+
88 " <Ad1/></Ad:Ad>"+
89 " </Sub-Doc>"+
90 " </bdd:dummyDocument>\n";
91
92 public static final String simpleFlatFile=
93 "<?xml version=\"1.0\"?>\n"+
94 "<Doc>\n"+
95 "<item>XSLT</item>\n"+
96 "<item>processors</item>\n"+
97 "<item>must</item>\n"+
98 "<item>use</item>\n"+
99 "<item>XML</item>\n"+
100 "<item>Namespaces</item>\n"+
101 "<item>mechanism</item>\n"+
102 "</Doc>";
103
104
105 public static final String[] TYPENAME=
106 { "NULL",
107 "ELEMENT",
108 "ATTRIBUTE",
109 "TEXT",
110 "CDATA_SECTION",
111 "ENTITY_REFERENCE",
112 "ENTITY",
113 "PROCESSING_INSTRUCTION",
114 "COMMENT",
115 "DOCUMENT",
116 "DOCUMENT_TYPE",
117 "DOCUMENT_FRAGMENT",
118 "NOTATION",
119 "NAMESPACE"
120 };
121
122 // This routine generates a new DTM for each testcase
123 // Get a DTM manager, and ask it to load the DTM "uniquely",
124 // with no whitespace filtering, nonincremental, but _with_
125 // indexing (a fairly common case, and avoids the special
126 // mode used for RTF DTMs).
createDTM(int method, String theSource, StringBuffer buf)127 public static DTM createDTM(int method, String theSource, StringBuffer buf)
128 {
129 dtmWSStripper stripper = new dtmWSStripper();
130 long dtmStart = 0;
131 long dtmStop = 0;
132 Source source;
133 long startMem, startTotMem, stopMem, stopTotMem, postGCfree, postGCtotal;
134
135
136 // Create DTM and generate initial context
137 if (method == 1)
138 {
139 source = new StreamSource(new StringReader(theSource));
140 }
141 else
142 {
143 source=new StreamSource(theSource);
144 }
145
146 startMem = Runtime.getRuntime().freeMemory();
147 startTotMem = Runtime.getRuntime().totalMemory();
148
149 dtmStart = System.currentTimeMillis();
150 DTMManager manager= new DTMManagerDefault().newInstance(new XMLStringFactoryImpl());
151 DTM dtm=manager.getDTM(source, true, stripper, false, true);
152 dtmStop = System.currentTimeMillis();
153
154 stopMem = Runtime.getRuntime().freeMemory();
155 stopTotMem = Runtime.getRuntime().totalMemory();
156
157 Runtime.getRuntime().gc();
158
159 postGCfree = Runtime.getRuntime().freeMemory();
160 postGCtotal = Runtime.getRuntime().totalMemory();
161
162 buf.append("\nPre-DTM free memory:\t" + startMem + "/" + startTotMem);
163 buf.append("\nPost-DTM free memory:\t" + stopMem + "/" + stopTotMem);
164 buf.append("\nPost-GC free memory:\t" + postGCfree + "/" + postGCtotal);
165
166
167 buf.append("\nInit of DTM took: \t"+ (dtmStop-dtmStart) + "\n");
168 System.out.println(buf);
169 return dtm;
170 }
171
timeAxisIterator(DTM dtm, int axis, int context, int[] rtdata)172 public static void timeAxisIterator(DTM dtm, int axis, int context, int[] rtdata)
173 {
174 long startTime = 0;
175 long iterTime = 0;
176 int atNode = 0;
177 int lastNode = 0;
178 int numOfNodes =0;
179
180 // Time creation and iteration.
181 startTime = System.currentTimeMillis();
182
183 DTMAxisIterator iter = dtm.getAxisIterator(axis);
184 iter.setStartNode(context);
185
186 for (atNode = iter.next(); DTM.NULL != atNode; atNode = iter.next())
187 {
188 lastNode = atNode;
189 numOfNodes = numOfNodes + 1; // Need to know that we Iterated the whole tree
190 }
191
192 iterTime = System.currentTimeMillis() - startTime;
193
194 if (lastNode != 0)
195 getNodeInfo(dtm, lastNode, " ");
196
197 rtdata[0] = (int)iterTime;
198 rtdata[1] = lastNode;
199 rtdata[2] = numOfNodes;
200 }
201
202
timeAxisTraverser(DTM dtm, int axis, int context, int[] rtdata)203 static void timeAxisTraverser(DTM dtm, int axis, int context, int[] rtdata)
204 {
205 long startTime = 0;
206 long travTime = 0;
207 int atNode = 0;
208 int lastNode = 0;
209 int numOfNodes =0;
210
211 // Time the creation and traversal.
212 startTime = System.currentTimeMillis();
213
214 DTMAxisTraverser at = dtm.getAxisTraverser(axis);
215
216 for (atNode = at.first(context); DTM.NULL != atNode; atNode = at.next(context, atNode))
217 {
218 lastNode = atNode;
219 numOfNodes = numOfNodes + 1;
220 }
221
222 travTime = System.currentTimeMillis() - startTime;
223
224 if (lastNode != 0)
225 getNodeInfo(dtm, lastNode, " ");
226
227 rtdata[0] = (int)travTime;
228 rtdata[1] = lastNode;
229 rtdata[2] = numOfNodes;
230
231 }
232
233 // This routine gathers up all the important info about a node, concatenates
234 // in all together into a single string and returns it.
getNodeInfo(DTM dtm, int nodeHandle, String indent)235 public static String getNodeInfo(DTM dtm, int nodeHandle, String indent)
236 {
237 // Formatting hack -- suppress quotes when value is null, to distinguish
238 // it from "null" (JK).
239 String buf = new String("null");
240 String value=dtm.getNodeValue(nodeHandle);
241 String vq = (value==null) ? "" : "\"";
242
243 // Skip outputing of text nodes. In most cases they clutter the output,
244 // besides I'm only interested in the elemental structure of the dtm.
245 if( TYPENAME[dtm.getNodeType(nodeHandle)] != "TEXT" )
246 {
247 buf = new String(indent+
248 nodeHandle+": "+
249 TYPENAME[dtm.getNodeType(nodeHandle)]+" "+
250 dtm.getNodeName(nodeHandle)+" "+
251 " Level=" + dtm.getLevel(nodeHandle)+" "+
252 "\tValue=" + vq + value + vq + "\n"
253 );
254 }
255
256 return buf;
257 }
258
259 // This routine generates the output file stream.
openFileStream(String name, Reporter reporter)260 public static FileOutputStream openFileStream(String name, Reporter reporter)
261 {
262 FileOutputStream fos = null;
263
264 try
265 { fos = new FileOutputStream(name); }
266
267 catch (Exception e)
268 { reporter.checkFail("Failure opening output file."); }
269
270 return fos;
271 }
272
273 // This routine writes the results to the output file.
writeClose(FileOutputStream fos, StringBuffer buf, Reporter reporter)274 public static void writeClose(FileOutputStream fos, StringBuffer buf, Reporter reporter)
275 {
276 // Write results and close output file.
277 try
278 {
279 fos.write(buf.toString().getBytes());
280 fos.close();
281 }
282
283 catch (Exception e)
284 { reporter.checkFail("Failure writing output."); }
285 }
286
287
288
289 }
290