Index: /home/jwi/workspace/ws-jaxme/src/test/jaxb/defaults.xsd
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMManager.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMManager.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMManager.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.ws.jaxme.impl.JAXBContextImpl;
 import org.apache.ws.jaxme.impl.JMSAXDriver;
+import org.apache.ws.jaxme.impl.JMSAXDriverController;
 import org.apache.ws.jaxme.impl.JMSAXElementParser;
 import org.xml.sax.SAXException;
 
@@ -78,7 +79,7 @@
    */
   public JMSAXElementParser getHandler() throws SAXException;
 
-  /** Returns the document types driverr class.
+  /** Returns the document types driver class.
    */
   public Class getDriverClass();
 
@@ -86,6 +87,14 @@
    */
   public JMSAXDriver getDriver() throws SAXException;
 
+  /** Returns the document types driver controller class.
+   */
+  public Class getDriverControllerClass();
+
+  /** Returns an instance of the document types driver controller class.
+   */
+  public JMSAXDriverController getDriverController() throws SAXException;
+
   /** <p>Returns the persistency class. The persistency class
    * must be able to store documents in a database, update,
    * delete or retrieve them.</p>
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/SimpleTypeSGImpl.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/SimpleTypeSGImpl.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/SimpleTypeSGImpl.java	(working copy)
@@ -56,6 +56,8 @@
   public boolean isAtomic(SimpleTypeSG pController) { return false; }
   public boolean isList(SimpleTypeSG pController) { return false; }
   public boolean isUnion(SimpleTypeSG pController) { return false; }
+  public boolean isXsId(SimpleTypeSG pController) { return false; }
+  public boolean isXsIdRef(SimpleTypeSG pController) { return false; }
   public boolean hasSetMethod(SimpleTypeSG pController) { return true; }
   public void setNullable(SimpleTypeSG pController, boolean pNullable) {
     setNullable(pNullable);
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDREFSG.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDREFSG.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDREFSG.java	(working copy)
@@ -17,17 +17,71 @@
 package org.apache.ws.jaxme.generator.types;
 
 import org.apache.ws.jaxme.generator.sg.SGFactory;
+import org.apache.ws.jaxme.generator.sg.SGlet;
 import org.apache.ws.jaxme.generator.sg.SchemaSG;
+import org.apache.ws.jaxme.generator.sg.SimpleTypeSG;
+import org.apache.ws.jaxme.js.DirectAccessible;
+import org.apache.ws.jaxme.js.JavaMethod;
+import org.apache.ws.jaxme.js.JavaQName;
+import org.apache.ws.jaxme.js.JavaQNameImpl;
+import org.apache.ws.jaxme.js.JavaSource;
+import org.apache.ws.jaxme.js.LocalJavaField;
+import org.apache.ws.jaxme.js.TypedValue;
+import org.apache.ws.jaxme.js.impl.TypedValueImpl;
 import org.apache.ws.jaxme.xs.XSType;
 import org.xml.sax.SAXException;
 
 /**
  * @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
  */
