View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2006 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  package com.mindtree.techworks.insight.reporting;
25  
26  import java.io.IOException;
27  import java.io.StringReader;
28  import java.io.StringWriter;
29  
30  import javax.xml.parsers.DocumentBuilder;
31  import javax.xml.parsers.DocumentBuilderFactory;
32  import javax.xml.parsers.ParserConfigurationException;
33  
34  import org.apache.xml.serialize.OutputFormat;
35  import org.apache.xml.serialize.XMLSerializer;
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  import org.w3c.dom.Node;
39  import org.w3c.dom.NodeList;
40  import org.xml.sax.InputSource;
41  import org.xml.sax.SAXException;
42  
43  
44  /**
45   * Utility class which has methods for handling common tasks in XML serializing
46   * and deserializing <code>Verifier</code>s and <code>Job</code>s.
47   *  
48   * @author <a href="mailto:bindul_bhowmik@mindtree.com">Bindul Bhowmik</a>
49   * @version $Revision: 27 $ $Date: 2007-12-16 04:58:03 -0700 (Sun, 16 Dec 2007) $
50   * @since Insight 1.5
51   */
52  public abstract class SerializationXmlUtils {
53  	
54  	// -------------------------------------------------------------------------
55  	// Constants
56  	// -------------------------------------------------------------------------
57  	
58  	/**
59  	 * Characters to escape in XML strings and their replacements.
60  	 */
61  	private static final String[][] XML_CHARS_TO_ESCAPE = { 
62  		{"&", "&amp;"},
63  		{"<", "&lt;"},
64  		{">", "&gt;"},
65  		{"'", "&apos;"},
66  		{"\"", "&quot;"}};
67  	
68  	// -------------------------------------------------------------------------
69  	// Public utility methods
70  	// -------------------------------------------------------------------------
71  
72  	/**
73  	 * Creates an XML Document from the XML String.
74  	 * 
75  	 * @param xmlString
76  	 *            The Serialized XML.
77  	 * @return A <code>Document</code> for the XML passed in.
78  	 * @throws InitializationException
79  	 *             If there is an exception while parsing the XML.
80  	 */
81  	public static Document createDocument (String xmlString)
82  			throws InitializationException {
83  	
84  		StringReader reader = new StringReader (xmlString.trim ());
85  		InputSource inputSource = new InputSource (reader);
86  	
87  		DocumentBuilderFactory domFactory = DocumentBuilderFactory
88  				.newInstance ();
89  		Document document = null;
90  	
91  		try {
92  			DocumentBuilder docBuilder = domFactory.newDocumentBuilder ();
93  			document = docBuilder.parse (inputSource);
94  		} catch (ParserConfigurationException e) {
95  			throw new InitializationException (
96  					"Could not parse serialized verifier.", e);
97  		} catch (SAXException e) {
98  			throw new InitializationException (
99  					"Could not parse serialized verifier.", e);
100 		} catch (IOException e) {
101 			throw new InitializationException (
102 					"Could not parse serialized verifier.", e);
103 		}
104 	
105 		return document;
106 	}
107 
108 	/**
109 	 * Returns the text value in an XML Element.
110 	 * <p>
111 	 * If an XML element is passed in in the format
112 	 * <code>&lt;element&gt;value&lt;/element&gt;</code>, then the
113 	 * <code>value</code> part of it is returned.
114 	 * </p>
115 	 * <p>
116 	 * If the element does not have a text value in it, then <code>null</code>
117 	 * is returned.
118 	 * </p>
119 	 * 
120 	 * @param element
121 	 *            The element from which the value is to be extracted.
122 	 * @return The text value in the element, if present, or <code>null</code>.
123 	 */
124 	public static String getTextValue (Element element) {
125 	
126 		String textValue = null;
127 	
128 		NodeList textNodes = element.getChildNodes ();
129 		for (int i = 0; i < textNodes.getLength (); i++ ) {
130 			Node textNode = textNodes.item (i);
131 			if (textNode.getNodeType () == Node.TEXT_NODE) {
132 				textValue = textNode.getNodeValue ();
133 				break;
134 			}
135 		}
136 	
137 		return textValue;
138 	}
139 	
140 	/**
141 	 * Escapes all the special characters to avoid in the value of the string
142 	 * representation of the filter criterion.
143 	 * 
144 	 * @param unescapedString The unescaped string.
145 	 * @return String with the special characters escaped.
146 	 */
147 	public static String escapeSpecialChars (String unescapedString) {
148 
149 		StringBuffer escapedString = new StringBuffer(unescapedString);
150 		
151 		// Escape XML special characters
152 		for (int i = 0; i < XML_CHARS_TO_ESCAPE.length; i++) {
153 			int charIndex = escapedString.indexOf(XML_CHARS_TO_ESCAPE[i][0]);
154 			if (charIndex >= 0) {
155 				while (charIndex != -1) {
156 					escapedString.replace (charIndex, charIndex + 1,
157 											XML_CHARS_TO_ESCAPE[i][1]);
158 					charIndex = escapedString
159 							.indexOf (XML_CHARS_TO_ESCAPE[i][0], charIndex
160 									+ XML_CHARS_TO_ESCAPE[i][1].length ());
161 				}
162 			}
163 		}
164 		
165 		return escapedString.toString();
166 	}
167 
168 	/**
169 	 * Serializes the XML element passed in to string format.
170 	 * 
171 	 * @param element
172 	 *            The element to serialize
173 	 * @return The serialized XML as a string.
174 	 * @throws InitializationException
175 	 *             If the underlying implementation cannot serialize the
176 	 *             element.
177 	 */
178 	public static String serializeXmlElement (Element element)
179 			throws InitializationException {
180 
181 		// Format to serialize the XML
182 		OutputFormat format = new OutputFormat(element.getOwnerDocument());
183 		format.setOmitXMLDeclaration(true);
184 
185 		// Serializer that will do the job
186 		StringWriter writer = new StringWriter();
187 		XMLSerializer serializer = new XMLSerializer(writer, format);
188 
189 		try {
190 			serializer.asDOMSerializer();
191 			serializer.serialize(element);
192 		} catch (IOException ie) {
193 			// Should actually never hit this, but still...
194 			throw new InitializationException ("Could not serialize element.",
195 					ie);
196 		}
197 		
198 		return writer.toString();
199 	}
200 	
201 	/**
202 	 * Extracts the class name of the <code>Verfier</code> or the <job> from
203 	 * the XML serialized format of it. It uses the XPath
204 	 * <code>//(verifier | job)/class</code> to look for the Class name.
205 	 * 
206 	 * @param serializedVerifier
207 	 *            XML Document representing the serialized <code>Verifier</code>.
208 	 * @return The class name of the <code>Verifier</code> or <code>Job</code>
209 	 *         if present.
210 	 * @throws InitializationException
211 	 *             If the class name is not present or cannot be read.
212 	 */
213 	public static String getSerializedObjectClassName (
214 			Document serializedVerifier)
215 			throws InitializationException {
216 
217 		// Get the 'class' element.
218 		// <verifier> or <job>
219 		Element docElement = serializedVerifier.getDocumentElement ();
220 		NodeList classElements = docElement.getElementsByTagName ("class");
221 
222 		// If class elements are not present, then the format is wrong.
223 		if (classElements.getLength () == 0) {
224 			throw new InitializationException (
225 					"Ill formatted verifier / job string: Verifier or Job " +
226 					"class name not found.");
227 		}
228 
229 		// Get only the first class, we are not interested in the rest.
230 		Element classElement = (Element) classElements.item (0);
231 		String className = SerializationXmlUtils.getTextValue (classElement);
232 
233 		if (null == className || className.trim ().length () == 0) {
234 			// Without a class name we cannot regenerate the verifier or job.
235 			throw new InitializationException (
236 					"Ill formatted verifier / job string: Verifier or Job " +
237 					"class name not found.");
238 		}
239 
240 		return className;
241 	}
242 
243 }