You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oodt.apache.org by ke...@apache.org on 2010/07/15 01:03:30 UTC
svn commit: r964249 [2/2] -
/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/SAXParser.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,321 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package org.apache.oodt.commons.util;
+
+import java.io.IOException;
+import java.util.*;
+import org.xml.sax.*;
+
+/** An XML Simple API for XML (SAX) parser.
+ *
+ * Objects of this class are SAX parsers.
+ *
+ * @author Kelly
+ */
+public class SAXParser {
+ /** Construct a SAX Parser.
+ */
+ SAXParser(javax.xml.parsers.SAXParser parser) {
+ this.parser = parser;
+ }
+
+ /** Returns a list of features that this parser recognizes.
+ *
+ * This method will never return null; if no features are recognized, this
+ * method will return a zero length array.
+ *
+ * @return Recognized features.
+ */
+ public String[] getFeaturesRecognized() {
+ return EMPTY_STRING_ARRAY;
+ }
+
+ /**
+ * Returns a list of properties that this parser recognizes.
+ * This method will never return null; if no properties are
+ * recognized, this method will return a zero length array.
+ *
+ * @return Recognized properties.
+ */
+ public String[] getPropertiesRecognized() {
+ return EMPTY_STRING_ARRAY;
+ }
+
+ /** Resets the parser. */
+ public void reset() {}
+
+
+ /**
+ * Set the state of any feature in a SAX2 parser. The parser
+ * might not recognize the feature, and if it does recognize
+ * it, it might not be able to fulfill the request.
+ *
+ * @param featureId The unique identifier (URI) of the feature.
+ * @param state The requested state of the feature (true or false).
+ *
+ * @exception SAXNotRecognizedException If the requested feature is
+ * not known.
+ * @exception SAXNotSupportedException If the requested feature is
+ * known, but the requested state
+ * is not supported.
+ */
+ public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException {
+ throw new SAXNotSupportedException("This parser supports no features");
+ }
+
+ /**
+ * Query the current state of any feature in a SAX2 parser. The
+ * parser might not recognize the feature.
+ *
+ * @param featureId The unique identifier (URI) of the feature
+ * being set.
+ *
+ * @return The current state of the feature.
+ *
+ * @exception SAXNotRecognizedException If the requested feature is
+ * not known.
+ */
+ public boolean getFeature(String featureId) throws SAXNotRecognizedException, SAXNotSupportedException {
+ throw new SAXNotSupportedException("This parser supports no features");
+ }
+
+ /**
+ * Set the value of any property in a SAX2 parser. The parser
+ * might not recognize the property, and if it does recognize
+ * it, it might not support the requested value.
+ *
+ * @param propertyId The unique identifier (URI) of the property
+ * being set.
+ * @param value The value to which the property is being set.
+ *
+ * @exception SAXNotRecognizedException If the requested property is
+ * not known.
+ * @exception SAXNotSupportedException If the requested property is
+ * known, but the requested
+ * value is not supported.
+ */
+ public void setProperty(String propertyId, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
+ throw new SAXNotSupportedException("This parser supports no properties");
+ }
+
+ /**
+ * Return the current value of a property in a SAX2 parser.
+ * The parser might not recognize the property.
+ *
+ * @param propertyId The unique identifier (URI) of the property
+ * being set.
+ *
+ * @return The current value of the property.
+ *
+ * @exception SAXNotRecognizedException If the requested property is
+ * not known.
+ *
+ */
+ public Object getProperty(String propertyId) throws SAXNotRecognizedException, SAXNotSupportedException {
+ throw new SAXNotSupportedException("This parser supports no properties");
+ }
+
+ /**
+ * Returns true if the specified feature is recognized.
+ *
+ */
+ public boolean isFeatureRecognized(String featureId) {
+ return false;
+ }
+
+
+ /**
+ * Returns true if the specified property is recognized.
+ *
+ */
+ public boolean isPropertyRecognized(String propertyId) {
+ return false;
+ }
+
+ /**
+ * return the locator being used by the parser
+ *
+ * @return the parser's active locator
+ */
+ public final Locator getLocator() {
+ throw new IllegalStateException("This parser doesn't support locators");
+ }
+
+ /**
+ * Sets the resolver used to resolve external entities. The EntityResolver
+ * interface supports resolution of public and system identifiers.
+ *
+ * @param resolver The new entity resolver. Passing a null value will
+ * uninstall the currently installed resolver.
+ */
+ public void setEntityResolver(EntityResolver resolver) {
+ try {
+ parser.getXMLReader().setEntityResolver(resolver);
+ } catch (SAXException ignore) {}
+ }
+
+ /**
+ * Return the current entity resolver.
+ *
+ * @return The current entity resolver, or null if none
+ * has been registered.
+ * @see #setEntityResolver
+ */
+ public EntityResolver getEntityResolver() {
+ throw new IllegalStateException("This parser supports only setting of the entity resolver, not querying");
+ }
+
+ /**
+ * Sets the error handler.
+ *
+ * @param handler The new error handler.
+ */
+ public void setErrorHandler(ErrorHandler handler) {
+ try {
+ parser.getXMLReader().setErrorHandler(handler);
+ } catch (SAXException ignore) {}
+ }
+
+ /**
+ * Return the current error handler.
+ *
+ * @return The current error handler, or null if none
+ * has been registered.
+ * @see #setErrorHandler
+ */
+ public ErrorHandler getErrorHandler() {
+ throw new IllegalStateException("This parser supports only setting of the error handler, not querying");
+ }
+
+ /**
+ * Parses the specified input source.
+ *
+ * @param source The input source.
+ *
+ * @exception org.xml.sax.SAXException Throws exception on SAX error.
+ * @exception java.io.IOException Throws exception on i/o error.
+ */
+ public void parse(InputSource source) throws SAXException, IOException {
+ parser.getXMLReader().parse(source);
+ }
+
+ /**
+ * Parses the input source specified by the given system identifier.
+ * <p>
+ * This method is equivalent to the following:
+ * <pre>
+ * parse(new InputSource(systemId));
+ * </pre>
+ *
+ * @param systemID The input source.
+ *
+ * @exception org.xml.sax.SAXException Throws exception on SAX error.
+ * @exception java.io.IOException Throws exception on i/o error.
+ */
+ public void parse(String systemID) throws SAXException, IOException {
+ parser.getXMLReader().parse(systemID);
+ }
+
+
+ /**
+ * Set the locale to use for messages.
+ *
+ * @param locale The locale object to use for localization of messages.
+ *
+ * @exception SAXException An exception thrown if the parser does not
+ * support the specified locale.
+ */
+ public void setLocale(Locale locale) throws SAXException {
+ throw new IllegalStateException("This parser doesn't support localized error messages");
+ }
+
+ /**
+ * Allow an application to register a DTD event handler.
+ *
+ * <p>If the application does not register a DTD handler, all DTD
+ * events reported by the SAX parser will be silently ignored.</p>
+ *
+ * <p>Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.</p>
+ *
+ * @param handler The DTD handler.
+ * @exception java.lang.NullPointerException If the handler
+ * argument is null.
+ * @see #getDTDHandler
+ */
+ public void setDTDHandler(DTDHandler handler) {
+ try {
+ parser.getXMLReader().setDTDHandler(handler);
+ } catch (SAXException ignore) {}
+ }
+
+ /**
+ * Return the current DTD handler.
+ *
+ * @return The current DTD handler, or null if none
+ * has been registered.
+ * @see #setDTDHandler
+ */
+ public DTDHandler getDTDHandler() {
+ try {
+ return parser.getXMLReader().getDTDHandler();
+ } catch (SAXException ex) {
+ throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+ }
+ }
+
+ /**
+ * Allow an application to register a content event handler.
+ *
+ * <p>If the application does not register a content handler, all
+ * content events reported by the SAX parser will be silently
+ * ignored.</p>
+ *
+ * <p>Applications may register a new or different handler in the
+ * middle of a parse, and the SAX parser must begin using the new
+ * handler immediately.</p>
+ *
+ * @param handler The content handler.
+ * @exception java.lang.NullPointerException If the handler
+ * argument is null.
+ * @see #getContentHandler
+ */
+ public void setContentHandler(ContentHandler handler) {
+ try {
+ parser.getXMLReader().setContentHandler(handler);
+ } catch (SAXException ignore) {}
+ }
+
+ /**
+ * Return the current content handler.
+ *
+ * @return The current content handler, or null if none
+ * has been registered.
+ * @see #setContentHandler
+ */
+ public ContentHandler getContentHandler() {
+ try {
+ return parser.getXMLReader().getContentHandler();
+ } catch (SAXException ex) {
+ throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+ }
+
+ }
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private javax.xml.parsers.SAXParser parser;
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/ScreenLogger.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import org.apache.oodt.commons.io.*;
+
+/**
+ The <code>ScreenLogger</code> class is intended to be used with the
+ {@link Log} class in order to setup the System.err as a {@link LogListener}.
+
+ @author S. Hardman
+ @version $Revision: 1.1 $
+*/
+public class ScreenLogger extends WriterLogger {
+
+ /**
+ Constructor given no arguments.
+
+ This constructor will specify System.err as the output stream
+ and then call the other constructor with the output stream argument.
+ */
+ public ScreenLogger () {
+ this(System.err);
+ }
+
+
+ /**
+ Constructor given an output stream.
+
+ This constructor calls the {@link WriterLogger} constructor with the
+ same signature.
+
+ @param outputStream The output stream representing the log destination.
+ */
+ public ScreenLogger (OutputStream outputStream) {
+ super(outputStream);
+ }
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/Utility.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/Utility.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/Utility.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/Utility.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,211 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package org.apache.oodt.commons.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/** Miscellaneous utilities.
+ *
+ * This class contains various miscellaneous functions as static methods.
+ *
+ * @author Kelly
+ */
+public class Utility {
+ /** Load properties from a resource.
+ *
+ * This loads properties from the given resource (relative to the given class)
+ * into the given properties object. If any error occurs, this method prints a
+ * message to stderr but otherwise takes no special action.
+ *
+ * <p>You typically use this to merge properties for your application into the
+ * System properties by calling this method as follows:
+ * <pre>Utility.loadProperties(System.getProperties(), MyClass.class,
+ * "MyClass.properties");</pre> This adds the properties from the file
+ * <code>MyClass.properties</code> (which must exist in the same directory as the
+ * file <code>MyClass.class</code>, whether in the filesystem or in a jar) into
+ * the system properties. You can then fetch these properties from anywhere in
+ * your program with <code>System.getProperty(String)</code>,
+ * <code>Integer.getInteger</code>, etc.
+ *
+ * <p>You can also use the method to load properties into a newly created
+ * properties object that you provide. This keeps your properties separate, but
+ * then you have to pass a properties object all over the place, and you can't
+ * take advantage of non-String properties through methods like
+ * <code>Long#getLong(String)</code>, etc.
+ *
+ * @param props The properties object to load.
+ * @param clazz The class used to locate the resource.
+ * @param resourceName The name of the resource.
+ */
+ public static void loadProperties(Properties props, final Class clazz, final String resourceName) {
+ BufferedInputStream in = null;
+ try {
+ in = new BufferedInputStream(clazz.getResourceAsStream(resourceName));
+ props.load(in);
+ } catch (IOException ex) {
+ System.err.println("I/O exception while loading \"" + resourceName + "\": " + ex.getMessage());
+ } finally {
+ if (in != null) try {
+ in.close();
+ } catch (IOException ignore) {}
+ }
+ }
+
+ /** Parse a list.
+ *
+ * This yields an iterator created from a list where commas (and optional leading
+ * and trailing whitespace) separate each element. Each element will occur only
+ * once in the iterator regardless of how many times it appeared in the string.
+ *
+ * @param list The list to parse.
+ * @return The iterator over unique elements in the <var>list</var>.
+ */
+ public static Iterator parseCommaList(final String list) {
+ if (list == null) return new Iterator() {
+ public boolean hasNext() {
+ return false;
+ }
+ public Object next() {
+ throw new java.util.NoSuchElementException("There weren't ANY elements in this iterator, ever");
+ }
+ public void remove() {
+ throw new UnsupportedOperationException("Can't remove elements from this iterator");
+ }
+ };
+ HashSet set = new HashSet();
+ StringTokenizer tokens = new StringTokenizer(list, ",");
+ while (tokens.hasMoreTokens())
+ set.add(tokens.nextToken().trim());
+ return set.iterator();
+ }
+
+ /** Asynchronously redirect an input stream onto an output stream.
+ *
+ * The output stream is never closed.
+ *
+ * @param in Input stream to redirect.
+ * @param out Where to redirect <var>in</var>.
+ */
+ public static void redirect(final InputStream in, final OutputStream out) {
+ new Thread() {
+ public void run() {
+ try {
+ byte[] buf = new byte[1024];
+ for (;;) {
+ int numRead = in.read(buf);
+ if (numRead == -1) {
+ in.close();
+ break;
+ }
+ out.write(buf, 0, numRead);
+ }
+ } catch (IOException ex) {
+ try {
+ in.close();
+ } catch (IOException ignore) {}
+ }
+ }
+ }.start();
+ }
+
+ /** Log statistics on memory to stderr.
+ *
+ * @param msg Text to include in log.
+ */
+ public static void logMemoryStats(String msg) {
+ Runtime rt = Runtime.getRuntime();
+ System.err.println(msg + ": total=" + (rt.totalMemory() / 1024) + "KB, free=" + (rt.freeMemory() / 1024) + "KB");
+ }
+
+ /** Check string s is numeric. Numeric strings include 5.7, -3.9, 14.981E16, etc.
+ *
+ * @param s Text to be checked.
+ * @return True is <var>s</var> is a numeric string.
+ */
+ public static boolean isNumeric(String s) {
+ try {
+ Double.parseDouble(s);
+ } catch (NumberFormatException ex) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Delete a file or directory. If <var>file</var> references a directory, it
+ * recursively deletes all the directory tree.
+ *
+ * @param file File, directory, or other filesystem artifact to delete.
+ * @return True if <var>file</var> was deleted, false otherwise.
+ */
+ public static boolean delete(File file) {
+ if (file.isDirectory()) {
+ File[] entries = file.listFiles();
+ for (int i = 0; i < entries.length; ++i)
+ if (!delete(entries[i]))
+ return false;
+ }
+ return file.delete();
+ }
+
+ /**
+ * This method will escape any single quotes found in the input string
+ * and return the escaped string. This will ready the string for
+ * insertion into a database. The single quote is escaped by inserting
+ * an additional single quote in front of it in the string. If some
+ * considerate developer has already escaped the single quotes in the
+ * input string, this method will essentially do nothing.
+ *
+ * @param inputString The string to be escaped.
+ * @return The escaped string.
+ */
+ public static String escapeSingleQuote(String inputString) {
+
+ int index = inputString.indexOf('\'');
+ if (index == -1) {
+ return (inputString);
+ }
+
+ String outputString = inputString;
+ while (index != -1) {
+
+ // If the single quote is the last character in the string or
+ // the next character is not another single quote, insert a
+ // single quote in front of the current single quote.
+ if ((index == (outputString.length() - 1)) || (outputString.charAt(index + 1) != '\'')) {
+ outputString = outputString.substring(0, index) + "'" + outputString.substring(index);
+ }
+
+ // If we are not at the end of the string, check for another
+ // single quote.
+ if ((index + 2) <= (outputString.length() - 1)) {
+ index = outputString.indexOf('\'', index + 2);
+ }
+ else {
+ index = -1;
+ }
+ }
+ return (outputString);
+ }
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XML.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XML.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XML.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XML.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,651 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+// Portions of this code come from the Apache XML Project's Xerces 1.0.3 XML Parser
+// (specifically, the functions escape and getEntityRef). Apache license applies:
+//
+// The Apache Software License, Version 1.1
+//
+// Copyright (c) 1999 The Apache Software Foundation. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other materials
+// provided with the distribution.
+//
+// 3. The end-user documentation included with the redistribution, if any, must include
+// the following acknowledgment:
+//
+// "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)."
+//
+// Alternately, this acknowledgment may appear in the software itself,
+// if and wherever such third-party acknowledgments normally appear.
+//
+// 4. The names "Xerces" and "Apache Software Foundation" must not be used to endorse or
+// promote products derived from this software without prior written permission. For
+// written permission, please contact apache@apache.org.
+//
+// 5. Products derived from this software may not be called "Apache", nor may "Apache"
+// appear in their name, without prior written permission of the Apache Software
+// Foundation.
+//
+// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
+// BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+// ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id: XML.java,v 1.2 2005-05-01 22:49:55 cmattmann Exp $
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.OutputKeys;
+
+/** XML services.
+ *
+ * This class provides several XML convenience services and encapsulates the underlying
+ * XML implementation, allowing it to vary without impacting developers.
+ *
+ * @author Kelly
+ */
+public class XML {
+ private static DocumentBuilder getStandardDocumentBuilder() {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setCoalescing(false);
+ factory.setExpandEntityReferences(false);
+ factory.setIgnoringComments(false);
+ factory.setIgnoringElementContentWhitespace(true);
+ factory.setNamespaceAware(true);
+ factory.setValidating(true);
+ return factory.newDocumentBuilder();
+ } catch (ParserConfigurationException ex) {
+ throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+ }
+ }
+
+ /** Get the DOM implementation.
+ *
+ * @return The DOM implementation.
+ */
+ public static DOMImplementation getDOMImplementation() {
+ return getStandardDocumentBuilder().getDOMImplementation();
+ }
+
+ /** Create a DOM document.
+ *
+ * @return A new DOM document.
+ */
+ public static Document createDocument() {
+ return getStandardDocumentBuilder().newDocument();
+ }
+
+ /** Create a DOM parser.
+ *
+ * This method creates a new DOM parser that has validation turned on and
+ * ignorable whitespace not included, and has a default error handler that prints
+ * error messages and warnings to the standard error stream.
+ *
+ * @return A new DOM parser.
+ */
+ public static DOMParser createDOMParser() {
+ DocumentBuilder builder = getStandardDocumentBuilder();
+ builder.setEntityResolver(ENTERPRISE_ENTITY_RESOLVER);
+ builder.setErrorHandler(new ErrorHandler() {
+ public void error(SAXParseException ex) {
+ System.err.println("Parse error: " + ex.getMessage());
+ ex.printStackTrace();
+ }
+ public void warning(SAXParseException ex) {
+ System.err.println("Parse warning: " + ex.getMessage());
+ }
+ public void fatalError(SAXParseException ex) {
+ System.err.println("Fatal parse error: " + ex.getMessage());
+ ex.printStackTrace();
+ }
+ });
+ return new DOMParser(builder);
+ }
+
+ /** Create a SAX parser.
+ *
+ * This method creates a new, default SAX parser. It's set up with a default
+ * error handler that just prints messages to the standard error stream.
+ *
+ * @return A new SAX parser.
+ */
+ public static SAXParser createSAXParser() {
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(false);
+ factory.setValidating(false);
+ javax.xml.parsers.SAXParser saxParser = factory.newSAXParser();
+ saxParser.getXMLReader().setEntityResolver(ENTERPRISE_ENTITY_RESOLVER);
+ saxParser.getXMLReader().setErrorHandler(new ErrorHandler() {
+ public void error(SAXParseException ex) {
+ System.err.println("Parse error: " + ex.getMessage());
+ }
+ public void warning(SAXParseException ex) {
+ System.err.println("Parse warning: " + ex.getMessage());
+ }
+ public void fatalError(SAXParseException ex) {
+ System.err.println("Fatal parse error: " + ex.getMessage());
+ }
+ });
+ SAXParser p = new SAXParser(saxParser);
+ return p;
+ } catch (ParserConfigurationException ex) {
+ throw new IllegalStateException("Unexpected ParserConfigurationException: " + ex.getMessage());
+ } catch (SAXException ex) {
+ throw new IllegalStateException("Unexpected SAXException: " + ex.getMessage());
+ }
+ }
+
+ /** Serialize an XML DOM document into a String.
+ *
+ * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+ * XML parlance) it into a string.
+ *
+ * @param doc The document.
+ * @param omitXMLDeclaration True if we should omit the XML declaration, false to keep the XML declaration.
+ * @return The pretty-serialized, stringified, document.
+ */
+ public static String serialize(Document doc, boolean omitXMLDeclaration) {
+ StringWriter writer = new StringWriter();
+ try {
+ serialize(doc, writer, omitXMLDeclaration);
+ } catch (IOException cantHappen) {}
+ return writer.getBuffer().toString();
+ }
+
+ /** Serialize an XML DOM document into a String.
+ *
+ * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+ * XML parlance) it into a string.
+ *
+ * @param doc The document.
+ * @return The pretty-serialized, stringified, document.
+ */
+ public static String serialize(Document doc) {
+ return serialize(doc, /*omitXMLDeclaration*/false);
+ }
+
+ /** Serialize an XML DOM document into a writer.
+ *
+ * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+ * XML parlance) it into a writer.
+ *
+ * @param doc The document.
+ * @param writer Where to write it.
+ * @param omitXMLDeclaration True if we should omit the XML declaration, false to keep the XML declaration.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static void serialize(Document doc, Writer writer, boolean omitXMLDeclaration) throws IOException {
+ try {
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+
+ //update 05/01/2005
+ //author: Chris Mattmann
+ //set properties to pretty print
+ //and also to include the DOCTYPE when serializing the XML
+
+ //only set this if it's not null else we get a nice NullPointerException
+ if(doc.getDoctype().getPublicId() != null){
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, doc.getDoctype().getPublicId());
+ }
+
+ //only set this if it's not null else we get a nice NullPointerException
+ if(doc.getDoctype().getSystemId() != null){
+ transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
+ }
+
+ transformer.setOutputProperty(OutputKeys.INDENT,"yes");
+
+ DOMSource source = new DOMSource(doc);
+ StreamResult result = new StreamResult(writer);
+ transformer.transform(source, result);
+ } catch (TransformerConfigurationException ex) {
+ throw new IllegalStateException("Unexpected TransformerConfigurationException: " + ex.getMessage());
+ } catch (TransformerException ex) {
+ throw new IllegalStateException("Unexpected TransformerException: " + ex.getMessage());
+ }
+ }
+
+ /** Serialize an XML DOM document into a writer.
+ *
+ * This method takes a DOM document and pretty-prints (or pretty-serializes, in
+ * XML parlance) it into a writer.
+ *
+ * @param doc The document.
+ * @param writer Where to write it.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static void serialize(Document doc, Writer writer) throws IOException {
+ serialize(doc, writer, /*omitXMLDeclaration*/false);
+ }
+
+ /** Parse the given XML document into a DOM tree.
+ *
+ * @param inputSource The XML document to parse.
+ * @return A DOM tree for the given XML document.
+ * @throws SAXException If a parse error occurs.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static Document parse(InputSource inputSource) throws SAXException, IOException {
+ DOMParser parser = XML.createDOMParser();
+ parser.parse(inputSource);
+ return parser.getDocument();
+ }
+
+ /** Parse the given XML document into a DOM tree.
+ *
+ * @param string The XML document to parse.
+ * @return A DOM tree for the given XML document.
+ * @throws SAXException If a parse error occurs.
+ */
+ public static Document parse(String string) throws SAXException {
+ Document doc = null;
+ try {
+ DOMParser parser = XML.createDOMParser();
+ StringReader reader = new StringReader(string);
+ InputSource inputSource = new InputSource(reader);
+ doc = parse(inputSource);
+ reader.close();
+ } catch (IOException cantHappen) {
+ cantHappen.printStackTrace();
+ throw new RuntimeException("I/O exception " + cantHappen.getClass().getName()
+ + " can NOT have happened, yet it did! Message: " + cantHappen.getMessage());
+ }
+ return doc;
+ }
+
+ /** Parse the given XML document into a DOM tree.
+ *
+ * @param reader The XML document to parse.
+ * @return A DOM tree for the given XML document.
+ * @throws SAXException If a parse error occurs.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static Document parse(Reader reader) throws SAXException, IOException {
+ return parse(new InputSource(reader));
+ }
+
+ /** Parse the given XML document into a DOM tree.
+ *
+ * @param inputStream The XML document to parse.
+ * @return A DOM tree for the given XML document.
+ * @throws SAXException If a parse error occurs.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static Document parse(InputStream inputStream) throws SAXException, IOException {
+ return parse(new InputStreamReader(inputStream));
+ }
+
+ /** Add a repeating child element with text from the given collection to the given node.
+ *
+ * For example, if <var>values</var> is a {@link java.util.List} with strings items
+ * "a", "b", and "c", and <var>name</var> is "value", then the XML document will
+ * have
+ * <pre><value>a</value>
+ * <value>b</value>
+ * <value>c</value></pre>
+ * appended to <var>node</var>.
+ *
+ * @param node Node to which to add child elements.
+ * @param name Name to give each child element.
+ * @param values Collection of values to assign to each child element, in iterator order.
+ * @throws DOMException If a DOM error occurs.
+ */
+ public static void add(Node node, String name, Collection values) throws DOMException {
+ for (Iterator i = values.iterator(); i.hasNext();)
+ add(node, name, i.next());
+ }
+
+ /** Add a child element with the given text to the given element.
+ *
+ * This method modifies your DOM tree so that
+ * <pre><node>
+ * ...
+ * </node></pre>
+ * becomes
+ * <pre><node>
+ * ...
+ * <name>text>/name>
+ * </node></pre>
+ *
+ * Adding a null <var>name</var> does nothing. Adding null <var>text</var>
+ * won't add the element.
+ *
+ * @param node Node to which to add a child element.
+ * @param name Name of the child element to add to <var>node</var>.
+ * @param text What text the text-node child the child element named <var>name</var> should have. If null,
+ * nothing happens.
+ * @throws DOMException If a DOM error occurs.
+ */
+ public static void addNonNull(Node node, String name, String text) throws DOMException {
+ if (text == null) return;
+ add(node, name, text);
+ }
+
+ /** Add a child element with the given text to the given element.
+ *
+ * This method modifies your DOM tree so that
+ * <pre><node>
+ * ...
+ * </node></pre>
+ * becomes
+ * <pre><node>
+ * ...
+ * <name>text>/name>
+ * </node></pre>
+ *
+ * Adding a null <var>name</var> does nothing. Adding null <var>text</var>
+ * results in an empty <var>name</var> tag.
+ *
+ * @param node Node to which to add a child element.
+ * @param name Name of the child element to add to <var>node</var>.
+ * @param text What text the text-node child the child element named <var>name</var> should have.
+ * @throws DOMException If a DOM error occurs.
+ */
+ public static void add(Node node, String name, String text) throws DOMException {
+ if (name == null) return;
+ if (node == null) throw new IllegalArgumentException("Can't add to a null node");
+ Document doc = node.getOwnerDocument();
+ Element element = doc.createElement(name);
+ if (text != null) element.appendChild(doc.createTextNode(text));
+ node.appendChild(element);
+ }
+
+ /** Add a child element with the string representation of the given
+ * <var>object</var> to the given <var>node</var>.
+ *
+ * This method modifies your DOM tree so that
+ * <pre><node>
+ * ...
+ * </node></pre>
+ * becomes
+ * <pre><node>
+ * ...
+ * <name>string-rep>/name>
+ * </node></pre>
+ *
+ * Adding a null <var>name</var> does nothing. Adding null <var>object</var>
+ * results in an empty <var>name</var> tag.
+ *
+ * @param node Node to which to add a child element.
+ * @param name Name of the child element to add to <var>node</var>.
+ * @param object The string representation of the object to have as the text-node
+ * child the child element named <var>name</var>.
+ * @throws DOMException If a DOM error occurs.
+ */
+ public static void add(Node node, String name, Object object) throws DOMException {
+ add(node, name, object == null? null : object.toString());
+ }
+
+ /** Get unwrapped text from the given DOM node
+ *
+ * This method unwraps any wrapped text. For example, if the document contains
+ * <pre><node>Hello, world. This is
+ * my first document.
+ * </node></pre>
+ * then the node's unwrapped text is
+ * <pre>Hello, world. This is my first document.</pre>
+ * while the {@link #text} method would return the wrapped value
+ * <pre>Hello, world. This is
+ * my first document.</pre>
+ *
+ * <p>In other words, it collects the text nodes under the given node and replaces
+ * strings of newlines and spaces with a single space. Unwrapping a null node
+ * returns a null string.
+ *
+ * @param node The node.
+ * @return The text in its children, unwrapped.
+ */
+ public static String unwrappedText(Node node) {
+ if (node == null) return null;
+ StringBuffer buffer = new StringBuffer();
+ StringBuffer wrapped = new StringBuffer(text1(node, buffer));
+ boolean newline = false;
+ for (int i = 0; i < wrapped.length(); ++i) {
+ if (newline == false) {
+ if (wrapped.charAt(i) == '\n') {
+ newline = true;
+ wrapped.setCharAt(i, ' ');
+ }
+ } else {
+ if (Character.isWhitespace(wrapped.charAt(i))) {
+ wrapped.deleteCharAt(i);
+ --i;
+ } else
+ newline = false;
+ }
+ }
+ return wrapped.toString().trim();
+ }
+
+ /** Get the text from the given DOM node.
+ *
+ * Getting text from a null node gives you a null string.
+ *
+ * @param node The node.
+ * @return The text in its children.
+ */
+ public static String text(Node node) {
+ // [ return text(node) ]
+ StringBuffer buffer = new StringBuffer();
+ return text1(node, buffer);
+ }
+
+ /** Dump the structure of the DOM tree rooted at the given node to the given writer.
+ *
+ * This outputs the tree structure including the type of each node, its name, and
+ * its value. Note that for many nodes, the name isn't useful (the name of text
+ * nodes, for example, is <code>#text</code>), and for many nodes, the value is
+ * null.
+ *
+ * @param writer The writer to which write the tree structure.
+ * @param node The tree to output.
+ */
+ public static void dump(PrintWriter writer, Node node) {
+ dump(writer, node, 0);
+ }
+
+ /** Remove all comments from the given document node's subtree.
+ *
+ * @param node Node from which to search for comments to nuke.
+ */
+ public static void removeComments(Node node) {
+ List commentNodes = new ArrayList();
+ findCommentNodes(commentNodes, node);
+ for (Iterator i = commentNodes.iterator(); i.hasNext();) {
+ Node commentNode = (Node) i.next();
+ commentNode.getParentNode().removeChild(commentNode);
+ }
+ }
+
+ /** The resolver for entities for the JPL enterprise. */
+ public static final EntityResolver ENTERPRISE_ENTITY_RESOLVER = new EnterpriseEntityResolver();
+
+ /** An empty XML DOM document. This is handy for some basic operations, and for
+ * fetching the DOM implementation.
+ */
+ public static final Document EMPTY_DOCUMENT = org.apache.oodt.commons.util.XML.createDocument();
+
+ /** Identifies the last printable character in the Unicode range that is supported
+ * by the encoding used with this serializer. For 8-bit encodings this will be either
+ * 0x7E or 0xFF. For 16-bit encodings this will be 0xFFFF. Characters that are not
+ * printable will be escaped using character references.
+ *
+ * <p>Taken from Xerces 1.0.3. Apache license applies; see source code for
+ * license.
+ *
+ */
+ private static int LAST_PRINTABLE = 0x7E;
+
+ /** Escapes a string so it may be printed as text content or attribute value. Non
+ * printable characters are escaped using character references. Where the format
+ * specifies a deault entity reference, that reference is used
+ * (e.g. <code>&lt;</code>).
+ *
+ * <p>Taken from Xerces 1.0.3. Apache license applies; see source code for
+ * license.
+ *
+ * @param source The string to escape
+ * @return The escaped string
+ */
+ public static String escape(String source) {
+ StringBuffer result;
+ int i;
+ char ch;
+ String charRef;
+
+ result = new StringBuffer(source.length());
+ for (i = 0; i < source.length(); ++i) {
+ ch = source.charAt(i);
+ // If the character is not printable, print as character
+ // reference. Non printables are below ASCII space but not tab or
+ // line terminator, ASCII delete, or above a certain Unicode
+ // threshold.
+ if ((ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r') || ch > LAST_PRINTABLE || ch == 0xF7)
+ result.append("&#").append(Integer.toString(ch)).append(';');
+ else {
+ // If there is a suitable entity reference for this
+ // character, print it. The list of available entity
+ // references is almost but not identical between XML and
+ // HTML.
+ charRef = getEntityRef(ch);
+ if (charRef == null) result.append(ch);
+ else result.append('&').append(charRef).append(';');
+ }
+ }
+ return result.toString();
+ }
+
+ /** Find all comment nodes under the given node and add them to the given list.
+ *
+ * @param list List to add to.
+ * @param node Node to search.
+ */
+ private static void findCommentNodes(List list, Node node) {
+ if (node.getNodeType() == Node.COMMENT_NODE)
+ list.add(node);
+ else {
+ NodeList children = node.getChildNodes();
+ for (int i = 0; i < children.getLength(); ++i) {
+ findCommentNodes(list, children.item(i));
+ }
+ }
+ }
+
+ /** Get the entity reference for the given character.
+ *
+ * Taken from Xerces 1.0.3; see source code for license.
+ */
+ private static String getEntityRef(char ch) {
+ // Encode special XML characters into the equivalent character references.
+ // These five are defined by default for all XML documents.
+ switch (ch) {
+ case '<': return "lt";
+ case '>': return "gt";
+ case '"': return "quot";
+ case '\'': return "apos";
+ case '&': return "amp";
+ }
+ return null;
+ }
+
+ /** Get the text from the child node using the given buffer.
+ *
+ * @param node The node.
+ * @param buffer The buffer to use.
+ * @return The text.
+ */
+ private static String text1(Node node, StringBuffer buffer) {
+ for (Node ch = node.getFirstChild(); ch != null; ch = ch.getNextSibling()) {
+ if (ch.getNodeType() == Node.ELEMENT_NODE || ch.getNodeType() == Node.ENTITY_REFERENCE_NODE)
+ buffer.append(text(ch));
+ else if (ch.getNodeType() == Node.TEXT_NODE)
+ buffer.append(ch.getNodeValue());
+ }
+ return buffer.toString();
+ }
+
+ /** Dump the structure of the DOM tree rooted at the given node to the given writer,
+ * indenting the contents.
+ *
+ * @param indentAmt The number of spaces to indent the output of this node;
+ * children are indented two more than this amount.
+ * @param writer The writer to which write the tree structure.
+ * @param node The tree to output.
+ */
+ private static void dump(PrintWriter writer, Node node, int indentAmt) {
+ for (int i = 0; i < indentAmt; ++i)
+ writer.print(' ');
+ writer.println(typeOf(node) + "(" + node.getNodeName() + ", " + node.getNodeValue() + ")");
+ NodeList children = node.getChildNodes();
+ for (int i = 0; i < children.getLength(); ++i)
+ dump(writer, children.item(i), indentAmt + 2);
+ }
+
+ /** Return a human-readable representation of the type of the given node.
+ *
+ * For example, an attribute node returns <code>Attribute</code>, while an element
+ * node returns <code>Element</code>.
+ *
+ * @param node The node.
+ * @return The name of the node's type.
+ */
+ private static String typeOf(Node node) {
+ switch (node.getNodeType()) {
+ case Node.ATTRIBUTE_NODE: return "Attribute";
+ case Node.CDATA_SECTION_NODE: return "CDATA-Section";
+ case Node.COMMENT_NODE: return "Comment";
+ case Node.DOCUMENT_FRAGMENT_NODE: return "Document-Fragment";
+ case Node.DOCUMENT_NODE: return "Document";
+ case Node.DOCUMENT_TYPE_NODE: return "Document-Type";
+ case Node.ELEMENT_NODE: return "Element";
+ case Node.ENTITY_NODE: return "Entity";
+ case Node.ENTITY_REFERENCE_NODE: return "Entity-Ref";
+ case Node.NOTATION_NODE: return "Notation";
+ case Node.PROCESSING_INSTRUCTION_NODE: return "Proc-Instr";
+ case Node.TEXT_NODE: return "Text";
+ default: return "Unknown!";
+ }
+ }
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPC.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,220 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** XML-RPC utilities.
+ *
+ * This class provides several XML-RPC utilities.
+ *
+ * @author Kelly
+ */
+public class XMLRPC {
+ /** Build an XML-RPC method call.
+ *
+ * This may throw {@link IllegalArgumentException} if the <var>params</var>
+ * contains an object that's incompatible with XML-RPC.
+ *
+ * @param name Name of the method to call.
+ * @param params Parameters to pass to the call.
+ * @return An XML string encapsulationg the call.
+ * @throws DOMException If we can't construct the call.
+ */
+ public static byte[] createMethodCall(String name, Collection params) throws DOMException {
+ Document doc = XML.createDocument();
+ Element methodCallElement = doc.createElement("methodCall");
+ doc.appendChild(methodCallElement);
+ XML.add(methodCallElement, "methodName", name);
+ if (params != null && !params.isEmpty()) {
+ Element paramsElement = doc.createElement("params");
+ methodCallElement.appendChild(paramsElement);
+ for (Iterator i = params.iterator(); i.hasNext();)
+ paramsElement.appendChild(createValueElement(doc, i.next()));
+ }
+ return XML.serialize(doc).getBytes();
+ }
+
+ /** Create a <value> element for an XML-RPC method.
+ *
+ * This may throw {@link IllegalArgumentException} if the <var>value</var> is
+ * incompatible with XML-RPC.
+ *
+ * @param doc Owning document.
+ * @param value The value.
+ * @throws DOMException If we can't construct the <value>.
+ */
+ private static Element createValueElement(Document doc, Object value) throws DOMException {
+ if (value == null)
+ throw new IllegalArgumentException("Nulls not supported in XML-RPC");
+ Element valueElement = doc.createElement("value");
+ if (value instanceof Integer || value instanceof Short) {
+ XML.add(valueElement, "int", value.toString());
+ } else if (value instanceof Boolean) {
+ XML.add(valueElement, "boolean", ((Boolean) value).booleanValue()? "1" : "0");
+ } else if (value instanceof String) {
+ Element stringElement = doc.createElement("string");
+ valueElement.appendChild(stringElement);
+ stringElement.appendChild(doc.createCDATASection(value.toString()));
+ } else if (value instanceof Float || value instanceof Double) {
+ XML.add(valueElement, "double", value.toString());
+ } else if (value instanceof Date) {
+ XML.add(valueElement, "dateTime.iso8601", ISO8601_FORMAT.format((Date) value));
+ } else if (value instanceof byte[]) {
+ Element base64Element = doc.createElement("base64");
+ valueElement.appendChild(base64Element);
+ base64Element.appendChild(doc.createCDATASection(new String(Base64.encode((byte[])value))));
+ } else if (value instanceof Map) {
+ Element structElement = doc.createElement("struct");
+ valueElement.appendChild(structElement);
+ Map map = (Map) value;
+ for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
+ Element memberElement = doc.createElement("member");
+ valueElement.appendChild(memberElement);
+ Map.Entry entry = (Map.Entry) i.next();
+ if (!(entry.getKey() instanceof String))
+ throw new IllegalArgumentException("Keys in maps for XML-RPC structs must be Strings");
+ XML.add(memberElement, "name", entry.getKey().toString());
+ memberElement.appendChild(createValueElement(doc, entry.getValue()));
+ }
+ } else if (value instanceof Collection) {
+ Element arrayElement = doc.createElement("array");
+ valueElement.appendChild(arrayElement);
+ Element dataElement = doc.createElement("data");
+ arrayElement.appendChild(dataElement);
+ Collection collection = (Collection) value;
+ for (Iterator i = collection.iterator(); i.hasNext();)
+ dataElement.appendChild(createValueElement(doc, i.next()));
+ } else throw new IllegalArgumentException(value.getClass().getName() + " not supported in XML-RPC");
+ return valueElement;
+ }
+
+ /** Parse an XML-RPC method response.
+ *
+ * @param response The response data.
+ * @return The value contained in the <var>response</var>.
+ * @throws XMLRPCFault If the <var>response</var> contained a fault.
+ */
+ public static Object parseResponse(byte[] response) throws XMLRPCFault {
+ try {
+ DOMParser parser = XML.createDOMParser();
+ parser.setFeature("http://xml.org/sax/features/validation", false);
+ parser.parse(new InputSource(new ByteArrayInputStream(response)));
+ Document doc = parser.getDocument();
+ doc.normalize();
+ XML.removeComments(doc);
+ Element methodResponseElement = doc.getDocumentElement();
+ if (!"methodResponse".equals(methodResponseElement.getNodeName()))
+ throw new SAXException("Not a <methodResponse> document");
+ Node child = methodResponseElement.getFirstChild();
+ if ("params".equals(child.getNodeName())) {
+ return parseValue(child.getFirstChild().getFirstChild());
+ } else if ("fault".equals(child.getNodeName())) {
+ try {
+ Map map = (Map) parseValue(child.getFirstChild());
+ throw new XMLRPCFault(((Integer) map.get("faultCode")).intValue(),
+ (String) map.get("faultString"));
+ } catch (ClassCastException ex) {
+ throw new SAXException("XML-RPC <fault> invalid");
+ }
+ } else throw new SAXException("XML-RPC response does not contain <params> or <fault>");
+ } catch (SAXException ex) {
+ throw new IllegalArgumentException(ex.getMessage());
+ } catch (IOException ex) {
+ throw new RuntimeException("Unexpected I/O exception that shouldn't happen, but did: " + ex.getMessage());
+ }
+ }
+
+ /** Parse an XML-RPC <value>.
+ *
+ * @param node The <value> node.
+ * @return The Java value of <var>node</var>.
+ */
+ private static Object parseValue(Node node) {
+ String n = node.getNodeName();
+ if (!"value".equals(n)) throw new IllegalArgumentException("Expecting a <value>, not a <" + n + ">");
+ Node t = node.getFirstChild();
+ n = t.getNodeName();
+
+ // Default if there's no nested element is a String.
+ if (t.getNodeType() == Node.TEXT_NODE || t.getNodeType() == Node.CDATA_SECTION_NODE) {
+ return t.getNodeValue();
+ }
+
+ // Figure out what the type is from the nested element.
+ String txt = XML.unwrappedText(t);
+ if ("i4".equals(n) || "int".equals(n)) {
+ return new Integer(txt);
+ } else if ("boolean".equals(n)) {
+ if ("1".equals(txt)) return new Boolean(true);
+ else if ("0".equals(txt)) return new Boolean(false);
+ else throw new IllegalArgumentException(n + " does not contain a 0 or 1");
+ } else if ("string".equals(n)) {
+ return txt;
+ } else if ("double".equals(n)) {
+ return new Double(txt);
+ } else if ("dateTime.iso8601".equals(n)) {
+ try {
+ return ISO8601_FORMAT.parse(txt);
+ } catch (ParseException ex) {
+ throw new IllegalArgumentException(n + " does not contain an ISO8601 format date/time");
+ }
+ } else if ("base64".equals(n)) {
+ return Base64.decode(txt.getBytes());
+ } else if ("struct".equals(n)) {
+ Map m = new HashMap();
+ NodeList memberNodes = t.getChildNodes();
+ for (int i = 0; i < memberNodes.getLength(); ++i) {
+ Node memberNode = memberNodes.item(i);
+ if (!"member".equals(memberNode.getNodeName()))
+ throw new IllegalArgumentException(n + " contains <" + memberNode.getNodeName()
+ + ">, not <member>");
+ Node nameNode = memberNode.getFirstChild();
+ if (nameNode == null || !"name".equals(nameNode.getNodeName()))
+ throw new IllegalArgumentException("<member> missing <name> element");
+ Node valueNode = nameNode.getNextSibling();
+ if (valueNode == null || !"value".equals(valueNode.getNodeName()))
+ throw new IllegalArgumentException("<member> missing <value> element");
+ m.put(XML.unwrappedText(nameNode), parseValue(valueNode));
+ }
+ return m;
+ } else if ("array".equals(n)) {
+ Node dataNode = t.getFirstChild();
+ if (dataNode == null || !"data".equals(dataNode.getNodeName()))
+ throw new IllegalArgumentException("<array> missing <data> element");
+ NodeList children = dataNode.getChildNodes();
+ List x = new ArrayList(children.getLength());
+ for (int i = 0; i < children.getLength(); ++i)
+ x.add(parseValue(children.item(i)));
+ return x;
+ } else throw new IllegalArgumentException("Illegal type " + n + " in <value>");
+ }
+
+ /** Constructor that causes a runtime exception since this is a utility class.
+ */
+ private XMLRPC() {
+ throw new IllegalStateException("Do not construct XMLRPC objects");
+ }
+
+ /** ISO8601 date format for XML-RPC dates. */
+ private static DateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/XMLRPCFault.java Wed Jul 14 23:03:30 2010
@@ -0,0 +1,63 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE.txt file distributed with this work for
+// additional information regarding copyright ownership. The ASF licenses this
+// file to you under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+package org.apache.oodt.commons.util;
+
+import java.io.*;
+import java.util.*;
+import java.text.ParseException;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+
+/** XML-RPC fault.
+ *
+ * This exception is thrown when a fault is returned from an XML-RPC call.
+ *
+ * @author Kelly
+ */
+public class XMLRPCFault extends Exception {
+ /** Constructor.
+ *
+ * @param code Fault code.
+ * @param string Fault string.
+ */
+ public XMLRPCFault(int code, String string) {
+ super(code + ": " + string);
+ this.code = code;
+ this.string = string;
+ }
+
+ /** Get the fault code.
+ *
+ * @return The fault code.
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /** Get the fault string.
+ *
+ * @return The fault string.
+ */
+ public String getString() {
+ return string;
+ }
+
+ /** Fault code. */
+ private int code;
+
+ /** Fault string. */
+ private String string;
+}
Added: incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/package.html
URL: http://svn.apache.org/viewvc/incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/package.html?rev=964249&view=auto
==============================================================================
--- incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/package.html (added)
+++ incubator/oodt/trunk/commons/src/main/java/org/apache/oodt/commons/util/package.html Wed Jul 14 23:03:30 2010
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+ <head>
+ <title>Apache OODT Common Utilities
+ </title>
+ </head>
+ <body>
+ <p>Utility classes for Apache OODT.
+ </p>
+ </body>
+</html>