-public class IDREFSG extends StringSG {
-  /** <p>Creates a new instance of IDREFSG.</p>
-   */
-  public IDREFSG(SGFactory pFactory, SchemaSG pSchema, XSType pType) throws SAXException {
-    super(pFactory, pSchema, pType);
-  }
+public class IDREFSG extends SimpleTypeSGImpl {
+	private static final JavaQName OBJECT_TYPE = JavaQNameImpl.getInstance(Object.class);
+
+	/** <p>Creates a new instance of IDREFSG.</p>
+	 */
+	public IDREFSG(SGFactory pFactory, SchemaSG pSchema, XSType pType) throws SAXException {
+		super(pFactory, pSchema, pType);
+	}
+
+	public JavaQName getRuntimeType(SimpleTypeSG pController) { return OBJECT_TYPE; }
+	public boolean isCausingParseConversionEvent(SimpleTypeSG pController) { return false; }
+	public boolean isXsIdRef(SimpleTypeSG pController) { return true; }
+
+	public TypedValue getCastFromString(SimpleTypeSG pController, JavaMethod pMethod, Object pValue, Object pData) throws SAXException {
+	    return new TypedValueImpl(null, OBJECT_TYPE);
+	}
+
+	public TypedValue getCastToString(SimpleTypeSG pController, JavaMethod pMethod, Object pValue, DirectAccessible pData) throws SAXException {
+		LocalJavaField s = pMethod.newJavaField(String.class);
+		pMethod.addIf(pValue, " == null");
+		pMethod.addLine(s, " = null;");
+		pMethod.addElse();
+		pMethod.addLine(s, " = ", pData, ".getXsIdAttribute(", pValue, ");");
+		pMethod.addIf(s, " == null");
+		pMethod.addThrowNew(IllegalStateException.class,
+							JavaSource.getQuoted("ID attribute not set"));
+		pMethod.addEndIf();
+		pMethod.addEndIf();
+		return s;
+	}
+
+	public TypedValue getCastFromString(SimpleTypeSG pController, String pValue) throws SAXException {
+		throw new IllegalStateException("Unable to resolve ID's at compile time.");
+	}
+
+	public void forAllValues(SimpleTypeSG pController, JavaMethod pMethod, Object pValue, SGlet pSGlet) throws SAXException {
+	    pSGlet.generate(pMethod, pValue);
+	}
+
+	public void forAllNonNullValues(SimpleTypeSG pController, JavaMethod pMethod, Object pValue, SGlet pSGlet) throws SAXException {
+	    LocalJavaField f = pMethod.newJavaField(OBJECT_TYPE);
+	    f.addLine(pValue);
+	    pMethod.addIf(f, " != null");
+	    pSGlet.generate(pMethod, pValue);
+	    pMethod.addEndIf();
+	}
+
+	public Object getEqualsCheck(SimpleTypeSG pController, JavaMethod pMethod, Object pValue1, Object pValue2) throws SAXException {
+	    return new Object[]{pValue1, ".equals(", pValue2, ")"};
+	}
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDSG.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDSG.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/types/IDSG.java	(working copy)
@@ -18,19 +18,20 @@
 
 import org.apache.ws.jaxme.generator.sg.SGFactory;
 import org.apache.ws.jaxme.generator.sg.SchemaSG;
+import org.apache.ws.jaxme.generator.sg.SimpleTypeSG;
 import org.apache.ws.jaxme.xs.XSType;
 import org.xml.sax.SAXException;
 
 
-/**
- * @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
+/** Implementation of {@link org.apache.ws.jaxme.generator.sg.SimpleTypeSG}
+ * for <code>xs:id</code>.
  */
 public class IDSG extends StringSG {
+	/** Creates a new instance of IDSG.
+	 */
+	public IDSG(SGFactory pFactory, SchemaSG pSchema, XSType pType) throws SAXException {
+		super(pFactory, pSchema, pType);
+	}
 
-  /** <p>Creates a new instance of IDSG.</p>
-   */
-  public IDSG(SGFactory pFactory, SchemaSG pSchema, XSType pType) throws SAXException {
-    super(pFactory, pSchema, pType);
-  }
-
+	public boolean isXsId(SimpleTypeSG pController) { return true; }
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/JAXBSchemaSG.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/JAXBSchemaSG.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/JAXBSchemaSG.java	(working copy)
@@ -33,6 +33,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.ws.jaxme.XMLWriter;
+import org.apache.ws.jaxme.generator.sg.AttributeSG;
 import org.apache.ws.jaxme.generator.sg.ComplexContentSG;
 import org.apache.ws.jaxme.generator.sg.ComplexTypeSG;
 import org.apache.ws.jaxme.generator.sg.Context;
@@ -44,14 +45,18 @@
 import org.apache.ws.jaxme.generator.sg.SchemaSGChain;
 import org.apache.ws.jaxme.generator.sg.TypeSG;
 import org.apache.ws.jaxme.impl.JAXBContextImpl;
+import org.apache.ws.jaxme.impl.JMMarshallerImpl;
+import org.apache.ws.jaxme.impl.JMSAXDriverController;
 import org.apache.ws.jaxme.impl.XMLWriterImpl;
 import org.apache.ws.jaxme.js.JavaConstructor;
 import org.apache.ws.jaxme.js.JavaField;
+import org.apache.ws.jaxme.js.JavaInnerClass;
 import org.apache.ws.jaxme.js.JavaMethod;
 import org.apache.ws.jaxme.js.JavaQName;
 import org.apache.ws.jaxme.js.JavaQNameImpl;
 import org.apache.ws.jaxme.js.JavaSource;
 import org.apache.ws.jaxme.js.JavaSourceFactory;
+import org.apache.ws.jaxme.js.LocalJavaField;
 import org.apache.ws.jaxme.js.Parameter;
 import org.apache.ws.jaxme.js.TextFile;
 import org.apache.ws.jaxme.logging.Logger;
@@ -68,6 +73,7 @@
 import org.apache.ws.jaxme.xs.xml.XsQName;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.xml.sax.ContentHandler;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
 
@@ -380,12 +386,16 @@
         continue;
       }
 
+      JavaQName implQName = ctx.getXMLImplementationName();
+      JavaQName jmSaxDriverControllerClass = getJMSAXDriverControllerClass(pController, implQName.getPackageName());
+
       Element manager = doc.createElementNS(uri, "Manager");
       root.appendChild(manager);
       manager.setAttributeNS(null, "elementInterface", ctx.getXMLInterfaceName().toString());
-      manager.setAttributeNS(null, "elementClass", ctx.getXMLImplementationName().toString());
+      manager.setAttributeNS(null, "elementClass", implQName.toString());
       manager.setAttributeNS(null, "handlerClass", typeCtx.getXMLHandlerName().toString());
       manager.setAttributeNS(null, "driverClass", typeCtx.getXMLSerializerName().toString());
+      manager.setAttributeNS(null, "driverControllerClass", jmSaxDriverControllerClass.toString());
       manager.setAttributeNS(null, "validatorClass", ctx.getXMLValidatorName().toString());
       if (o instanceof ObjectSG) {
 		  XsQName name = ((ObjectSG) o).getName();
@@ -509,10 +519,116 @@
 
 	  generateCreateMethod(js, contextSet, typeSG, null);
     }
-    
+
     return js;
   }
 
+  private AttributeSG getIdAttribute(TypeSG pType) {
+	  if (pType.isComplex()) {
+		  /* Check, if the super class has an ID attribute.
+		   * If so, do nothing and leave the ID handling to
+		   * super class.
+		   */
+		  if (!pType.isExtension()  ||
+		      getIdAttribute(pType.getExtendedType()) == null) {
+			  AttributeSG[] attributes = pType.getComplexTypeSG().getAttributes();
+			  for (int i = 0;  i < attributes.length;  i++) {
+				  AttributeSG attr = attributes[i];
+				  TypeSG type = attr.getTypeSG();
+				  if (type != null  &&  type.getSimpleTypeSG().isXsId()) {
+					  return attr;
+				  }
+			  }
+		  }
+	  }
+	  return null;
+  }
+
+  protected JavaQName getJMSAXDriverControllerClass(SchemaSG pController, String pPackage) throws SAXException {
+	  final List list = new ArrayList();
+	  TypeSG[] types = pController.getTypes();
+	  for (int i = 0;  i < types.length;  i++) {
+		  checkIdAttribute(list, types[i]);
+	  }
+	  ObjectSG[] objects = pController.getObjects();
+	  for (int i = 0;  i < objects.length;  i++) {
+		  checkIdAttribute(list, objects[i]);
+	  }
+	  GroupSG[] groups = pController.getGroups();
+	  for (int i = 0;  i < groups.length;  i++) {
+		  checkIdAttribute(list, groups[i]);
+	  }
+	  if (list.size() == 0) {
+		  return JavaQNameImpl.getInstance(JMSAXDriverController.class);
+	  } else {
+		  JavaQName qName = JavaQNameImpl.getInstance(pPackage, "JMSAXDriverController");
+		  JavaSourceFactory factory = pController.getJavaSourceFactory();
+		  if (factory.getJavaSource(qName) == null) {
+			  JavaSource js = factory.newJavaSource(qName, JavaSource.PUBLIC);
+			  js.addExtends(JMSAXDriverController.class);
+			  JavaMethod jm = js.newJavaMethod("getXsIdAttribute", String.class, JavaSource.PUBLIC);
+			  Parameter param = jm.addParam(Object.class, "pObject");
+			  for (int i = 0;  i < list.size();  i++) {
+				  TypeSG tSG = (TypeSG) list.get(i);
+				  jm.addIf(i == 0, param, " instanceof ", tSG.getRuntimeType());
+				  LocalJavaField f = jm.newJavaField(tSG.getRuntimeType());
+				  f.addLine("(", tSG.getRuntimeType(), ") ", param);
+				  AttributeSG attr = getIdAttribute(tSG);
+				  jm.addLine("return ", attr.getPropertySG().getValue(f), ";");
+			  }
+			  jm.addElse();
+			  jm.addLine("return null;");
+			  jm.addEndIf();
+		  }
+		  return qName;
+	  }
+  }
+
+  private void checkIdAttribute(final List pList, ObjectSG pObjectSG) throws SAXException {
+	  TypeSG type = pObjectSG.getTypeSG();
+	  if (!type.isGlobalType()) {
+		  checkIdAttribute(pList, type);
+	  }
+  }
+
+  private void checkIdAttribute(final List pList, GroupSG pGroup) throws SAXException {
+	  ParticleSG[] particles = pGroup.getParticles();
+	  for (int i = 0;  i < particles.length;  i++) {
+		  checkIdAttribute(pList, particles[i]);
+	  }
+  }
+
+  private void checkIdAttribute(final List pList, ParticleSG pParticle) throws SAXException {
+	  if (pParticle.isElement()) {
+		  ObjectSG oSG = pParticle.getObjectSG();
+		  if (!oSG.isGlobal()) {
+			  checkIdAttribute(pList, oSG);
+		  }
+	  } else if (pParticle.isGroup()) {
+		  GroupSG group = pParticle.getGroupSG();
+		  if (!group.isGlobal()) {
+			  checkIdAttribute(pList, group);
+		  }
+	  } else if (pParticle.isWildcard()) {
+		  // Ignore it
+	  } else {
+		  throw new IllegalStateException("Invalid particle type");
+	  }
+  }
+
+  private void checkIdAttribute(final List pList, TypeSG pType) throws SAXException {
+	AttributeSG attr = getIdAttribute(pType);
+	if (attr != null) {
+		pList.add(pType);
+	}
+	if (pType.isComplex()  &&  !pType.getComplexTypeSG().hasSimpleContent()) {
+		ComplexContentSG ccSG = pType.getComplexTypeSG().getComplexContentSG();
+		if (!ccSG.isEmpty()) {
+			checkIdAttribute(pList, ccSG.getRootParticle());
+		}
+	}
+  }
+
   private void generateCreateMethod(JavaSource pJs, Set pContextSet,
 		  							TypeSG pType, String pPrefix) throws SAXException {
 	  if (!pType.isComplex()  ||  pContextSet.contains(pType)) {
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/ccsg/HandlerSGImpl.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/ccsg/HandlerSGImpl.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/impl/ccsg/HandlerSGImpl.java	(working copy)
@@ -17,11 +17,13 @@
 
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import javax.xml.bind.ValidationEvent;
 import javax.xml.namespace.QName;
 
+import org.apache.ws.jaxme.IDREF;
 import org.apache.ws.jaxme.ValidationEvents;
 import org.apache.ws.jaxme.generator.sg.AttributeSG;
 import org.apache.ws.jaxme.generator.sg.ComplexTypeSG;
@@ -34,10 +36,14 @@
 import org.apache.ws.jaxme.js.JavaQNameImpl;
 import org.apache.ws.jaxme.js.JavaSource;
 import org.apache.ws.jaxme.js.LocalJavaField;
+import org.apache.ws.jaxme.js.Parameter;
 import org.apache.ws.jaxme.js.TypedValue;
 import org.apache.ws.jaxme.js.impl.TypedValueImpl;
+import org.apache.ws.jaxme.xs.xml.XsQName;
 import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 
 
 /** Base implementation of
@@ -106,9 +112,9 @@
 		}
 		
 		JavaMethod jm = getJavaSource().newJavaMethod("addAttribute", JavaQNameImpl.VOID, JavaSource.PUBLIC);
-		DirectAccessible pURI = jm.addParam(String.class, "pURI");
-		DirectAccessible pLocalName = jm.addParam(String.class, "pLocalName");
-		DirectAccessible pValue = jm.addParam(String.class, "pValue");
+		Parameter pURI = jm.addParam(String.class, "pURI");
+		Parameter pLocalName = jm.addParam(String.class, "pLocalName");
+		Parameter pValue = jm.addParam(String.class, "pValue");
 		jm.addThrows(SAXException.class);
 		jm.addIf(pURI, " == null");
 		jm.addLine(pURI, " = \"\";");
@@ -116,6 +122,7 @@
 		
 		JavaQName resultType = ctSG.getClassContext().getXMLInterfaceName();
 		LocalJavaField result = jm.newJavaField(resultType);
+		result.setFinal(true);
 		result.addLine("(", resultType, ") result");
 
 		Set uris = createSetOfExplicitURIs(myAttributes);
@@ -138,9 +145,57 @@
 				
 				jm.addIf(firstInNamespace, JavaSource.getQuoted(attr.getName().getLocalName()), ".equals(", pLocalName, ")");
 				firstInNamespace = false;
-				createSimpleTypeConversion(jm, myAttributes[i].getTypeSG(), pValue,
-										   "@" + myAttributes[i].getName(),
-										   attr.getPropertySG(), result);
+				boolean idref = false;
+				if (attr.getTypeSG().getSimpleTypeSG().isXsId()) {
+					jm.addIf("!getHandler().addId(", pValue, ", ", result, ")");
+					jm.addLine("getHandler().validationEvent(",
+							   javax.xml.bind.ValidationEvent.class,
+							   ".ERROR, ",
+							   JavaSource.getQuoted("Duplicate ID: "),
+							   " + ", pValue, ", ",
+							   ValidationEvents.class,
+							   ".EVENT_DUPLICATE_ID, null);");
+					jm.addEndIf();
+				} else if (attr.getTypeSG().getSimpleTypeSG().isXsIdRef()) {
+					idref = true;
+					try {
+						pValue.setFinal(true);
+						LocalJavaField locator = jm.newJavaField(Locator.class);
+						locator.setFinal(true);
+						locator.addLine("getHandler().getDocumentLocator()");
+						
+						// FIXME how to properly create anonymous innner class?
+						LocalJavaField idrefField = jm.newJavaField(IDREF.class, "idref");
+						idrefField.addLine("new ", IDREF.class, "() {");
+						idrefField.addLine("  public void validate(", Map.class, " pIds) throws ", SAXException.class, " {");
+						idrefField.addLine("    Object o = pIds.get(", pValue, ");");
+						idrefField.addLine("    if (o != null) {");
+						idrefField.addLine("      ", result, ".", attr.getPropertySG().getXMLSetMethodName(), "(", "o", ");");
+						idrefField.addLine("    } else {");
+						idrefField.addLine("      final String msg = ",
+										   JavaSource.getQuoted("ID attribute '"),
+										   " + ", pValue, " + ",
+										   JavaSource.getQuoted("' was referenced but never declared"), ";");
+						idrefField.addLine("      ", SAXParseException.class, " e = new ",
+									       SAXParseException.class, "(msg, ", locator, ");");
+						idrefField.addLine("      getHandler().validationEvent(",
+										   javax.xml.bind.ValidationEvent.class,
+										   ".ERROR, msg,",
+										   ValidationEvents.class,
+										   ".EVENT_IDREF_UNDECLARED, e);");
+						idrefField.addLine("    }");
+						idrefField.addLine("  }");
+						idrefField.addLine("};");
+						jm.addLine("getHandler().addIdref(", idrefField, ");");
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+				if (!idref) {
+					createSimpleTypeConversion(jm, myAttributes[i].getTypeSG(), pValue,
+											   "@" + myAttributes[i].getName(),
+											   attr.getPropertySG(), result);
+				}
 				jm.addLine("return;");
 			}
 			if (!firstInNamespace) {
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/SimpleTypeSG.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/SimpleTypeSG.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/generator/sg/SimpleTypeSG.java	(working copy)
@@ -155,4 +155,14 @@
    * "set" method <code>pMethod</code>.</p>
    */
   public void addValidation(JavaMethod pMethod, DirectAccessible pValue) throws SAXException;
+
+	/** Returns, whether the simple type is an instance of
+	 * <code>xs:id</code>.
+	 */
+	public boolean isXsId();
+
+	/** Returns, whether the simple type is an instance of
+	 * <code>xs:idref</code>.
+	 */
+	public boolean isXsIdRef();
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/junit/JiraTest.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/junit/JiraTest.java	(revision 232372)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/junit/JiraTest.java	(working copy)
@@ -16,12 +16,17 @@
 import net.dspc.commons.activitymodel2.Body2;
 import net.dspc.commons.activitymodel2.ObjectFactory;
 
+import org.apache.ws.jaxme.ValidationEvents;
 import org.apache.ws.jaxme.generator.Generator;
 import org.apache.ws.jaxme.generator.SchemaReader;
 import org.apache.ws.jaxme.generator.impl.GeneratorImpl;
 import org.apache.ws.jaxme.generator.sg.SchemaSG;
 import org.apache.ws.jaxme.generator.sg.impl.JAXBSchemaReader;
 import org.apache.ws.jaxme.generator.util.JavaNamer;
+import org.apache.ws.jaxme.impl.ValidationEventImpl;
+import org.apache.ws.jaxme.test.jira.jaxme58.AuthorType;
+import org.apache.ws.jaxme.test.jira.jaxme58.BookType;
+import org.apache.ws.jaxme.test.jira.jaxme58.Booklist;
 import org.apache.ws.jaxme.test.jira.jaxme65.Jaxme65;
 import org.apache.ws.jaxme.test.jira.jaxme65.Jaxme65Type;
 import org.apache.ws.jaxme.test.misc.types.Jira62;
@@ -175,12 +180,15 @@
 	}
 
 	private static class EventDetector implements ValidationEventHandler {
-		private boolean gotEvent = false;
+		private ValidationEvent event;
 		public boolean handleEvent(ValidationEvent pEvent) {
-			gotEvent = true;
+			if (event == null) {
+				event = pEvent;
+			}
 			return true;
 		}
-		boolean isSuccess() { return !gotEvent; }
+		boolean isSuccess() { return event == null; }
+		ValidationEventImpl getEvent() { return (ValidationEventImpl) event; }
 	};
 
 	private void runFacetTest(int i, String pAttrName, boolean pSuccess) throws JAXBException {
@@ -257,4 +265,55 @@
 		assertEquals(1, list2.size());
 		assertEquals("some text", list2.get(0));
 	}
+
+	/** Test for <a href="http://issues.apache.org/jira/browse/JAXME-58">JAXME-58</a>.
+	 */
+	public void testJAXME58() throws Exception {
+		final String xml1 = getBooklist(false, false);
+		final JAXBContext ctx = getJAXBContext(Booklist.class);
+		Unmarshaller unmarshaller = ctx.createUnmarshaller();
+		final Booklist booklist = (Booklist) unmarshaller.unmarshal(new InputSource(new StringReader(xml1)));
+		final List books = booklist.getBook();
+		assertEquals(2, books.size());
+		final BookType hi = (BookType) books.get(0);
+		final BookType helloAgain = (BookType) books.get(1);
+		final List authors = booklist.getAuthor();
+		assertEquals(2, authors.size());
+		final AuthorType bill = (AuthorType) authors.get(0);
+		final AuthorType bob = (AuthorType) authors.get(1);
+		assertSame(hi.getAuthor(), bill);
+		assertSame(helloAgain.getAuthor(), bob);
+
+		final String xml2 = getBooklist(true, false);
+		EventDetector detector2 = new EventDetector();
+		unmarshaller.setEventHandler(detector2);
+		unmarshaller.unmarshal(new InputSource(new StringReader(xml2)));
+		assertTrue(!detector2.isSuccess());
+		assertEquals(ValidationEvents.EVENT_IDREF_UNDECLARED, detector2.getEvent().getErrorCode());
+
+		final String xml3 = getBooklist(false, true);
+		EventDetector detector3 = new EventDetector();
+		unmarshaller.setEventHandler(detector3);
+		unmarshaller.unmarshal(new InputSource(new StringReader(xml3)));
+		assertTrue(!detector3.isSuccess());
+		assertEquals(ValidationEvents.EVENT_DUPLICATE_ID, detector3.getEvent().getErrorCode());
+	}
+
+	private String getBooklist(boolean pUndeclaredId, boolean pDuplicateId) {
+		String result =
+			"<booklist xmlns='http://ws.apache.org/jaxme/test/jira/jaxme58'>\n"
+			+ "  <book title='hi' author='a1'/>\n"
+			+ "  <book title='hello again' author='a2'/>\n";
+		if (pUndeclaredId) {
+			result += "  <book title='hello there!' author='a3'/>\n";
+		}
+		result +=
+			"  <author id='a1' name='Bill'/>\n"
+			+ "  <author id='a2' name='Bob'/>\n";
+		if (pDuplicateId) {
+			result += "  <author id='a2' name='Ben'/>\n";
+		}
+		result += "</booklist>\n";
+		return result;
+	}
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/ValidationEvents.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/ValidationEvents.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/ValidationEvents.java	(working copy)
@@ -26,80 +26,88 @@
 	 * been used.
 	 */
 	public static final String EVENT_CHOICE_GROUP_REUSE = "JM_EVENT_CHOICE_GROUP_REUSE";
+	
+	/** <p>A processing instruction was found. JaxMe doesn't know
+	 * how to handle processing instruction, thus they are treated
+	 * as a validation event, possibly throwing an exception.</p>
+	 * <p>This behaviour is questionable. It may very well be changed
+	 * at a later time, if another way of handling processing
+	 * instructions is defined. However, if we throw an event now,
+	 * the possible change is upwards compatible.</p>
+	 */
+	public static final String EVENT_PROCESSING_INSTRUCTION = "JM_EVENT_PROCESSING_INSTRUCTION";
+	
+	/** <p>A skipped entity was found. JaxMe doesn't know
+	 * how to handle skipped entities, thus they are treated
+	 * as a validation event, possibly throwing an exception.</p>
+	 * <p>This behaviour is questionable. It may very well be changed
+	 * at a later time, if another way of handling skipped
+	 * entities is defined. However, if we throw an event now,
+	 * the possible change is upwards compatible.</p>
+	 */
+	public static final String EVENT_SKIPPED_ENTITY = "JM_EVENT_SKIPPED_ENTITY";
+	
+	/** <p>Unexpected textual contents have been found. For example,
+	 * a sequence must not have embedded text, because it would have
+	 * mixed content otherwise. Textual content is ignored, if it
+	 * consists of whitespace characters only.</p>
+	 */
+	public static final String EVENT_UNEXPECTED_TEXTUAL_CONTENTS = "JM_EVENT_UNEXPECTED_TEXTUAL_CONTENTS";
+	
+	/** <p>An unexpected child was found in an atomic element or in a
+	 * complex element with simple content.</p>
+	 */
+	public static final String EVENT_UNEXPECTED_CHILD_ELEMENT = "JM_EVENT_UNEXPECTED_CHILD_ELEMENT";
+	
+	/**A childs of an all group was used more than once.
+	 */
+	public static final String EVENT_ALL_GROUP_REUSE = "JM_EVENT_ALL_GROUP_REUSE";
+	
+	/** <p>A child element was not expected at this place. For example,
+	 * in the case of a choice, this may indicate that more than one
+	 * of the possible elements have been found. In the case of a
+	 * sequence, this can indicate a mismatch in the order of the
+	 * child elements.</p>
+	 */
+	public static final String EVENT_UNEXPECTED_CHILD_STATE = "JM_EVENT_UNEXPECTED_CHILD_STATE";
+	
+	/** <p>A complex elements child is unknown. A possible reason
+	 * is an error in the child elements name.</p>
+	 */
+	public static final String EVENT_ADDITIONAL_CHILD_ELEMENT = "JM_EVENT_ADDITIONAL_CHILD_ELEMENT";
+	
+	/** <p>An element occurred more than expected. In other words,
+	 * the elements <code>maxOccurs</code> facet was violated.</p>
+	 */
+	public static final String EVENT_MULTIPLE_OCCURRENCIES = "JM_EVENT_MULTIPLE_OCCURRENCIES";
+	
+	/** <p>The root elements type was wrong.</p>
+	 */
+	public static final String EVENT_WRONG_ROOT_ELEMENT = "JM_EVENT_WRONG_ROOT_ELEMENT";
+	
+	/** <p>An element or attribute value was invalid. For example, in the
+	 * case of a dateTime instance, this may indicate an unparseable date.</p>
+	 */
+	public static final String EVENT_ILLEGAL_VALUE = "JM_EVENT_ILLEGAL_VALUE";
+	
+	/** <p>An attribute was unknown.</p>
+	 */
+	public static final String EVENT_UNKNOWN_ATTRIBUTE = "JM_EVENT_UNKNOWN_ATTRIBUTE";
+	
+	/** <p>An attribute with an invalid namespace was detected in an
+	 * element with an "anyAttribute" declaration.</p>
+	 */
+	public static final String EVENT_UNKNOWN_ANY_ATTRIBUTE = "JM_EVENT_UNKNOWN_ANY_ATTRIBUTE";
+	
+	/** Some of an elements child are missing.
+	 */
+	public static final String EVENT_PREMATURE_END_ELEMENT = "JM_EVENT_PREMATURE_END_ELEMENT";
 
-/** <p>A processing instruction was found. JaxMe doesn't know
-   * how to handle processing instruction, thus they are treated
-   * as a validation event, possibly throwing an exception.</p>
-   * <p>This behaviour is questionable. It may very well be changed
-   * at a later time, if another way of handling processing
-   * instructions is defined. However, if we throw an event now,
-   * the possible change is upwards compatible.</p>
-   */
-  public static final String EVENT_PROCESSING_INSTRUCTION = "JM_EVENT_PROCESSING_INSTRUCTION";
+	/** Ad ID attribute was declared twice.
+	 */
+	public static final String EVENT_DUPLICATE_ID = "JM_EVENT_DUPLICATE_ID";
 
-  /** <p>A skipped entity was found. JaxMe doesn't know
-   * how to handle skipped entities, thus they are treated
-   * as a validation event, possibly throwing an exception.</p>
-   * <p>This behaviour is questionable. It may very well be changed
-   * at a later time, if another way of handling skipped
-   * entities is defined. However, if we throw an event now,
-   * the possible change is upwards compatible.</p>
-   */
-  public static final String EVENT_SKIPPED_ENTITY = "JM_EVENT_SKIPPED_ENTITY";
-
-  /** <p>Unexpected textual contents have been found. For example,
-   * a sequence must not have embedded text, because it would have
-   * mixed content otherwise. Textual content is ignored, if it
-   * consists of whitespace characters only.</p>
-   */
-  public static final String EVENT_UNEXPECTED_TEXTUAL_CONTENTS = "JM_EVENT_UNEXPECTED_TEXTUAL_CONTENTS";
-
-  /** <p>An unexpected child was found in an atomic element or in a
-   * complex element with simple content.</p>
-   */
-  public static final String EVENT_UNEXPECTED_CHILD_ELEMENT = "JM_EVENT_UNEXPECTED_CHILD_ELEMENT";
-
-  /**A childs of an all group was used more than once.
-   */
-  public static final String EVENT_ALL_GROUP_REUSE = "JM_EVENT_ALL_GROUP_REUSE";
-
-  /** <p>A child element was not expected at this place. For example,
-   * in the case of a choice, this may indicate that more than one
-   * of the possible elements have been found. In the case of a
-   * sequence, this can indicate a mismatch in the order of the
-   * child elements.</p>
-   */
-  public static final String EVENT_UNEXPECTED_CHILD_STATE = "JM_EVENT_UNEXPECTED_CHILD_STATE";
-
-  /** <p>A complex elements child is unknown. A possible reason
-   * is an error in the child elements name.</p>
-   */
-  public static final String EVENT_ADDITIONAL_CHILD_ELEMENT = "JM_EVENT_ADDITIONAL_CHILD_ELEMENT";
-
-  /** <p>An element occurred more than expected. In other words,
-   * the elements <code>maxOccurs</code> facet was violated.</p>
-   */
-  public static final String EVENT_MULTIPLE_OCCURRENCIES = "JM_EVENT_MULTIPLE_OCCURRENCIES";
-
-  /** <p>The root elements type was wrong.</p>
-   */
-  public static final String EVENT_WRONG_ROOT_ELEMENT = "JM_EVENT_WRONG_ROOT_ELEMENT";
-
-  /** <p>An element or attribute value was invalid. For example, in the
-   * case of a dateTime instance, this may indicate an unparseable date.</p>
-   */
-  public static final String EVENT_ILLEGAL_VALUE = "JM_EVENT_ILLEGAL_VALUE";
-
-  /** <p>An attribute was unknown.</p>
-   */
-  public static final String EVENT_UNKNOWN_ATTRIBUTE = "JM_EVENT_UNKNOWN_ATTRIBUTE";
-
-  /** <p>An attribute with an invalid namespace was detected in an
-   * element with an "anyAttribute" declaration.</p>
-   */
-  public static final String EVENT_UNKNOWN_ANY_ATTRIBUTE = "JM_EVENT_UNKNOWN_ANY_ATTRIBUTE";
-
-  /** Some of an elements child are missing.
-   */
-  public static final String EVENT_PREMATURE_END_ELEMENT = null;
+    /** An IDREF attributes value was never declared as ID.
+     */
+    public static final String EVENT_IDREF_UNDECLARED = "JM_EVENT_IDREF_UNDECLARED";
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMElement.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMElement.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/JMElement.java	(working copy)
@@ -12,7 +12,6 @@
  * 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;
 
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMSAXDriverController.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMSAXDriverController.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMSAXDriverController.java	(working copy)
@@ -36,9 +36,9 @@
  */
 public class JMSAXDriverController {
 	private static final Attributes ZERO_ATTRIBUTES = new AttributesImpl();
-	private final JMMarshallerImpl marshaller;
-	private final DatatypeConverterInterface converter;
-	private final ContentHandler target;
+	private JMMarshallerImpl marshaller;
+	private DatatypeConverterInterface converter;
+	private ContentHandler target;
     private final NamespaceSupport nss = new NamespaceSupport();
 	private int cnt;
 
@@ -61,9 +61,9 @@
 		return nss;
     }
 
-	/** Creates a new instance with the given marshaller and target.
+	/** Initializes the controller by setting marshaller and target.
 	 */
-	public JMSAXDriverController(JMMarshallerImpl pMarshaller, ContentHandler pTarget) throws SAXException {
+	public void init(JMMarshallerImpl pMarshaller, ContentHandler pTarget) throws SAXException {
 		marshaller = pMarshaller;
 		target = pTarget;
 		converter = marshaller.getDatatypeConverter();
@@ -260,6 +260,8 @@
 		}
 	}
 
+	/** Fires a {@link javax.xml.bind.PrintConversionEvent}.
+	 */
 	public void printConversionEvent(Object pObject, String pMsg, Exception pException) throws SAXException {
 		ValidationEventHandler handler = getJMMarshaller().getEventHandler();
 		if (handler != null) {
@@ -269,6 +271,17 @@
 				return;
 			}
 		}
-		throw new SAXException(pMsg, pException);
+		if (pException instanceof SAXException) {
+			throw (SAXException) pException;
+		} else {
+			throw new SAXException(pMsg, pException);
+		}
 	}
+
+	/** Returns an ID for the object <code>pObject</code>.
+	 * The default implementation returns null. This method
+	 * is being overwritten by subclasses.
+	 * @param pObject The object for which an ID is being queried.
+	 */
+	public String getXsIdAttribute(Object pObject) { return null; }
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMMarshallerImpl.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMMarshallerImpl.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMMarshallerImpl.java	(working copy)
@@ -12,7 +12,6 @@
  * 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;
 
@@ -46,388 +45,388 @@
  * @version $Id$
  */
 public class JMMarshallerImpl extends JMControllerImpl implements JMMarshaller {
-  /** Default value for {@link Marshaller#JAXB_ENCODING}.
-   * (UTF-8 encoding)
-   */
-  public static final String DEFAULT_JAXB_ENCODING = "UTF-8";
+	/** Default value for {@link Marshaller#JAXB_ENCODING}.
+	 * (UTF-8 encoding)
+	 */
+	public static final String DEFAULT_JAXB_ENCODING = "UTF-8";
+	
+	/** Default value for {@link #JAXME_INDENTATION_STRING}: Two blanks.
+	 */
+	public static final String DEFAULT_JAXME_INDENTATION_STRING = "  ";
+	
+	/** Default value for {@link #JAXME_INDENTATION_SEPARATOR}.
+	 * ("\n", Line Feed)
+	 */
+	public static final String DEFAULT_JAXME_INDENTATION_SEPARATOR = "\n";
+	
+	/** Property name for setting the String used to indent
+	 * the formatted output by one level.
+	 * ("jaxme.indentation.string")
+	 * Defaults to {@link #DEFAULT_JAXME_INDENTATION_STRING}.
+	 *
+	 * @see #setIndentationString
+	 * @see #getIndentationString
+	 */
+	public static final String JAXME_INDENTATION_STRING = "jaxme.indentation.string";
+	
+	/** Property name for setting the String used as a
+	 * line separator in the formatted output.
+	 * ("jaxme.indentation.separator")
+	 *
+	 * @see #setIndentationSeparator
+	 * @see #getIndentationSeparator
+	 */
+	public static final String JAXME_INDENTATION_SEPARATOR = "jaxme.indentation.separator";
+	
+	/** Property name for choosing whether the marshalled
+	 * output should contain an XML declaration. The methods
+	 * {@link #marshal(Object, OutputStream)} and
+	 * {@link #marshal(Object, Writer)} recognize
+	 * requests for XML declarations.
+	 *
+	 * @see #setXmlDeclaration(boolean)
+	 * @see #getXmlDeclaration
+	 */
+	public static final String JAXME_XML_DECLARATION = "jaxme.xml.declaration";
+	
+	/** Property name for a SAX {@link ContentHandler} which is able to
+	 * marshal a SAX stream into a character stream. The property value is
+	 * an instance of {@link Class} implementing {@link XMLWriter}.
+	 */
+	public static final String JAXME_XML_WRITER = "jaxme.xml.writer";
+	
+	private static final Class xmlWriterClassDefault;
+	
+	static {
+		Class c;
+		try {
+			c = Class.forName("org.apache.ws.jaxme.impl.CharSetXMLWriter");
+		} catch (Exception e) {
+			c = XMLWriterImpl.class;
+		}
+		xmlWriterClassDefault = c;
+	}
+	
+	private String encoding = DEFAULT_JAXB_ENCODING;
+	private boolean indentation = true;
+	private String indentationString = DEFAULT_JAXME_INDENTATION_STRING;
+	private String indentationSeparator = DEFAULT_JAXME_INDENTATION_SEPARATOR;
+	private boolean xmlDeclaration = true;
+	private Class xmlWriterClass;
+	private String noNamespaceSchemaLocation, schemaLocation;
+	
+	/** Sets the controllers encoding; to be used in
+	 * marshalling. Defaults to {@link #DEFAULT_JAXB_ENCODING}.
+	 *
+	 * @param pEncoding Suggested encoding or null to restore
+	 *    the default
+	 */
+	public void setEncoding(String pEncoding) throws PropertyException {
+		if (pEncoding == null) {
+			pEncoding = DEFAULT_JAXB_ENCODING;
+		}
+		encoding = pEncoding;
+	}
+	
+	/** Returns the controllers encoding; to be used in
+	 * marshalling. Defaults to {@link #DEFAULT_JAXB_ENCODING}.
+	 */
+	public String getEncoding() { return encoding; }
+	
+	/** Sets the controllers class implementing {@link XMLWriter}.
+	 * Defaults to {@link XMLWriterImpl}.
+	 *
+	 * @param pClass A class implementing {@link XMLWriterImpl} or
+	 *   null to restore the default.
+	 */
+	public void setXMLWriterClass(Class pClass) throws PropertyException {
+		if (pClass == null) {
+			// Restore
+			xmlWriterClass = null;
+		} else if (XMLWriter.class.isAssignableFrom(pClass)  &&  !pClass.isInterface()) {
+			xmlWriterClass = pClass;
+		} else {
+			throw new PropertyException("The class " + pClass.getName() + " is not implementing " + XMLWriter.class.getName());
+		}
+	}
+	
+	/** <p>Returns the controllers class implementing {@link XMLWriter}.
+	 * Defaults to {@link XMLWriterImpl}.</p>
+	 */
+	public Class getXMLWriterClass() {
+		return xmlWriterClass == null ? xmlWriterClassDefault : xmlWriterClass;
+	}
+	
+	/** <p>Sets whether XML documents generated by the controller
+	 * ought to be formatted. Defaults to true.</p>
+	 */
+	public void setIndentation(boolean pIndentation) {
+		indentation = pIndentation;
+	}
+	
+	/** <p>Returns whether XML documents generated by the controller
+	 * ought to be formatted. Defaults to true.</p>
+	 */
+	public boolean getIndentation() {
+		return indentation;
+	}
+	
+	/** <p>Sets whether the methods <code>marshal(Object, Writer)</code>
+	 * and <code>marshal(Object, OutputStream)</code> ought to emit an
+	 * XML declaration.</p>
+	 */
+	public void setXmlDeclaration(boolean pDeclaration) {
+		xmlDeclaration = pDeclaration;
+	}
+	
+	/** <p>Returns whether the methods <code>marshal(Object, Writer)</code>
+	 * and <code>marshal(Object, OutputStream)</code> ought to emit an
+	 * XML declaration.</p>
+	 */
+	public boolean getXmlDeclaration() { return xmlDeclaration; }
+	
+	/** <p>Sets the string used to indent one level. Defaults to
+	 * {@link #DEFAULT_JAXME_INDENTATION_STRING}. Equivalent to
+	 * <code>setProperty(JAXME_INDENTATION_STRING, pStr)</code>.</p>
+	 *
+	 * @see #DEFAULT_JAXME_INDENTATION_STRING
+	 * @see #setProperty
+	 * @see #getProperty
+	 */
+	public void setIndentationString(String pStr) { indentationString = pStr; }
+	
+	/** <p>Returns the string used to indent one level. Defaults to
+	 * {@link #DEFAULT_JAXME_INDENTATION_STRING}. Equivalent to
+	 * <code>getProperty(JAXME_INDENTATION_STRING)</code>.</p>
+	 *
+	 * @see #DEFAULT_JAXME_INDENTATION_STRING
+	 * @see #setProperty
+	 * @see #getProperty
+	 */
+	public String getIndentationString() { return indentationString; }
+	
+	/** <p>Sets the string used as a line separator. Defaults to
+	 * {@link #DEFAULT_JAXME_INDENTATION_SEPARATOR}. Equivalent to
+	 * <code>setProperty(JAXME_INDENTATION_SEPARATOR, pStr)</code>.</p>
+	 *
+	 * @see #DEFAULT_JAXME_INDENTATION_SEPARATOR
+	 * @see #setProperty
+	 * @see #getProperty
+	 */
+	public void setIndentationSeparator(String pStr) { indentationSeparator = pStr; }
+	
+	/** <p>Returns the string used as a line separator. Defaults to
+	 * {@link #DEFAULT_JAXME_INDENTATION_SEPARATOR}. Equivalent to
+	 * <code>getProperty(JAXME_INDENTATION_SEPARATOR)</code>.</p>
+	 *
+	 * @see #DEFAULT_JAXME_INDENTATION_SEPARATOR
+	 * @see #setProperty
+	 * @see #getProperty
+	 */
+	public String getIndentationSeparator() { return indentationSeparator; }
+	
+	/** <p>Sets the schema location. The marshaller will use this to
+	 * create an attribute <code>xsi:schemaLocation</code>. Equivalent
+	 * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
+	 * Defaults to null, in which case the attribute isn't created.</p>
+	 * @see Marshaller#JAXB_SCHEMA_LOCATION
+	 * @see #setProperty(String, Object)
+	 * @see #getSchemaLocation()
+	 */
+	public void setSchemaLocation(String pValue) throws PropertyException {
+		if (pValue != null  &&  noNamespaceSchemaLocation != null) {
+			throw new PropertyException("The properties schemaLocation and noNamespaceSchemaLocation are mutually exclusive.");
+		}
+		schemaLocation = pValue;
+	}
+	
+	/** <p>Returns the schema location. The marshaller will use this to
+	 * create an attribute <code>xsi:schemaLocation</code>. Equivalent
+	 * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
+	 * Defaults to null, in which case the attribute isn't created.</p>
+	 * @see Marshaller#JAXB_SCHEMA_LOCATION
+	 * @see #setProperty(String, Object)
+	 * @see #setSchemaLocation(String)
+	 */
+	public String getSchemaLocation() {
+		return schemaLocation;
+	}
+	
+	/** <p>Sets the schema location without namespace. The marshaller
+	 * will use this to create an attribute <code>xsi:noNamespaceSchemaLocation</code>.
+	 * Equivalent to <code>setProperty(JAXB_NO_NAMESPACE_SCHEMA_LOCATION,
+	 * pValue)</code>. Defaults to null, in which case the attribute isn't
+	 * created.</p>
+	 * @see Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
+	 * @see #setProperty(String, Object)
+	 * @see #getNoNamespaceSchemaLocation()
+	 */
+	public void setNoNamespaceSchemaLocation(String pValue) throws PropertyException {
+		if (pValue != null  &&  noNamespaceSchemaLocation != null) {
+			throw new PropertyException("The properties schemaLocation and noNamespaceSchemaLocation are mutually exclusive.");
+		}
+		noNamespaceSchemaLocation = pValue;
+	}
+	
+	/** <p>Returns the schema location. The marshaller will use this to
+	 * create an attribute <code>xsi:noNamespaceSchemaLocation</code>. Equivalent
+	 * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
+	 * Defaults to null, in which case the attribute isn't created.</p>
+	 * @see Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
+	 * @see #setProperty(String, Object)
+	 * @see #setNoNamespaceSchemaLocation(String)
+	 */
+	public String getNoNamespaceSchemaLocation() {
+		return noNamespaceSchemaLocation;
+	}
 
-  /** Default value for {@link #JAXME_INDENTATION_STRING}: Two blanks.
-   */
-  public static final String DEFAULT_JAXME_INDENTATION_STRING = "  ";
+	public void setProperty(String pProperty, Object pValue)
+			throws PropertyException {
+		if (pProperty.startsWith("jaxb.")) {
+			if (Marshaller.JAXB_ENCODING.equals(pProperty)) {
+				setEncoding((String) pValue);
+				return;
+			} else if (Marshaller.JAXB_FORMATTED_OUTPUT.equals(pProperty)) {
+				setIndentation(((Boolean) pValue).booleanValue());
+				return;
+			} else if (Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(pProperty)) {
+				setNoNamespaceSchemaLocation((String) pValue);
+				return;
+			} else if (Marshaller.JAXB_SCHEMA_LOCATION.equals(pProperty)) {
+				setSchemaLocation((String) pValue);
+				return;
+			}
+		} else if (pProperty.startsWith("jaxme.")) {
+			if (JAXME_XML_WRITER.equals(pProperty)) {
+				setXMLWriterClass((Class) pValue);
+				return;
+			} else if (JAXME_XML_DECLARATION.equals(pProperty)) {
+				setXmlDeclaration(((Boolean) pValue).booleanValue());
+				return;
+			} else if (JAXME_INDENTATION_SEPARATOR.equals(pProperty)) {
+				setIndentationSeparator((String) pValue);
+				return;
+			} else if (JAXME_INDENTATION_STRING.equals(pProperty)) {
+				setIndentationString((String) pValue);
+				return;
+			}
+		}
+		super.setProperty(pProperty, pValue);
+	}
 
-  /** Default value for {@link #JAXME_INDENTATION_SEPARATOR}.
-   * ("\n", Line Feed)
-   */
-  public static final String DEFAULT_JAXME_INDENTATION_SEPARATOR = "\n";
+	public Object getProperty(String pProperty) throws PropertyException {
+		if (pProperty.startsWith("jaxb.")) {
+			if (Marshaller.JAXB_ENCODING.equals(pProperty)) {
+				return getEncoding();
+			} else if (Marshaller.JAXB_FORMATTED_OUTPUT.equals(pProperty)) {
+				return new Boolean(getIndentation());
+			}
+		} else if (pProperty.startsWith("jaxme.")) {
+			if (JAXME_INDENTATION_STRING.equals(pProperty)) {
+				return getIndentationString();
+			} else if (JAXME_XML_WRITER.equals(pProperty)) {
+				return getXMLWriterClass();
+			} else if (JAXME_XML_DECLARATION.equals(pProperty)) {
+				return getEncoding();
+			} else if (JAXME_INDENTATION_SEPARATOR.equals(pProperty)) {
+				return getIndentationSeparator();
+			}
+		}
+		return super.getProperty(pProperty);
+	}
 
-  /** Property name for setting the String used to indent
-   * the formatted output by one level.
-   * ("jaxme.indentation.string")
-   * Defaults to {@link #DEFAULT_JAXME_INDENTATION_STRING}.
-   *
-   * @see #setIndentationString
-   * @see #getIndentationString
-   */
-  public static final String JAXME_INDENTATION_STRING = "jaxme.indentation.string";
+	/* Marshaller methods
+	 */
+	public void marshal(Object pObject, OutputStream pStream) throws JAXBException {
+		Writer writer;
+		try {
+			writer = new OutputStreamWriter(pStream, getEncoding());
+		} catch(UnsupportedEncodingException e) {
+			throw new MarshalException("Unsupported encoding: " + getEncoding(), e);
+		}
+		marshal(pObject, writer);
+		try {
+			writer.close();
+		} catch (IOException e) {
+			throw new MarshalException(e);
+		}
+	}
 
-  /** Property name for setting the String used as a
-   * line separator in the formatted output.
-   * ("jaxme.indentation.separator")
-   *
-   * @see #setIndentationSeparator
-   * @see #getIndentationSeparator
-   */
-  public static final String JAXME_INDENTATION_SEPARATOR = "jaxme.indentation.separator";
+	public void marshal(Object pObject, ContentHandler pHandler) throws JAXBException {
+		JMElement element = (JMElement) pObject;
+		QName qName = element.getQName();
+		try {
+			JMManager manager = getJAXBContextImpl().getManager(qName);
+			JMSAXDriver driver = manager.getDriver();
+			JMSAXDriverController controller = manager.getDriverController();
+			controller.init(this, pHandler);
+			controller.marshal(driver, qName.getPrefix(), qName.getNamespaceURI(), qName.getLocalPart(), element);
+		} catch (SAXException e) {
+			throw new MarshalException(e);
+		}
+	}
 
-  /** Property name for choosing whether the marshalled
-   * output should contain an XML declaration. The methods
-   * {@link #marshal(Object, OutputStream)} and
-   * {@link #marshal(Object, Writer)} recognize
-   * requests for XML declarations.
-   *
-   * @see #setXmlDeclaration(boolean)
-   * @see #getXmlDeclaration
-   */
-  public static final String JAXME_XML_DECLARATION = "jaxme.xml.declaration";
+	public void marshal(Object pObject, Writer pWriter) throws JAXBException {
+		if (getXmlDeclaration()) {
+			try {
+				pWriter.write("<?xml version='1.0' encoding='" + getEncoding() + "'?>");
+				if (getIndentation()) {
+					pWriter.write(getIndentationSeparator());
+				}
+			} catch (IOException e) {
+				throw new MarshalException(e);
+			}
+		}
+		XMLWriter w;
+		Class c = getXMLWriterClass();
+		try {
+			w = (XMLWriter) c.newInstance();
+		} catch (Exception e) {
+			throw new JAXBException("Failed to instantiate XMLWriter class " + c.getName(), e);
+		}
+		w.init(this);
+		w.setWriter(pWriter);
+		marshal(pObject, w);
+	}
 
-  /** Property name for a SAX {@link ContentHandler} which is able to
-   * marshal a SAX stream into a character stream. The property value is
-   * an instance of {@link Class} implementing {@link XMLWriter}.
-   */
-  public static final String JAXME_XML_WRITER = "jaxme.xml.writer";
+	public void marshal(Object pObject, Node pNode) throws JAXBException {
+		DOMBuilder db = new DOMBuilder();
+		db.setTarget(pNode);
+		marshal(pObject, db);
+	}
 
-  private static final Class xmlWriterClassDefault;
+	public void marshal(Object pObject, Result pResult) throws JAXBException {
+		if (pResult instanceof SAXResult) {
+			ContentHandler ch = ((SAXResult) pResult).getHandler();
+			if (ch == null) {
+				throw new MarshalException("The SAXResult doesn't have its ContentHandler set.");
+			}
+			marshal(pObject, ch);
+		} else if (pResult instanceof StreamResult) {
+			StreamResult sr = (StreamResult) pResult;
+			Writer w = sr.getWriter();
+			if (w == null) {
+				OutputStream s = sr.getOutputStream();
+				if (s == null) {
+					throw new MarshalException("The StreamResult doesn't have its Writer or OutputStream set.");
+				}
+				marshal(pObject, s);
+			} else {
+				marshal(pObject, w);
+			}
+		} else if (pResult instanceof DOMResult) {
+			Node node = ((DOMResult) pResult).getNode();
+			if (node == null) {
+				throw new MarshalException("The DOMResult doesn't have its Node set.");
+			}
+			marshal(pObject, node);
+		} else {
+			throw new MarshalException("Unknown type of Result: " + pResult.getClass().getName() +
+			", only SAXResult, StreamResult and DOMResult are supported.");
+		}
+	}
 
-  static {
-    Class c;
-    try {
-        c = Class.forName("org.apache.ws.jaxme.impl.CharSetXMLWriter");
-    } catch (Exception e) {
-        c = XMLWriterImpl.class;
-    }
-    xmlWriterClassDefault = c;
-  }
-
-  private String encoding = DEFAULT_JAXB_ENCODING;
-  private boolean indentation = true;
-  private String indentationString = DEFAULT_JAXME_INDENTATION_STRING;
-  private String indentationSeparator = DEFAULT_JAXME_INDENTATION_SEPARATOR;
-  private boolean xmlDeclaration = true;
-  private Class xmlWriterClass;
-  private String noNamespaceSchemaLocation, schemaLocation;
-
-  /** Sets the controllers encoding; to be used in
-   * marshalling. Defaults to {@link #DEFAULT_JAXB_ENCODING}.
-   *
-   * @param pEncoding Suggested encoding or null to restore
-   *    the default
-   */
-  public void setEncoding(String pEncoding) throws PropertyException {
-  	if (pEncoding == null) {
-  	  pEncoding = DEFAULT_JAXB_ENCODING;
-    }
-    encoding = pEncoding;
-  }
-
-  /** Returns the controllers encoding; to be used in
-   * marshalling. Defaults to {@link #DEFAULT_JAXB_ENCODING}.
-   */
-  public String getEncoding() { return encoding; }
-
-  /** Sets the controllers class implementing {@link XMLWriter}.
-   * Defaults to {@link XMLWriterImpl}.
-   *
-   * @param pClass A class implementing {@link XMLWriterImpl} or
-   *   null to restore the default.
-   */
-  public void setXMLWriterClass(Class pClass) throws PropertyException {
-    if (pClass == null) {
-      // Restore
-      xmlWriterClass = null;
-    } else if (XMLWriter.class.isAssignableFrom(pClass)  &&  !pClass.isInterface()) {
-      xmlWriterClass = pClass;
-    } else {
-      throw new PropertyException("The class " + pClass.getName() + " is not implementing " + XMLWriter.class.getName());
-    }
-  }
-
-  /** <p>Returns the controllers class implementing {@link XMLWriter}.
-   * Defaults to {@link XMLWriterImpl}.</p>
-   */
-  public Class getXMLWriterClass() {
-    return xmlWriterClass == null ? xmlWriterClassDefault : xmlWriterClass;
-  }
-
-  /** <p>Sets whether XML documents generated by the controller
-   * ought to be formatted. Defaults to true.</p>
-   */
-  public void setIndentation(boolean pIndentation) {
-    indentation = pIndentation;
-  }
-
-  /** <p>Returns whether XML documents generated by the controller
-   * ought to be formatted. Defaults to true.</p>
-   */
-  public boolean getIndentation() {
-    return indentation;
-  }
-
-  /** <p>Sets whether the methods <code>marshal(Object, Writer)</code>
-   * and <code>marshal(Object, OutputStream)</code> ought to emit an
-   * XML declaration.</p>
-   */
-  public void setXmlDeclaration(boolean pDeclaration) {
-    xmlDeclaration = pDeclaration;
-  }
-
-  /** <p>Returns whether the methods <code>marshal(Object, Writer)</code>
-   * and <code>marshal(Object, OutputStream)</code> ought to emit an
-   * XML declaration.</p>
-   */
-  public boolean getXmlDeclaration() { return xmlDeclaration; }
-
-  /** <p>Sets the string used to indent one level. Defaults to
-   * {@link #DEFAULT_JAXME_INDENTATION_STRING}. Equivalent to
-   * <code>setProperty(JAXME_INDENTATION_STRING, pStr)</code>.</p>
-   *
-   * @see #DEFAULT_JAXME_INDENTATION_STRING
-   * @see #setProperty
-   * @see #getProperty
-   */
-  public void setIndentationString(String pStr) { indentationString = pStr; }
-
-  /** <p>Returns the string used to indent one level. Defaults to
-   * {@link #DEFAULT_JAXME_INDENTATION_STRING}. Equivalent to
-   * <code>getProperty(JAXME_INDENTATION_STRING)</code>.</p>
-   *
-   * @see #DEFAULT_JAXME_INDENTATION_STRING
-   * @see #setProperty
-   * @see #getProperty
-   */
-  public String getIndentationString() { return indentationString; }
-
-  /** <p>Sets the string used as a line separator. Defaults to
-   * {@link #DEFAULT_JAXME_INDENTATION_SEPARATOR}. Equivalent to
-   * <code>setProperty(JAXME_INDENTATION_SEPARATOR, pStr)</code>.</p>
-   *
-   * @see #DEFAULT_JAXME_INDENTATION_SEPARATOR
-   * @see #setProperty
-   * @see #getProperty
-   */
-  public void setIndentationSeparator(String pStr) { indentationSeparator = pStr; }
-
-  /** <p>Returns the string used as a line separator. Defaults to
-   * {@link #DEFAULT_JAXME_INDENTATION_SEPARATOR}. Equivalent to
-   * <code>getProperty(JAXME_INDENTATION_SEPARATOR)</code>.</p>
-   *
-   * @see #DEFAULT_JAXME_INDENTATION_SEPARATOR
-   * @see #setProperty
-   * @see #getProperty
-   */
-  public String getIndentationSeparator() { return indentationSeparator; }
-
-  /** <p>Sets the schema location. The marshaller will use this to
-   * create an attribute <code>xsi:schemaLocation</code>. Equivalent
-   * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
-   * Defaults to null, in which case the attribute isn't created.</p>
-   * @see Marshaller#JAXB_SCHEMA_LOCATION
-   * @see #setProperty(String, Object)
-   * @see #getSchemaLocation()
-   */
-  public void setSchemaLocation(String pValue) throws PropertyException {
-    if (pValue != null  &&  noNamespaceSchemaLocation != null) {
-      throw new PropertyException("The properties schemaLocation and noNamespaceSchemaLocation are mutually exclusive.");
-    }
-    schemaLocation = pValue;
-  }
-
-  /** <p>Returns the schema location. The marshaller will use this to
-   * create an attribute <code>xsi:schemaLocation</code>. Equivalent
-   * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
-   * Defaults to null, in which case the attribute isn't created.</p>
-   * @see Marshaller#JAXB_SCHEMA_LOCATION
-   * @see #setProperty(String, Object)
-   * @see #setSchemaLocation(String)
-   */
-  public String getSchemaLocation() {
-  	return schemaLocation;
-  }
-
-  /** <p>Sets the schema location without namespace. The marshaller
-   * will use this to create an attribute <code>xsi:noNamespaceSchemaLocation</code>.
-   * Equivalent to <code>setProperty(JAXB_NO_NAMESPACE_SCHEMA_LOCATION,
-   * pValue)</code>. Defaults to null, in which case the attribute isn't
-   * created.</p>
-   * @see Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
-   * @see #setProperty(String, Object)
-   * @see #getNoNamespaceSchemaLocation()
-   */
-  public void setNoNamespaceSchemaLocation(String pValue) throws PropertyException {
-    if (pValue != null  &&  noNamespaceSchemaLocation != null) {
-      throw new PropertyException("The properties schemaLocation and noNamespaceSchemaLocation are mutually exclusive.");
-    }
-    noNamespaceSchemaLocation = pValue;
-  }
-
-  /** <p>Returns the schema location. The marshaller will use this to
-   * create an attribute <code>xsi:noNamespaceSchemaLocation</code>. Equivalent
-   * to <code>setProperty(JAXB_SCHEMA_LOCATION, pValue)</code>.
-   * Defaults to null, in which case the attribute isn't created.</p>
-   * @see Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
-   * @see #setProperty(String, Object)
-   * @see #setNoNamespaceSchemaLocation(String)
-   */
-  public String getNoNamespaceSchemaLocation() {
-    return noNamespaceSchemaLocation;
-  }
-
-  public void setProperty(String pProperty, Object pValue)
-      throws PropertyException {
-    if (pProperty.startsWith("jaxb.")) {
-      if (Marshaller.JAXB_ENCODING.equals(pProperty)) {
-        setEncoding((String) pValue);
-        return;
-      } else if (Marshaller.JAXB_FORMATTED_OUTPUT.equals(pProperty)) {
-        setIndentation(((Boolean) pValue).booleanValue());
-        return;
-      } else if (Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(pProperty)) {
-      	setNoNamespaceSchemaLocation((String) pValue);
-        return;
-      } else if (Marshaller.JAXB_SCHEMA_LOCATION.equals(pProperty)) {
-      	setSchemaLocation((String) pValue);
-        return;
-      }
-    } else if (pProperty.startsWith("jaxme.")) {
-      if (JAXME_XML_WRITER.equals(pProperty)) {
-        setXMLWriterClass((Class) pValue);
-        return;
-      } else if (JAXME_XML_DECLARATION.equals(pProperty)) {
-        setXmlDeclaration(((Boolean) pValue).booleanValue());
-        return;
-      } else if (JAXME_INDENTATION_SEPARATOR.equals(pProperty)) {
-        setIndentationSeparator((String) pValue);
-        return;
-      } else if (JAXME_INDENTATION_STRING.equals(pProperty)) {
-        setIndentationString((String) pValue);
-        return;
-      }
-    }
-    super.setProperty(pProperty, pValue);
-  }
-
-  public Object getProperty(String pProperty) throws PropertyException {
-    if (pProperty.startsWith("jaxb.")) {
-      if (Marshaller.JAXB_ENCODING.equals(pProperty)) {
-        return getEncoding();
-      } else if (Marshaller.JAXB_FORMATTED_OUTPUT.equals(pProperty)) {
-        return new Boolean(getIndentation());
-      }
-    } else if (pProperty.startsWith("jaxme.")) {
-      if (JAXME_INDENTATION_STRING.equals(pProperty)) {
-        return getIndentationString();
-      } else if (JAXME_XML_WRITER.equals(pProperty)) {
-        return getXMLWriterClass();
-      } else if (JAXME_XML_DECLARATION.equals(pProperty)) {
-        return getEncoding();
-      } else if (JAXME_INDENTATION_SEPARATOR.equals(pProperty)) {
-        return getIndentationSeparator();
-      }
-    }
-    return super.getProperty(pProperty);
-  }
-
-
-  /* Marshaller methods
-   */
-  public void marshal(Object pObject, OutputStream pStream) throws JAXBException {
-    Writer writer;
-    try {
-      writer = new OutputStreamWriter(pStream, getEncoding());
-    } catch(UnsupportedEncodingException e) {
-      throw new MarshalException("Unsupported encoding: " + getEncoding(), e);
-    }
-    marshal(pObject, writer);
-    try {
-      writer.close();
-    } catch (IOException e) {
-      throw new MarshalException(e);
-    }
-  }
-
-  public void marshal(Object pObject, ContentHandler pHandler) throws JAXBException {
-    JMElement element = (JMElement) pObject;
-	QName qName = element.getQName();
-    try {
-		JMManager manager = getJAXBContextImpl().getManager(qName);
-		JMSAXDriver driver = manager.getDriver();
-		JMSAXDriverController controller = new JMSAXDriverController(this, pHandler);
-		controller.marshal(driver, qName.getPrefix(), qName.getNamespaceURI(), qName.getLocalPart(), element);
-    } catch (SAXException e) {
-      throw new MarshalException(e);
-    }
-  }
-
-  public void marshal(Object pObject, Writer pWriter) throws JAXBException {
-    if (getXmlDeclaration()) {
-      try {
-        pWriter.write("<?xml version='1.0' encoding='" + getEncoding() + "'?>");
-        if (getIndentation()) {
-          pWriter.write(getIndentationSeparator());
-        }
-      } catch (IOException e) {
-        throw new MarshalException(e);
-      }
-    }
-    XMLWriter w;
-    Class c = getXMLWriterClass();
-    try {
-      w = (XMLWriter) c.newInstance();
-    } catch (Exception e) {
-      throw new JAXBException("Failed to instantiate XMLWriter class " + c.getName(), e);
-    }
-    w.init(this);
-    w.setWriter(pWriter);
-    marshal(pObject, w);
-  }
-
-  public void marshal(Object pObject, Node pNode) throws JAXBException {
-    DOMBuilder db = new DOMBuilder();
-    db.setTarget(pNode);
-    marshal(pObject, db);
-  }
-
-  public void marshal(Object pObject, Result pResult) throws JAXBException {
-    if (pResult instanceof SAXResult) {
-      ContentHandler ch = ((SAXResult) pResult).getHandler();
-      if (ch == null) {
-        throw new MarshalException("The SAXResult doesn't have its ContentHandler set.");
-      }
-      marshal(pObject, ch);
-    } else if (pResult instanceof StreamResult) {
-      StreamResult sr = (StreamResult) pResult;
-      Writer w = sr.getWriter();
-      if (w == null) {
-        OutputStream s = sr.getOutputStream();
-        if (s == null) {
-          throw new MarshalException("The StreamResult doesn't have its Writer or OutputStream set.");
-        }
-        marshal(pObject, s);
-      } else {
-        marshal(pObject, w);
-      }
-    } else if (pResult instanceof DOMResult) {
-      Node node = ((DOMResult) pResult).getNode();
-      if (node == null) {
-        throw new MarshalException("The DOMResult doesn't have its Node set.");
-      }
-      marshal(pObject, node);
-    } else {
-      throw new MarshalException("Unknown type of Result: " + pResult.getClass().getName() +
-                                  ", only SAXResult, StreamResult and DOMResult are supported.");
-    }
-  }
-
-  public Node getNode(java.lang.Object contentTree) throws JAXBException {
-    throw new UnsupportedOperationException("JaxMe doesn't support live DOM views");
-  }
+	public Node getNode(java.lang.Object contentTree) throws JAXBException {
+		throw new UnsupportedOperationException("JaxMe doesn't support live DOM views");
+	}
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMUnmarshallerHandlerImpl.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMUnmarshallerHandlerImpl.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JMUnmarshallerHandlerImpl.java	(working copy)
@@ -17,17 +17,22 @@
 package org.apache.ws.jaxme.impl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import javax.xml.bind.DatatypeConverterInterface;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.ValidationEvent;
 import javax.xml.bind.ValidationEventHandler;
 import javax.xml.bind.helpers.ParseConversionEventImpl;
+import javax.xml.bind.helpers.PrintConversionEventImpl;
 import javax.xml.bind.helpers.ValidationEventImpl;
 import javax.xml.bind.helpers.ValidationEventLocatorImpl;
 import javax.xml.namespace.QName;
 
+import org.apache.ws.jaxme.IDREF;
 import org.apache.ws.jaxme.JMManager;
 import org.apache.ws.jaxme.JMUnmarshaller;
 import org.apache.ws.jaxme.JMUnmarshallerHandler;
@@ -74,6 +79,8 @@
     private final StringBuffer sb = new StringBuffer();
 	private Observer observer;
 	private Object result;
+	private final Map idMap = new HashMap();
+	private final List idrefs = new ArrayList();
 
     public int getLevel() { return level; }
 
@@ -131,6 +138,10 @@
     }
 
     public void endDocument() throws SAXException {
+    	for (Iterator i = idrefs.iterator(); i.hasNext();) {
+			IDREF idref = (IDREF) i.next();
+			idref.validate(idMap);
+		}
     }
 
     public void startPrefixMapping(String pPrefix, String pURI) throws SAXException {
@@ -313,6 +324,9 @@
 	 */
 	public void parseConversionEvent(String pMsg, Exception pException) throws SAXException {
 		ParseConversionEventImpl event = new ParseConversionEventImpl(ValidationEvent.FATAL_ERROR, pMsg, null);
+		if (locator != null) {
+			event.setLocator(new ValidationEventLocatorImpl(locator));
+		}
 		handleEvent(event, pException);
 	}
 
@@ -320,15 +334,22 @@
 	 */
 	public void validationEvent(int pSeverity, String pMsg, String pErrorCode,
 								Exception pException) throws SAXException {
+		validationEvent(pSeverity, pMsg, pErrorCode, pException, locator);
+	}
+
+	/** Posts a {@link ValidationEvent}.
+	 */
+	public void validationEvent(int pSeverity, String pMsg, String pErrorCode,
+								Exception pException, Locator pLocator) throws SAXException {
 		org.apache.ws.jaxme.impl.ValidationEventImpl event = new org.apache.ws.jaxme.impl.ValidationEventImpl(pSeverity, pMsg, null);
 		event.setErrorCode(pErrorCode);
+		if (pLocator != null) {
+			event.setLocator(new ValidationEventLocatorImpl(pLocator));
+		}
 		handleEvent(event, pException);
 	}
 
 	private void handleEvent(ValidationEventImpl pEvent, Exception pException) throws SAXException {
-		if (locator != null) {
-			pEvent.setLocator(new ValidationEventLocatorImpl(locator));
-		}
 		if (pException != null) {
 			pEvent.setLinkedException(pException);
 		}
@@ -339,6 +360,9 @@
 			throw new SAXException(e);
 		}
 		if (eventHandler == null  ||  !eventHandler.handleEvent(pEvent)) {
+			if (pException != null  &&  pException instanceof SAXParseException) {
+				throw (SAXParseException) pException;
+			}
 			String msg = pEvent.getMessage();
 			if (pEvent instanceof org.apache.ws.jaxme.impl.ValidationEventImpl) {
 				String errorCode = ((org.apache.ws.jaxme.impl.ValidationEventImpl) pEvent).getErrorCode();
@@ -394,4 +418,25 @@
 			state = STATE_GROUP;
 		}
 	}
+	
+	/**
+	 * @param id XML ID attribute of JAXB object
+	 * @param jaxbObject the JAXB object
+	 * @throws SAXException if duplicate ID
+	 */
+	public boolean addId(String id, Object jaxbObject) throws SAXException {
+		if (idMap.containsKey(id)) {
+			return false;
+		}
+		idMap.put(id, jaxbObject);
+		return true;
+	}
+	
+	/**
+	 * @param idref
+	 */
+	public void addIdref(IDREF idref) {
+		idrefs.add(idref);
+	}
+	
 }
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/Configuration.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/Configuration.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/Configuration.java	(working copy)
@@ -77,6 +77,7 @@
     private Class elementClass;
     private Class handlerClass;
     private Class driverClass;
+    private Class driverControllerClass;
     private Class pmClass;
 	private String prefix;
     private Map properties;
@@ -189,13 +190,44 @@
 		try {
 			return elementClass.newInstance();
 		} catch (InstantiationException e) {
-			throw new SAXException("Unable to instantiate handler class "
-								   + jmUnmarshallerClass.getName(), e);
+			throw new SAXException("Unable to instantiate element class "
+								   + elementClass.getName(), e);
 		} catch (IllegalAccessException e) {
-			throw new SAXException("Illegal access to handler class "
-								   + jmUnmarshallerClass.getName(), e);
+			throw new SAXException("Illegal access to element class "
+								   + elementClass.getName(), e);
 		}
     }
