All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ws.jaxme.util.Configurator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2003, 2004  The Apache Software Foundation
 * 
 * Licensed 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.ws.jaxme.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.xml.namespace.QName;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/** 

The Configurator is an idea borrowed by the Ant project. * It is a SAX2 handler that reads a config file which is * represented by a hierarchy of Java beans. For example:

*
 *   <outerBean foo="true" bar="Quite right">
 *     <innerBean whatever="57">
 *     </innerBean
 *   </outerBean>
 * 
* The example would create an object outerBean and call its * methods setFoo(boolean) and * setBar(String) to process the attributes. * It would also create a bean innerBean by calling the * outerBeans method createInnerBean(). * Finally the innerBean is configured by calling * setWhatever(int).

* * @author Jochen Wiedmann * @version $Id: Configurator.java 232067 2005-03-10 11:14:08 +0100 (Thu, 10 Mar 2005) jochen $ */ public class Configurator implements ContentHandler, NamespaceResolver { private static final Class[] zeroClasses = new Class[0]; private static final Object[] zeroObjects = new Object[0]; private static final Class[] oneClassString = new Class[]{String.class}; private static final Class[] oneClassAttributes = new Class[]{Attributes.class}; private String[] namespaces; private List beans = new ArrayList(); private List names = new ArrayList(); private Object currentBean; private String currentName; private Locator locator; private Object beanFactory; private Object rootObject; private Object resultBean; private int ignoreLevel = 0; private NamespaceSupport nss = new NamespaceSupport(); boolean nssNeedsContext; /**

Sets the namespace handled by the configurator. Defaults * to no namespace. Shortcut for * setNamespace(new String[]{pNamespace}).

* * @param pNamespace The namespace being set */ public void setNamespace(String pNamespace) { setNamespaces(new String[]{pNamespace}); } /**

Sets the namespaces handled by the configurator. Defaults * to no namespace.

* * @param pNamespaces The namespaces being set */ public void setNamespaces(String[] pNamespaces) { namespaces = pNamespaces; } /**

Returns the namespaces handled by the configurator. Defaults * to no namespace.

*/ public String[] getNamespaces() { return namespaces; } /**

Sets the Locator being used in error messages.

*/ public void setDocumentLocator(Locator pLocator) { locator = pLocator; } /**

Returns the Locator being used in error messages.

*/ public Locator getDocumentLocator() { return locator; } /**

Sets the bean factory, creating the outermost element. * The bean factory must have a matching createElementName() * method, with ElementName being the element name * of the document element.

*/ public void setBeanFactory(Object pFactory) { beanFactory = pFactory; } /**

Returns the bean factory, creating the outermost element. * The bean factory must have a matching createElementName() * method, with ElementName being the element name * of the document element.

*/ public Object getBeanFactory() { return beanFactory == null ? this : beanFactory; } /**

An alternative to using the bean factory. This object * is used as the root object, regardless of its name.

*/ public void setRootObject(Object pRootObject) { rootObject = pRootObject; } /**

An alternative to using the bean factory. This object * is used as the root object, regardless of its name.

*/ public Object getRootObject() { return rootObject; } public void startDocument() throws SAXException { currentBean = null; currentName = null; beans.clear(); names.clear(); ignoreLevel = 0; nss.reset(); nssNeedsContext = true; } public void endDocument() throws SAXException {} public void startPrefixMapping(String pPrefix, String pURI) throws SAXException { nss.declarePrefix(pPrefix, pURI); } public void endPrefixMapping(String pPrefix) throws SAXException { nss.undeclarePrefix(pPrefix); } /**

Returns whether a namespace is matching the configured * namespace.

*/ protected boolean isNamespaceMatching(String pNamespace) { if (pNamespace == null) { pNamespace = ""; } String[] myNamespaces = getNamespaces(); if (myNamespaces == null || myNamespaces.length == 0) { return pNamespace.length() == 0; } else { for (int i = 0; i < myNamespaces.length; i++) { String s = myNamespaces[i]; if (s == null) { s = ""; } if (s.equals(pNamespace)) { return true; } } return false; } } /**

Given a prefix and a name, creates a method name matching * the prefix and the name.

*/ protected String getMethodNameFor(String pPrefix, String pName) { StringBuffer result = new StringBuffer(pPrefix); for (int i = 0; i < pName.length(); i++) { char c = pName.charAt(i); if (i == 0) { if (Character.isJavaIdentifierStart(c)) { result.append(Character.toUpperCase(c)); } else { result.append('_'); } } else { if (Character.isJavaIdentifierPart(c)) { result.append(c); } else { result.append('_'); } } } return result.toString(); } /**

Creates a new bean, matching the element name pLocalName. * If this is the outermost bean, calls the bean factorys * createBeanName() method, otherwise calls the current beans * createBeanName() method, with beanName * being the value of the pLocalName parameter.

*/ public void startElement(String pNamespaceURI, String pQName, String pLocalName, Attributes pAttr) throws SAXException { if (ignoreLevel > 0) { ++ignoreLevel; return; } if (!isNamespaceMatching(pNamespaceURI)) { if (currentBean == null) { String[] myNamespaces = getNamespaces(); if (myNamespaces == null || myNamespaces.length == 0) { throw new SAXParseException("The document element must have the default namespace.", getDocumentLocator()); } else { StringBuffer sb = new StringBuffer("The document element must have either of the namespaces: "); for (int i = 0; i < myNamespaces.length; i++) { if (i > 0) sb.append(","); String s = myNamespaces[i]; if (s == null) { s = ""; } sb.append('"').append(s).append('"'); } throw new SAXParseException(sb.toString(), getDocumentLocator()); } } ++ignoreLevel; return; // Namespace not matching, ignore this element } Object o; if (currentBean == null && rootObject != null) { o = rootObject; } else { o = null; Object factory = (currentBean == null) ? beanFactory : currentBean; String methodName = getMethodNameFor("create", pLocalName); try { o = invokeMethod(methodName, factory, oneClassAttributes, new Object[]{pAttr}); } catch (SAXParseException e) { if (e.getException() != null && e.getException() instanceof NoSuchMethodException) { try { o = invokeMethod(methodName, factory, zeroClasses, zeroObjects); e = null; } catch (SAXParseException f) { if (f.getException() != null && f.getException() instanceof NoSuchMethodException) { if (currentBean == null) { throw new SAXParseException("Invalid document element: " + pQName, getDocumentLocator()); } else { throw new SAXParseException("Invalid child element name: " + pQName, getDocumentLocator()); } } throw f; } } if (e != null) { throw e; } } if (o == null) { throw new SAXParseException("Method " + methodName + " of class " + factory.getClass().getName() + " did not return an object.", getDocumentLocator()); } } if (currentBean == null) { resultBean = o; } else { beans.add(currentBean); names.add(currentName); } currentBean = o; currentName = pQName; if (pAttr != null) { for (int i = 0; i < pAttr.getLength(); i++) { String uri = pAttr.getURI(i); if (uri == null || uri.length() == 0 || isNamespaceMatching(uri)) { String value = pAttr.getValue(i); String qName = pAttr.getQName(i); String setMethodName = getMethodNameFor("set", pAttr.getLocalName(i)); Method[] methods = currentBean.getClass().getMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; if (!setMethodName.equals(method.getName())) { continue; } Class[] argClasses = method.getParameterTypes(); if (argClasses.length != 1) { continue; } Object[] args = null; if (argClasses[0] == String.class) { args = new Object[]{value}; } else if (argClasses[0] == Integer.class || argClasses[0] == Integer.TYPE) { try { args = new Object[]{new Integer(value)}; } catch (Exception e) { throw new SAXParseException("Attribute " + qName + " contains an invalid Integer value: " + value, getDocumentLocator()); } } else if (argClasses[0] == Long.class || argClasses[0] == Long.TYPE) { try { args = new Object[]{new Long(value)}; } catch (Exception e) { throw new SAXParseException("Attribute " + qName + " contains an invalid Long value: " + value, getDocumentLocator()); } } else if (argClasses[0] == Short.class || argClasses[0] == Short.TYPE) { try { args = new Object[]{new Short(value)}; } catch (Exception e) { throw new SAXParseException("Attribute " + qName + " contains an invalid Short value: " + value, getDocumentLocator()); } } else if (argClasses[0] == Byte.class || argClasses[0] == Byte.TYPE) { try { args = new Object[]{new Byte(value)}; } catch (Exception e) { throw new SAXParseException("Attribute " + qName + " contains an invalid Byte value: " + value, getDocumentLocator()); } } else if (argClasses[0] == Boolean.class || argClasses[0] == Boolean.TYPE) { try { args = new Object[]{Boolean.valueOf(value)}; } catch (Exception e) { throw new SAXParseException("Attribute " + qName + " contains an invalid Boolean value: " + value, getDocumentLocator()); } } else if (argClasses[0] == Character.class || argClasses[0] == Character.TYPE) { if (value.length() != 1) { throw new SAXParseException("Attribute " + qName + " contains an invalid Character value: " + value, getDocumentLocator()); } args = new Object[]{new Character(value.charAt(0))}; } else if (argClasses[0] == Class.class) { Class c; try { c = ClassLoader.getClass(value); } catch (Exception e) { throw new SAXParseException("Failed to load class " + value, getDocumentLocator(), e); } args = new Object[]{c}; } else if (argClasses[0] == QName.class) { try { QName name = QName.valueOf(value); args = new Object[]{name}; } catch (Exception e) { throw new SAXParseException("Failed to parse QName " + value, getDocumentLocator()); } } else { // Try a constructor class(String) try { Constructor con = argClasses[0].getConstructor(oneClassString); args = new Object[]{con.newInstance(new Object[]{value})}; } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); throw new SAXParseException("Failed to invoke constructor of class " + argClasses[0].getClass().getName(), getDocumentLocator(), (t instanceof Exception) ? ((Exception) t) : e); } catch (NoSuchMethodException e) { throw new SAXParseException("Attribute " + qName + " has an invalid type: " + argClasses[0].getClass().getName(), getDocumentLocator()); } catch (IllegalAccessException e) { throw new SAXParseException("Illegal access to constructor of class " + argClasses[0].getClass().getName(), getDocumentLocator(), e); } catch (InstantiationException e) { throw new SAXParseException("Failed to instantiate class " + argClasses[0].getClass().getName(), getDocumentLocator(), e); } } try { method.invoke(currentBean, args); } catch (IllegalAccessException e) { throw new SAXParseException("Illegal access to method " + setMethodName + " of class " + currentBean.getClass().getName(), getDocumentLocator(), e); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); throw new SAXParseException("Failed to invoke method " + setMethodName + " of class " + currentBean.getClass().getName(), getDocumentLocator(), (t instanceof Exception) ? ((Exception) t) : e); } } } } } } protected Object invokeMethod(String pMethodName, Object pBean, Class[] pSignature, Object[] pArgs) throws SAXException { try { Method m = pBean.getClass().getMethod(pMethodName, pSignature); return m.invoke(pBean, pArgs); } catch (IllegalAccessException e) { throw new SAXParseException("Illegal access to method " + pMethodName + " of class " + pBean.getClass().getName(), getDocumentLocator(), e); } catch (NoSuchMethodException e) { throw new SAXParseException("No such method in class " + pBean.getClass().getName() + ": " + pMethodName, getDocumentLocator(), e); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); throw new SAXParseException("Failed to invoke method " + pMethodName + " of class " + pBean.getClass().getName(), getDocumentLocator(), (t instanceof Exception) ? ((Exception) t) : e); } } /**

Terminates parsing the current bean by calling its * finish() method, if any.

*/ public void endElement(String namespaceURI, String qName, String localName) throws SAXException { if (ignoreLevel > 0) { --ignoreLevel; return; } Object previousBean = currentBean; if (beans.size() > 0) { currentBean = beans.remove(beans.size()-1); currentName = names.remove(names.size()-1).toString(); } else { currentBean = null; currentName = null; } try { invokeMethod("finish", previousBean, zeroClasses, zeroObjects); } catch (SAXParseException e) { if (e.getException() == null || !(e.getException() instanceof NoSuchMethodException)) { throw e; } } } /**

Handles atomic child elements by invoking their method * addText(String pText). Note that it may happen, * that this method is invoked multiple times, if the parser * splits a piece of text into multiple SAX events.

*/ public void characters(char[] ch, int start, int length) throws SAXException { if (ignoreLevel > 0) { return; } String s = new String(ch, start, length); try { invokeMethod("addText", currentBean, oneClassString, new String[]{s}); } catch (SAXParseException e) { if (e.getException() != null && (e.getException() instanceof NoSuchMethodException)) { boolean allWhitespace = true; for (int i = 0; i < length; i++) { if (!Character.isWhitespace(ch[start+i])) { allWhitespace = false; break; } } if (allWhitespace) { // Ignore this } else { throw new SAXParseException("Element " + currentName + " doesn't support embedded text.", getDocumentLocator()); } } else { throw e; } } } public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { } public void processingInstruction(String target, String data) throws SAXException { } public void skippedEntity(String name) throws SAXException { } /** Returns the parsed result bean. */ public Object getResult() { return resultBean; } public boolean processName(String pName, String[] parts) { int offset = pName.indexOf(':'); if (offset == -1) { String uri = nss.getNamespaceURI(""); if (uri == null) { parts[0] = ""; } else { parts[0] = uri; } parts[1] = pName; parts[2] = pName; return true; } else { String uri = nss.getNamespaceURI(pName.substring(0, offset)); if (uri == null) { return false; } else { parts[0] = uri; parts[1] = pName.substring(offset+1); parts[2] = pName; return true; } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy