Hi Johen,
    I modified the following three classes and JaxME now supports JAXB objects in children classloaders while JaxME sits in a parent classloader.  Luckily, I did not have to write a custom classloader at all :).

Can you look this over and give me your thoughts?  Basically, the way I use JaxME now is like so
       
       //first few lines are JAXB compliant
        JAXBContext ctx = JAXBContext.newInstance("biz.xsoftware.impl.router.jaxme", getClass().getClassLoader());
        unmarshal = ctx.createUnmarshaller();

        Classloader cl = newBean.getClassLoader(); //get the new beans classloader
        //now we get into non-compliant stuff but there is not too much non-compliance....
        jaxmeCtx = (JAXBContextImpl)ctx;
        jaxmeCtx.registerPackages("biz.xsoftware.impl.new.dynamicly.deployedbeans", cl);

I can now dynamically now deploy new jars with JaxME objects into a VM.  I bet you are probably the only JAXB implementation that can do so too.  Castor can, but it is not JAXB compliant.....and of course, using this feature leaves you non-compliant, but heh, I think it is a cool feature :).  Let me know what you think.
thanks,
dean

/*
 * 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.impl;


import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.xml.bind.DatatypeConverter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.MarshalException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationException;
import javax.xml.bind.Validator;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.ws.jaxme.JMManager;
import org.apache.ws.jaxme.JMMarshaller;
import org.apache.ws.jaxme.JMUnmarshaller;
import org.apache.ws.jaxme.JMValidator;
import org.apache.ws.jaxme.PM;
import org.apache.ws.jaxme.PMException;
import org.apache.ws.jaxme.util.Configurator;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;


/** <p>JaxMe's implementation of a JAXBContext.</p>
 *
 * @author <a href="mailto:[EMAIL PROTECTED]">Jochen Wiedmann</a>
 * @version $Id: JAXBContextImpl.java,v 1.9 2005/03/10 10:14:03 jochen Exp $
 */
public class JAXBContextImpl extends JAXBContext {
    /** The namespace of JaxMe's configuration files.
     */
        public static final String CONFIGURATION_URI = 
"http://ws.apache.org/jaxme/namespaces/jaxme2/configuration";;
        private static final SAXParserFactory spf;
        private static final DatatypeConverterImpl datatypeConverter = new 
DatatypeConverterImpl();
        private ClassLoader cl;
        private String packageNames;
        private Map managersByQName = new HashMap();
        private Map managersByInterface = new HashMap();
        private Class jmMarshallerClass;
        private Class jmUnmarshallerClass;
        private Class jmValidatorClass;

        static {
                spf = SAXParserFactory.newInstance();
                spf.setValidating(false);
                spf.setNamespaceAware(true);
                DatatypeConverter.setDatatypeConverter(datatypeConverter);
        }

        protected JAXBContextImpl() {}

        /** <p>Sets the ClassLoader to use.</p>
         */
        protected void setClassLoader(ClassLoader pClassLoader) {
                cl = pClassLoader;
        }

        /** <p>Returns the ClassLoader to use.</p>
         */
        public ClassLoader getClassLoader() {
                return cl;
        }

        /** <p>Sets the package names managed by this context.</p>
         */
        protected void setPackageNames(String pPackageNames) {
                packageNames = pPackageNames;
        }

        /** <p>Returns the package names managed by this context.</p>
         */
        public String getPackageNames() {
                return packageNames;
        }

        /** <p>Sets the JMMarshaller class to use.</p>
         */
        protected void setJMMarshallerClass(Class pClass) {
                jmMarshallerClass = pClass;
        }

        /** <p>Returns the JMMarshaller class to use.</p>
         */
        public Class getJMMarshallerClass() {
                return jmMarshallerClass;
        }

        /** <p>Sets the JMUnmarshaller class to use.</p>
         */
        protected void setJMUnmarshallerClass(Class pClass) {
                jmUnmarshallerClass = pClass;
        }

        /** <p>Sets the JMUnmarshaller class to use.</p>
         */
        public Class getJMUnmarshallerClass() {
                return jmUnmarshallerClass;
        }

        /** <p>Sets the JMValidator class to use.</p>
         */
        protected void setJMValidatorClass(Class pClass) {
                jmValidatorClass = pClass;
        }

        /** <p>Returns the JMValidator class to use.</p>
         */
        public Class getJMValidatorClass() {
                return jmValidatorClass;
        }

        public Marshaller createMarshaller() throws JAXBException {
                Class c = getJMMarshallerClass();
                try {
                        JMMarshaller marshaller = (JMMarshaller) 
c.newInstance();
                        marshaller.setJAXBContextImpl(this);
                        return marshaller;
                } catch (InstantiationException e) {
                        throw new JAXBException("Failed to instantiate class " 
+ c.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new JAXBException("Illegal access to class " + 
c.getName(), e);
                } catch (ClassCastException e) {
                        throw new JAXBException("Class " + c.getName() +
                                        " is not implementing " +
                                        JMMarshaller.class.getName());
                }
        }

        public Unmarshaller createUnmarshaller() throws JAXBException {
                Class c = getJMUnmarshallerClass();
                try {
                        JMUnmarshaller unmarshaller = (JMUnmarshaller) 
c.newInstance();
                        unmarshaller.setJAXBContextImpl(this);
                        return unmarshaller;
                } catch (InstantiationException e) {
                        throw new JAXBException("Failed to instantiate class " 
+ c.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new JAXBException("Illegal access to class " + 
c.getName(), e);
                } catch (ClassCastException e) {
                        throw new JAXBException("Class " + c.getName() +
                                        " is not implementing " +
                                        JMUnmarshaller.class.getName());
                }
        }

        public Validator createValidator() throws JAXBException {
                Class c = getJMValidatorClass();
                try {
                        JMValidator validator = (JMValidator) c.newInstance();
                        validator.setJAXBContextImpl(this);
                        return validator;
                } catch (InstantiationException e) {
                        throw new JAXBException("Failed to instantiate class " 
+ c.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new JAXBException("Illegal access to class " + 
c.getName(), e);
                } catch (ClassCastException e) {
                        throw new JAXBException("Class " + c.getName() +
                                        " is not implementing " +
                                        JMValidator.class.getName());
                }
        }

        protected JMManager getManagerByQName(QName pQName) {
                return (JMManager) managersByQName.get(pQName);
        }

        protected JMManager getManagerByInterface(Class pElementInterface) {
                return (JMManager) managersByInterface.get(pElementInterface);
        }

        /** Returns a Manager for the given QName.
         *
         * @throws JAXBException No Manager is registered for the
         *   given QName.
         */
        public JMManager getManager(QName pQName) throws JAXBException {
                JMManager manager = getManagerByQName(pQName);
                if (manager == null) {
                        throw new JAXBException("A Manager for " + pQName + " 
is not declared.");
                }
                return manager;
        }

        /** Returns a Manager for the given element interface.
         * Same method than [EMAIL PROTECTED] #getManager(Class)}, except that 
it
         * throws a [EMAIL PROTECTED] JAXBException}.
         * @throws JAXBException No Manager is registered for the
         *   given QName.
         * @see #getManagerS(Class)
         */
        public JMManager getManager(Class pElementInterface) throws 
JAXBException {
                JMManager manager = getManagerByInterface(pElementInterface);
                if (manager == null) {
                        throw new JAXBException("A Manager for " + 
pElementInterface.getName() +
                        " is not declared.");
                }
                return manager;
        }

        /** Returns a Manager for the given element interface.
         * Same method than [EMAIL PROTECTED] #getManager(Class)}, except that 
it
         * throws a [EMAIL PROTECTED] SAXException}.
         * @throws SAXException No Manager is registered for the
         *   given QName.
         * @see #getManager(Class)
         */
        public JMManager getManagerS(Class pElementInterface) throws 
SAXException {
                JMManager manager = getManagerByInterface(pElementInterface);
                if (manager == null) {
                        throw new SAXException("A Manager for " + 
pElementInterface.getName() +
                                                                   " is not 
declared.");
                }
                return manager;
        }

  /** <p>Returns a new JMMarshaller.</p>
   */
  public JMMarshaller getJMMarshaller() throws MarshalException {
    Class c = getJMMarshallerClass();
    if (c == null) {
      throw new MarshalException("A JMMarshaller class is not set.");
    }
    try {
      return (JMMarshaller) c.newInstance();
    } catch (Exception e) {
      throw new MarshalException("Failed to instantiate JMMarshaller class " + 
c, e);
    }
  }

  /** <p>Returns a new JMUnmarshaller.</p>
   */
  public JMUnmarshaller getJMUnmarshaller() throws UnmarshalException {
    Class c = getJMUnmarshallerClass();
    if (c == null) {
      throw new UnmarshalException("A JMUnmarshaller class is not set.");
    }
    try {
      return (JMUnmarshaller) c.newInstance();
    } catch (Exception e) {
      throw new UnmarshalException("Failed to instantiate JMUnmarshaller class 
" + c, e);
    }
  }

  /** <p>Returns a new JMValidator.</p>
   */
  public JMValidator getJMValidator() throws ValidationException {
    Class c = getJMValidatorClass();
    if (c == null) {
      throw new ValidationException("A JMValidator class is not set.");
    }
    try {
      return (JMValidator) c.newInstance();
    } catch (Exception e) {
      throw new ValidationException("Failed to instantiate JMValidator class " 
+ c, e);
    }
  }

  /** <p>Returns a new instance of JMPM.</p>
   */
  public PM getJMPM(Class pElementInterface) throws PMException {
    JMManager manager = getManagerByInterface(pElementInterface);
    Class c = manager.getPmClass();
    if (c == null) {
      throw new PMException("No persistency class configured for " +
                             pElementInterface.getName());
    }
    try {
      PM pm = (PM) c.newInstance();
      pm.init(manager);
      return pm;
    } catch (Exception e) {
      e.printStackTrace(System.err);
      throw new PMException("Could not instantiate persistence manager class " +
                             c.getName(), e);
    }
  }

  /** <p>Returns a new instance of JMPM.</p>
   */
  public PM getJMPM(QName pQName) throws PMException {
    JMManager manager = getManagerByQName(pQName);
    Class c = manager.getPmClass();
    if (c == null) {
      throw new PMException("No persistency class configured for " + pQName);
    }
    try {
      PM pm = (PM) c.newInstance();
      pm.init(manager);
      return pm;
    } catch (Exception e) {
      throw new PMException("Could not instantiate persistence manager class " +
                             c.getName(), e);
    }
  }

  private boolean first = true;
  public void registerPackages(String packageNames, ClassLoader cl)
                        throws JAXBException {
          for (StringTokenizer st = new StringTokenizer(packageNames, ":"); st
                                .hasMoreTokens();) {
                        String packageName = st.nextToken();
                        String configFileName = ((packageName.length() > 0) ? 
(packageName
                                        .replace('.', '/') + '/') : "")
                                        + "Configuration.xml";
                        URL url = cl.getResource(configFileName);
                        if (url != null) {
                                InputStream istream = null;
                                try {
                                        Configuration c = new 
Configuration(this, cl);
                                        Configurator configurator = new 
Configurator();
                                        
configurator.setNamespace(CONFIGURATION_URI);
                                        configurator.setRootObject(c);
                                        SAXParser sp = spf.newSAXParser();
                                        XMLReader xr = sp.getXMLReader();
                                        xr.setContentHandler(configurator);
                                        istream = url.openStream();
                                        InputSource isource = new 
InputSource(istream);
                                        isource.setSystemId(url.toString());
                                        xr.parse(isource);
                                        istream.close();
                                        istream = null;

                                        if (first) {
                                                first = false;
                                                
setJMMarshallerClass(c.getJMMarshallerClass());
                                                
setJMUnmarshallerClass(c.getJMUnmarshallerClass());
                                                
setJMValidatorClass(c.getJMValidatorClass());
                                        }
                                } catch (IOException e) {
                                        throw new JAXBException(
                                                        "Failed to load config 
file " + url, e);
                                } catch (SAXParseException e) {
                                        Exception f = e.getException() == null 
? e : e
                                                        .getException();
                                        JAXBException jaxbExc = new 
JAXBException("Failed to parse config file "
                                                        + url + " at line " + 
e.getLineNumber()
                                                        + ", column " + 
e.getColumnNumber() + ": "
                                                        + f.getMessage(), f);
                                        jaxbExc.initCause(e);
                                        throw jaxbExc;
                                } catch (SAXException e) {
                                        Exception f = e.getException() == null 
? e : e
                                                        .getException();
                                        String msg = "Failed to parse config 
file " + url + ": "
                                                        + f.getMessage();
                                        throw new JAXBException(msg, f);
                                } catch (ParserConfigurationException e) {
                                        throw new JAXBException("Failed to 
create a SAX Parser: "
                                                        + e.getMessage(), e);
                                } finally {
                                        if (istream != null) {
                                                try {
                                                        istream.close();
                                                } catch (Throwable ignore) {
                                                }
                                        }
                                }
                        }
                }
            if (first) {
                throw new JAXBException("Unable to locate configuration file 
Configuration.xml in " + packageNames);
              }         
        }
  
  public void unregisterPackages(String packageNames) {
          
  }
  
  /**
         * <p>
         * Initializes the context by loading the configuration or the
         * configurations from the given classpath.
         * </p>
         */
  protected void init() throws JAXBException {
    if (packageNames == null  ||  packageNames.length() == 0) {
      packageNames = JAXBContextImpl.class.getName();
      packageNames = packageNames.substring(0, packageNames.lastIndexOf('.'));
    }
    registerPackages(packageNames, getClassLoader());
  }

  /** Creates a new instance of [EMAIL PROTECTED] javax.xml.bind.JAXBContext}.
   * Invoked implicitly by
   * [EMAIL PROTECTED] 
javax.xml.bind.JAXBContext#newInstance(java.lang.String)}.
   */
  public static JAXBContextImpl createContext() throws JAXBException {
    return createContext(null, JAXBContextImpl.class.getClassLoader());
  }

  /** Invoked from the SAX handler when loading the config file.
   */
  public Configuration createConfiguration(Attributes pAttributes) throws 
JAXBException {
    String className = pAttributes.getValue("", "className");
    if (className == null  ||  className.length() == 0) {
      return new Configuration(this, cl);
    } else {
      try {
        return (Configuration) cl.loadClass(className).newInstance();
      } catch (Exception e) {
        throw new JAXBException("Failed to instantiate Configuration class " + 
className, e);
      }
    }
  }

  private static boolean verbose = true;
  private static void showException(Exception e) {
    if (!verbose) { return; }
    System.err.println("Exception catched in " + 
JAXBContextImpl.class.getName() +
                       ".createContext().");
    System.err.println("Set " + JAXBContextImpl.class.getName() +
                       ".verbose = false to suppress this message.");
    e.printStackTrace(System.err);
  }

  /** Creates a new instance of [EMAIL PROTECTED] javax.xml.bind.JAXBContext}.
   * Invoked implicitly by
   * [EMAIL PROTECTED] javax.xml.bind.JAXBContext#newInstance(String, 
ClassLoader)}
   */
  public static JAXBContextImpl createContext(String pPackageNames,
                                              ClassLoader pClassLoader)
      throws JAXBException {
    try {
       JAXBContextImpl result = new JAXBContextImpl();
       result.setClassLoader(pClassLoader);
       result.setPackageNames(pPackageNames);
       result.init();
       return result;
    } catch (RuntimeException e) {
      showException(e);
      throw e;
    } catch (JAXBException e) {
      showException(e);
      throw e;
    }
  }

  /** Invoked from the SAX handler when reading the config file
   * for adding another instance of JMManager.
   */
  public void addManager(JMManager pManager) throws JAXBException {
    Class elementInterface = pManager.getElementInterface();
    if (elementInterface == null) {
      throw new JAXBException("The Manager must have its elementInterface 
set.");
    }
    if (managersByInterface.containsKey(elementInterface)) {
      throw new JAXBException("A Manager for interface " +
                               elementInterface.getName() +
                               " is already set.");
    }

        if (pManager.getDriverClass() == null) {
                throw new IllegalStateException("Missing driver class for " + 
pManager.getQName());
        }
        if (pManager.getHandlerClass() == null) {
                throw new IllegalStateException("Missing driver class for " + 
pManager.getQName());
        }
        
    QName qName = pManager.getQName();
    if (qName != null  &&  managersByQName.containsKey(qName)) {
      throw new JAXBException("A Manager for document type " + qName +
                               " is already set.");
    }

    managersByInterface.put(elementInterface, pManager);
    if (qName != null) {
      managersByQName.put(qName, pManager);
    }
  }
}
/*
 * 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.impl;

import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;

import org.apache.ws.jaxme.JMManager;
import org.apache.ws.jaxme.xs.xml.XsQName;
import org.xml.sax.SAXException;



/** <p>An instance of this class represents a config file.
 * A JAXBContext requires an associated Configuration which
 * is located through the classpath.</p>
 *
 * @author <a href="mailto:[EMAIL PROTECTED]">Jochen Wiedmann</a>
 * @version $Id: Configuration.java,v 1.7 2005/03/10 10:14:03 jochen Exp $
 */
public class Configuration {
  JAXBContextImpl context;
  Manager currentManager;
  Map managers = new HashMap();
  private Class jmMarshallerClass = JMMarshallerImpl.class;
  private Class jmUnmarshallerClass = JMUnmarshallerImpl.class;
  private Class jmValidatorClass = JMValidatorImpl.class;
  private ClassLoader classLoader;
  
  public Configuration(JAXBContextImpl pContext, ClassLoader cl) {
    context = pContext;
    this.classLoader = cl;
  }

  public class Manager implements JMManager {
    public class Property {
      private String managerName;
      private String value;

      public String getName() { return managerName; }
      public void setName(String pName) { managerName = pName; }
      public String getValue() { return value; }
      public void setValue(String pValue) { value = pValue; }
      public void finish() throws SAXException {
        if (managerName == null) {
          throw new NullPointerException("Missing 'name' attribute in 
'property' element.");
        }
        if (value == null) {
          throw new NullPointerException("Missing 'value' attribute in 
'property' element.");
        }
        if (properties == null) {
          properties = new HashMap();
        }
        if (properties.put(managerName, value) != null) {
          throw new IllegalStateException("The property " + managerName + " was 
specified more than once.");
        }
      }
    }

    private QName name;
    private Class elementInterface;
    private Class elementClass;
    private Class handlerClass;
    private Class driverClass;
    private Class pmClass;
        private String prefix;
    private Map properties;
    private ClassLoader classLoader;
    
        public Manager(ClassLoader classLoader) {
                this.classLoader = classLoader;
        }
        public String getPrefix() {
                return prefix;
        }
        /** Sets the suggested prefix for the elements namespace.
         */
        public void setPrefix(String prefix) {
                this.prefix = prefix;
        }
        
        public void setQName(QName pName) { name = pName; }
    public QName getQName() { return name; }
    public void setElementClass(String pElementClass) throws 
ClassNotFoundException {
        elementClass = classLoader.loadClass(pElementClass);
    }
    public Class getElementClass() { return elementClass; }
    public void setElementInterface(String pElementInterface) throws 
ClassNotFoundException {
        elementInterface = classLoader.loadClass(pElementInterface);
    }
    public Class getElementInterface() { return elementInterface; }
        public Class getHandlerClass() { return handlerClass; }
        public void setHandlerClass(String pHandlerClass) throws 
ClassNotFoundException {
        handlerClass = classLoader.loadClass(pHandlerClass);
                if (!JMSAXElementParser.class.isAssignableFrom(handlerClass)) {
                        throw new IllegalStateException("The class " + 
handlerClass.getName()
                                                                                
        + " is not implementing "
                                                                                
        + JMSAXElementParser.class.getName());
                }
    }
    public void setDriverClass(String pMarshallerClass) throws 
ClassNotFoundException {
        driverClass = classLoader.loadClass(pMarshallerClass);
                if (!JMSAXDriver.class.isAssignableFrom(driverClass)) {
                        throw new IllegalStateException("The class " + 
driverClass.getName()
                                                                                
        + " is not implementing "
                                                                                
        + JMSAXDriver.class.getName());
                }
    }
        public Class getDriverClass() { return driverClass; }
    public JMSAXDriver getDriver() throws SAXException {
                try {
                        return (JMSAXDriver) driverClass.newInstance();
                } catch (InstantiationException e) {
                        throw new SAXException("Unable to instantiate driver 
class " + driverClass.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new SAXException("Illegal access to driver class 
" + driverClass.getName(), e);
                }
        }
        /** Sets the persistence manager class.
         */
        public void setPmClass(String pPersistencyClass) throws 
ClassNotFoundException {
        pmClass = classLoader.loadClass(pPersistencyClass);
    }
    public Class getPmClass() { return pmClass; }
    public JAXBContextImpl getFactory() { return context; }
    public Property createProperty() {
      return new Property();
    }
    public String getProperty(String pName) {
      if (pName == null) {
        throw new IllegalArgumentException("The property name must not be 
null.");
      }
      if (properties == null) {
        return null;
      }
      return (String) properties.get(pName);
    }
    public void finish() throws SAXException {
      if (currentManager != this) {
        throw new IllegalStateException("currentManager != this");
      }
      try {
                  if (prefix != null) {
                          name = new QName(name.getNamespaceURI(), 
name.getLocalPart(), prefix);
                  }
                  context.addManager(currentManager);
                  currentManager = null;
      } catch (Exception e) {
        throw new SAXException(e.getMessage(), e);
      }
    }

    public JMSAXElementParser getHandler() throws SAXException {
                try {
                        return (JMSAXElementParser) handlerClass.newInstance();
                } catch (InstantiationException e) {
                        throw new SAXException("Unable to instantiate handler 
class "
                                                                   + 
jmUnmarshallerClass.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new SAXException("Illegal access to handler class 
"
                                                                   + 
jmUnmarshallerClass.getName(), e);
                }
    }

        public Object getElementJ() throws JAXBException {
                try {
                        return elementClass.newInstance();
                } catch (InstantiationException e) {
                        throw new JAXBException("Unable to instantiate handler 
class "
                                                                    + 
jmUnmarshallerClass.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new JAXBException("Illegal access to handler 
class "
                                                                    + 
jmUnmarshallerClass.getName(), e);
                }
    }

        public Object getElementS() throws SAXException {
                try {
                        return elementClass.newInstance();
                } catch (InstantiationException e) {
                        throw new SAXException("Unable to instantiate handler 
class "
                                                                   + 
jmUnmarshallerClass.getName(), e);
                } catch (IllegalAccessException e) {
                        throw new SAXException("Illegal access to handler class 
"
                                                                   + 
jmUnmarshallerClass.getName(), e);
                }
    }
  }

  /** <p>Creates a new Manager.</p>
   */
  public Manager createManager() {
    if (currentManager != null) {
      throw new IllegalStateException("currentManager != null");
    }
    currentManager = new Manager(classLoader);
    return currentManager;
  }

  /** <p>Sets the JMMarshaller class.</p>
   */
  public void setJMMarshallerClass(Class pJMMarshallerClass) {
    jmMarshallerClass = pJMMarshallerClass;
  }

  /** <p>Returns the JMMarshaller class.</p>
   */
  public Class getJMMarshallerClass() {
    return jmMarshallerClass;
  }

  /** <p>Sets the JMUnmarshaller class.</p>
   */
  public void setJMUnmarshallerClass(Class pJMUnmarshallerClass) {
    jmUnmarshallerClass = pJMUnmarshallerClass;
  }

  /** <p>Returns the JMUnmarshaller class.</p>
   */
  public Class getJMUnmarshallerClass() {
    return jmUnmarshallerClass;
  }

  /** <p>Sets the JMValidator class.</p>
   */
  public void setJMValidatorClass(Class pJMValidatorClass) {
    jmValidatorClass = pJMValidatorClass;
  }

  public Class getJMValidatorClass() {
    return jmValidatorClass;
  }
}
/*
 * 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;


/** <p>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:</p>
 * <pre>
 *   &lt;outerBean foo="true" bar="Quite right"&gt;
 *     &lt;innerBean whatever="57"&gt;
 *     &lt;/innerBean
 *   &lt;/outerBean&gt;
 * </pre>
 * The example would create an object outerBean and call its
 * methods <code>setFoo(boolean)</code> and
 * <code>setBar(String)</code> to process the attributes.
 * It would also create a bean innerBean by calling the
 * outerBeans method <code>createInnerBean()</code>.
 * Finally the innerBean is configured by calling
 * <code>setWhatever(int)</code>.</p>
 * 
 * @author <a href="mailto:[EMAIL PROTECTED]">Jochen Wiedmann</a>
 * @version $Id: Configurator.java,v 1.4 2005/03/10 10:14:03 jochen Exp $
 */
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;

  /** <p>Sets the namespace handled by the configurator. Defaults
   * to no namespace. Shortcut for
   * <code>setNamespace(new String[]{pNamespace})</code>.</p>
   *
   * @param pNamespace The namespace being set
   */
  public void setNamespace(String pNamespace) {
    setNamespaces(new String[]{pNamespace});
  }

  /** <p>Sets the namespaces handled by the configurator. Defaults
   * to no namespace.</p>
   *
   * @param pNamespaces The namespaces being set
   */
  public void setNamespaces(String[] pNamespaces) {
    namespaces = pNamespaces;
  }

  /** <p>Returns the namespaces handled by the configurator. Defaults
   * to no namespace.</p>
   */
  public String[] getNamespaces() {
    return namespaces;
  }

  /** <p>Sets the Locator being used in error messages.</p>
   */
  public void setDocumentLocator(Locator pLocator) {
    locator = pLocator;
  }

  /** <p>Returns the Locator being used in error messages.</p>
   */
  public Locator getDocumentLocator() {
    return locator;
  }

  /** <p>Sets the bean factory, creating the outermost element.
   * The bean factory must have a matching <code>createElementName()</code>
   * method, with <samp>ElementName</samp> being the element name
   * of the document element.</p>
   */
  public void setBeanFactory(Object pFactory) {
    beanFactory = pFactory;
  }

  /** <p>Returns the bean factory, creating the outermost element.
   * The bean factory must have a matching <code>createElementName()</code>
   * method, with <samp>ElementName</samp> being the element name
   * of the document element.</p>
   */
  public Object getBeanFactory() {
    return beanFactory == null ? this : beanFactory;
  }

  /** <p>An alternative to using the bean factory. This object
   * is used as the root object, regardless of its name.</p>
   */
  public void setRootObject(Object pRootObject) {
    rootObject = pRootObject;
  }

  /** <p>An alternative to using the bean factory. This object
   * is used as the root object, regardless of its name.</p>
   */
  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);
  }

  /** <p>Returns whether a namespace is matching the configured
   * namespace.</p>
   */
  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;
    }
  }

  /** <p>Given a prefix and a name, creates a method name matching
   * the prefix and the name.</p>
   */
  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();
  }

  /** <p>Creates a new bean, matching the element name <code>pLocalName</code>.
   * If this is the outermost bean, calls the bean factorys
   * <code>createBeanName()</code> method, otherwise calls the current beans
   * <code>createBeanName()</code> method, with <samp>beanName</samp>
   * being the value of the <code>pLocalName</code> parameter.</p>
   */
  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();
              SAXParseException saxExc = new SAXParseException("Failed to 
invoke method " + setMethodName +
                                           " of class " + 
currentBean.getClass().getName(),
                                           getDocumentLocator(),
                                           (t instanceof Exception) ? 
((Exception) t) : e);
              saxExc.initCause(e);
              throw saxExc;
            }
          }
        }
      }
    }
  }

  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);
    }
  }

  /** <p>Terminates parsing the current bean by calling its
   * <code>finish()</code> method, if any.</p>
   */
  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;
      }
    }
  }

  /** <p>Handles atomic child elements by invoking their method
   * <code>addText(String pText)</code>. Note that it may happen,
   * that this method is invoked multiple times, if the parser
   * splits a piece of text into multiple SAX events.</p>
   */
  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;
      }
    }
  }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to