+
+	public JMSAXDriverController getDriverController() throws SAXException {
+		try {
+			return (JMSAXDriverController) driverControllerClass.newInstance();
+		} catch (InstantiationException e) {
+			throw new SAXException("Unable to instantiate driver controller class "
+								   + driverControllerClass.getName(), e);
+		} catch (IllegalAccessException e) {
+			throw new SAXException("Illegal access to driver controller class "
+								   + driverControllerClass.getName(), e);
+		}
+	}
+
+	/** Returns the subclass of {@link JMSAXDriverController},
+	 * which is being used for marshalling this object.
+	 */
+	public Class getDriverControllerClass() {
+		return driverControllerClass;
+	}
+
+	/** Sets the subclass of {@link JMSAXDriverController},
+	 * which is being used for marshalling this object.
+	 */
+	public void setDriverControllerClass(String pDriverControllerClass) throws ClassNotFoundException {
+		driverControllerClass = context.getClassLoader().loadClass(pDriverControllerClass);
+		if (!JMSAXDriverController.class.isAssignableFrom(driverControllerClass)) {
+			throw new IllegalStateException("The class " + driverControllerClass.getName()
+											+ " is not implementing "
+											+ JMSAXDriverController.class.getName());
+		}
+	}
   }
 
   /** <p>Creates a new Manager.</p>
Index: /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JAXBContextImpl.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JAXBContextImpl.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/jaxme/org/apache/ws/jaxme/impl/JAXBContextImpl.java	(working copy)
@@ -458,10 +458,13 @@
 	if (pManager.getDriverClass() == null) {
 		throw new IllegalStateException("Missing driver class for " + pManager.getQName());
 	}
+	if (pManager.getDriverControllerClass() == null) {
+		throw new IllegalStateException("Missing driver controller 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 +
Index: /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/Parameter.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/Parameter.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/Parameter.java	(working copy)
@@ -24,21 +24,32 @@
  * @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
  */
 public class Parameter implements DirectAccessible, IndentedObject {
-  private final JavaQName type;
-  private final String name;
-  private boolean isNullable = true;
-
-  public Parameter(JavaQName pType, String pName) {
-    type = pType;
-    name = pName;
-  }
-  public JavaQName getType() { return type; }
-  public String getName() { return name; }
-  public String toString() { return type.toString() + " " + name; }
-  public void write(IndentationEngine pEngine, IndentationTarget pTarget)
-      throws IOException {
-    pEngine.write(pTarget, getName());
-  }
-  public boolean isNullable() { return isNullable; }
-  public void setNullable(boolean pNullable) { isNullable = pNullable; }
+	private final JavaQName type;
+	private final String name;
+	private boolean isNullable = true;
+	private boolean isFinal;
+	
+	public Parameter(JavaQName pType, String pName) {
+		type = pType;
+		name = pName;
+	}
+	public JavaQName getType() { return type; }
+	public String getName() { return name; }
+	public String toString() { return type.toString() + " " + name; }
+	public void write(IndentationEngine pEngine, IndentationTarget pTarget)
+	throws IOException {
+		pEngine.write(pTarget, getName());
+	}
+	public boolean isNullable() { return isNullable; }
+	public void setNullable(boolean pNullable) { isNullable = pNullable; }
+	/** Sets, whether the parameter is final.
+	 */
+	public void setFinal(boolean pFinal) {
+		isFinal = pFinal;
+	}
+	/** Returns, whether the parameter is final.
+	 */
+	public boolean isFinal() {
+		return isFinal;
+	}
 }
Index: /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/JavaMethod.java
===================================================================
--- /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/JavaMethod.java	(revision 232222)
+++ /home/jwi/workspace/ws-jaxme/src/js/org/apache/ws/jaxme/js/JavaMethod.java	(working copy)
@@ -76,6 +76,9 @@
         pTarget.write(", ");
       }
       Parameter p = params[i];
+      if (p.isFinal()) {
+    	  pTarget.write("final ");
+      }
       pTarget.write(pTarget.asString(p.getType()) );
       pTarget.write(" ");
       pTarget.write(p.getName());
