001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s): Alexandre Iline.
025: *
026: * The Original Software is the Jemmy library.
027: * The Initial Developer of the Original Software is Alexandre Iline.
028: * All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: *
041: *
042: *
043: * $Id: Dumper.java,v 1.8 2007/10/05 11:36:15 jskrivanek Exp $ $Revision: 1.8 $ $Date: 2007/10/05 11:36:15 $
044: *
045: */
046:
047: package org.netbeans.jemmy.util;
048:
049: import java.awt.*;
050: import java.io.*;
051: import java.util.*;
052: import org.netbeans.jemmy.*;
053: import org.netbeans.jemmy.QueueTool.QueueAction;
054: import org.netbeans.jemmy.operators.*;
055:
056: /**
057: * Allows to "dump" current GUI state into XML file.
058: * Uses operators' getDump methods to gather the information.
059: *
060: * @author Alexandre Iline (alexandre.iline@sun.com)
061: *
062: */
063:
064: public class Dumper {
065:
066: /**
067: * Prints XML DTD information.
068: * @param writer a writer to write to.
069: */
070: public static void printDTD(PrintWriter writer) {
071: printDTD(writer, "");
072: }
073:
074: /**
075: * Prints XML DTD information.
076: * @param writer a stream to write to.
077: */
078: public static void printDTD(PrintStream writer) {
079: printDTD(new PrintWriter(writer));
080: }
081:
082: /**
083: * Prints XML DTD information into file.
084: * @param fileName a file to write to.
085: * @throws FileNotFoundException
086: */
087: public static void printDTD(String fileName)
088: throws FileNotFoundException {
089: printDTD(new PrintWriter(new FileOutputStream(fileName)));
090: }
091:
092: /**
093: * Prints component hierarchy (GUI dump)
094: * starting from <code>comp</code> component.
095: * @param comp a component to get information from.
096: * @param writer a writer to write to.
097: */
098: public static void dumpComponent(Component comp,
099: final PrintWriter writer, final DumpController listener) {
100: QueueTool qt = new QueueTool();
101: Component[] comps;
102: if (comp != null) {
103: comps = new Component[1];
104: comps[0] = comp;
105: } else {
106: comps = Frame.getFrames();
107: }
108: final Component[] comps_final = comps;
109: qt.invokeAndWait(new QueueAction("dumpComponent") {
110: public Object launch() throws Exception {
111: printHeader(writer);
112: dumpSome("dump", comps_final, writer, "", listener);
113: writer.flush();
114: return null;
115: }
116: });
117: }
118:
119: public static void dumpComponent(Component comp, PrintWriter writer) {
120: dumpComponent(comp, writer, new DumpController() {
121: public boolean onComponentDump(Component comp) {
122: return (true);
123: }
124:
125: public boolean onPropertyDump(Component comp, String name,
126: String value) {
127: return (true);
128: }
129: });
130: }
131:
132: /**
133: * Prints component hierarchy (GUI dump).
134: * starting from <code>comp</code> component.
135: * @param comp a component to get information from.
136: * @param writer a stream to write to.
137: */
138: public static void dumpComponent(Component comp, PrintStream writer) {
139: dumpComponent(comp, new PrintWriter(writer));
140: }
141:
142: public static void dumpComponent(Component comp,
143: PrintStream writer, DumpController listener) {
144: dumpComponent(comp, new PrintWriter(writer), listener);
145: }
146:
147: /**
148: * Prints component hierarchy (GUI dump) into file.
149: * @param comp a component to get information from.
150: * @param fileName a file to write to.
151: * @throws FileNotFoundException
152: */
153: public static void dumpComponent(Component comp, String fileName)
154: throws FileNotFoundException {
155: dumpComponent(comp, new PrintWriter(new FileOutputStream(
156: fileName)));
157: }
158:
159: public static void dumpComponent(Component comp, String fileName,
160: DumpController listener) throws FileNotFoundException {
161: dumpComponent(comp, new PrintWriter(new FileOutputStream(
162: fileName)), listener);
163: }
164:
165: /**
166: * Prints all component hierarchy (GUI dump).
167: * @param writer a writer to write to.
168: */
169: public static void dumpAll(PrintWriter writer) {
170: dumpComponent(null, writer);
171: }
172:
173: public static void dumpAll(PrintWriter writer,
174: DumpController listener) {
175: dumpComponent(null, writer, listener);
176: }
177:
178: /**
179: * Prints all component hierarchy (GUI dump).
180: * @param writer a stream to write to.
181: */
182: public static void dumpAll(PrintStream writer) {
183: dumpAll(new PrintWriter(writer));
184: }
185:
186: public static void dumpAll(PrintStream writer,
187: DumpController listener) {
188: dumpAll(new PrintWriter(writer), listener);
189: }
190:
191: /**
192: * Prints component hierarchy (GUI dump) into file.
193: * @param fileName a file to write to.
194: * @throws FileNotFoundException
195: */
196: public static void dumpAll(String fileName)
197: throws FileNotFoundException {
198: dumpAll(new PrintWriter(new FileOutputStream(fileName)));
199: }
200:
201: public static void dumpAll(String fileName, DumpController listener)
202: throws FileNotFoundException {
203: dumpAll(new PrintWriter(new FileOutputStream(fileName)),
204: listener);
205: }
206:
207: private static final String tabIncrease = " ";
208:
209: private static void printTagStart(PrintWriter writer, String tag,
210: String tab) {
211: writer.println(tab + "<" + tag + ">");
212: }
213:
214: private static void printTagOpening(PrintWriter writer, String tag,
215: String tab) {
216: writer.print(tab + "<" + tag);
217: }
218:
219: private static void printTagClosing(PrintWriter writer, String tag) {
220: writer.println(">");
221: }
222:
223: private static void printTagEnd(PrintWriter writer, String tag,
224: String tab) {
225: writer.println(tab + "</" + tag + ">");
226: }
227:
228: private static void printEmptyTagOpening(PrintWriter writer,
229: String tag, String tab) {
230: writer.print(tab + "<" + tag);
231: }
232:
233: private static void printEmptyTagClosing(PrintWriter writer,
234: String tag) {
235: writer.println("/>");
236: }
237:
238: private static void dumpSome(String tag, Component[] comps,
239: PrintWriter writer, String tab, DumpController listener) {
240: if (comps.length > 0) {
241: printTagStart(writer, tag, tab);
242: for (int i = 0; i < comps.length; i++) {
243: dumpOne(comps[i], writer, tab + tabIncrease, listener);
244: }
245: printTagEnd(writer, tag, tab);
246: }
247: }
248:
249: private static void dumpOne(Component component,
250: PrintWriter writer, String tab, DumpController listener) {
251: //whether to dump at all
252: boolean toDump = listener.onComponentDump(component);
253: if (toDump) {
254: try {
255: Operator oper = Operator.createOperator(component);
256: Hashtable componentDump = oper.getDump();
257: printTagOpening(writer, "component", tab);
258: writer.print(" operator=\"" + oper.getClass().getName()
259: + "\"");
260: printTagClosing(writer, "component");
261: Object[] keys = componentDump.keySet().toArray();
262: Arrays.sort(keys);
263: String name, value;
264: for (int i = 0; i < keys.length; i++) {
265: name = (String) keys[i];
266: value = ((String) componentDump.get(keys[i]));
267: if (listener.onPropertyDump(component, name, value)) {
268: printEmptyTagOpening(writer, "property", tab
269: + tabIncrease);
270: writer.print(" name=\"" + escape(name)
271: + "\" value=\"" + escape(value) + "\"");
272: printEmptyTagClosing(writer, "property");
273: }
274: }
275: } catch (Exception e) {
276: JemmyProperties.getCurrentOutput().printStackTrace(e);
277: printTagStart(writer, "component", tab);
278: printEmptyTagOpening(writer, "exception", tab
279: + tabIncrease);
280: writer.print(" toString=\"" + escape(e.toString())
281: + "\"");
282: printEmptyTagClosing(writer, "exception");
283: }
284: }
285: if (component instanceof Window) {
286: dumpSome("subwindows", ((Window) component)
287: .getOwnedWindows(), writer, tab + tabIncrease,
288: listener);
289: }
290: if (component instanceof Container) {
291: dumpSome("subcomponents", ((Container) component)
292: .getComponents(), writer, tab + tabIncrease,
293: listener);
294: }
295: if (toDump) {
296: printTagEnd(writer, "component", tab);
297: }
298: }
299:
300: private static void printHeader(PrintWriter writer) {
301: writer.println("<?xml version=\"1.0\"?>");
302: writer.println("<!DOCTYPE dump [");
303: printDTD(writer, tabIncrease);
304: writer.println("]>");
305: }
306:
307: private static void printDTD(PrintWriter writer, String tab) {
308: writer.println(tab + "<!ELEMENT dump (component*)>");
309: writer
310: .println(tab
311: + "<!ELEMENT component (property+, subcomponents?, subwindows?, exception?)>");
312: writer.println(tab + "<!ELEMENT subcomponents (component+)>");
313: writer.println(tab + "<!ELEMENT subwindows (component+)>");
314: writer.println(tab + "<!ELEMENT property EMPTY>");
315: writer.println(tab + "<!ELEMENT exception EMPTY>");
316: writer.println(tab + "<!ATTLIST component");
317: writer.println(tab + " operator CDATA #IMPLIED>");
318: writer.println(tab + "<!ATTLIST exception");
319: writer.println(tab + " toString CDATA #REQUIRED>");
320: writer.println(tab + "<!ATTLIST property");
321: writer.println(tab + " name CDATA #REQUIRED");
322: writer.println(tab + " value CDATA #REQUIRED>");
323: }
324:
325: public static String escape(String str) {
326: return str.replaceAll("&", "&").replaceAll("<", "<")
327: .replaceAll(">", ">").replaceAll("\"", """);
328: }
329: }
|