Index: src/test/java/org/castor/util/TestHex.java
===================================================================
--- src/test/java/org/castor/util/TestHex.java	(revision 0)
+++ src/test/java/org/castor/util/TestHex.java	(revision 0)
@@ -0,0 +1,30 @@
+package org.castor.util;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Johan Lindquist
+ * @version $Revision$
+ */
+public class TestHex extends TestCase
+{
+
+    public void testEncodeDecode()
+    {
+        byte[] bytes = new byte[256];
+
+        new Random(1L).nextBytes(bytes);
+        final String encodedBytes = Hex.encode(bytes);
+        assertEquals("Bad encoded data","73d51abbd89cb8196f0efb6892f94d68fccc2c35f0b84609e5f12c55dd85aba8d5d9bef76808f3b572e5900112b81927ba5bb5f67e1bda28b4049bf0e4aed78db15d7bf2fc0c34e9a99de4ef3bc2b17c8137ad659878f9e93df1f658367aca286452474b9ef3765e24e9a88173724dddfb04b01dcceb0c8aead641c58dad569581baeea87c10d40a47902028e61cfdc243d9d16008aabc9fb77cc723a56017e14f1ce8b1698341734a6823ce02043e016b544901214a2ddab82fec85c0b9fe0549c475be5b887bb4b8995b24fb5c6846f88b527b4f9d4c1391f1678b23ba4f9c9cd7bc93eb5776f4f03675344864294661c5949faf17b130fcf6482f971a5500",encodedBytes);
+
+        final byte[] decodedBytes = Hex.decode(encodedBytes);
+
+        assertTrue("Bad decoded bytes", Arrays.equals(bytes,decodedBytes));
+
+
+    }
+
+}
Index: src/bugs/xml/bug423/mapping.xml
===================================================================
--- src/bugs/xml/bug423/mapping.xml	(revision 0)
+++ src/bugs/xml/bug423/mapping.xml	(revision 0)
@@ -0,0 +1,29 @@
+<?xml version="1.0" ?>
+<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
+        "http://castor.org/mapping.dtd">
+<mapping>
+
+    <class name="xml.bug423.Entity">
+
+        <map-to xml="entity"/>
+
+        <field name="elementBase64" type="bytes">
+            <bind-xml name="elementBase64" type="base64Binary"/>
+        </field>
+
+        <field name="attributeBase64" type="bytes">
+            <bind-xml name="attributeBase64" node="attribute" location="elementBase64" type="base64Binary"/>
+        </field>
+
+        <field name="elementHex" type="bytes">
+            <bind-xml name="elementHex" type="hexBinary"/>
+        </field>
+
+        <field name="attributeHex" type="bytes">
+            <bind-xml name="attributeHex" node="attribute" location="elementHex" type="hexBinary"/>
+        </field>
+
+    </class>
+
+</mapping>
+
Index: src/bugs/xml/bug423/README.txt
===================================================================
--- src/bugs/xml/bug423/README.txt	(revision 0)
+++ src/bugs/xml/bug423/README.txt	(revision 0)
@@ -0,0 +1,3 @@
+bug number: 423
+description: Handling of hex binary / base64 encoding 
+castor: version trunk
Index: src/bugs/xml/bug423/TestTemplate.java
===================================================================
--- src/bugs/xml/bug423/TestTemplate.java	(revision 0)
+++ src/bugs/xml/bug423/TestTemplate.java	(revision 0)
@@ -0,0 +1,88 @@
+package xml.bug423;
+
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.exolab.castor.mapping.Mapping;
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+import org.xml.sax.InputSource;
+
+/**
+ * @author Johan Lindquist
+ */
+public final class TestTemplate extends TestCase {
+
+    private static final String SAMPLE_FILE = "entity.xml";
+    private static final String MAPPING_FILE = "mapping.xml";
+
+    private static final byte[] EXPECTED_HEX_ELEMENT_ARRAY = new byte[]{0x01, 0x04, 0x03, 0x02, 0x01, 0x01};
+    private static final byte[] EXPECTED_HEX_ATTRIBUTE_ARRAY = new byte[]{0x01, 0x04, 0x03, 0x02, 0x01, 0x02};
+    private static final byte[] EXPECTED_BASE64_ELEMENT_ARRAY = new byte[]{104, -55, 0, 0};
+    private static final byte[] EXPECTED_BASE64_ATTRIBUTE_ARRAY = new byte[]{104, -55, 0, 0};
+    private static final String EXPECTED_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+            "<entity>\n" +
+            "    <elementBase64 attributeBase64=\"aMkAAA==\">aMkAAA==</elementBase64>\n" +
+            "    <elementHex>010403020101</elementHex>\n" +
+            "</entity>";
+
+
+    public TestTemplate() {
+        super();
+    }
+
+    public TestTemplate(final String name) {
+        super(name);
+    }
+
+    /**
+     * Test method.
+     * @throws Exception For any exception thrown.
+     */
+    public void testUnmarshalEntity() throws Exception {
+
+        Mapping mapping = new Mapping();
+        mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+        Unmarshaller unmarshaller = new Unmarshaller (Entity.class);
+        unmarshaller.setMapping(mapping);
+
+        Entity entity = (Entity) unmarshaller.unmarshal(new InputSource(getClass().getResource(SAMPLE_FILE).toExternalForm()));
+
+        assertNotNull (entity);
+
+        assertTrue("Invalid hex value in element", Arrays.equals(EXPECTED_HEX_ELEMENT_ARRAY,entity.getElementHex()));
+        assertTrue("Invalid hex value in attribute", Arrays.equals(EXPECTED_HEX_ATTRIBUTE_ARRAY, entity.getAttributeHex()));
+        assertTrue("Invalid base64 value in element", Arrays.equals(EXPECTED_BASE64_ELEMENT_ARRAY, entity.getElementBase64()));
+        assertTrue("Invalid base64 value in attribute", Arrays.equals(EXPECTED_BASE64_ATTRIBUTE_ARRAY, entity.getAttributeBase64()));
+    }
+
+    /**
+     * Test method.
+     * @throws Exception For any exception thrown.
+     */
+    public void testMarshalEntity() throws Exception {
+        Mapping mapping = new Mapping();
+        mapping.loadMapping(getClass().getResource(MAPPING_FILE).toExternalForm());
+
+        StringWriter stringWriter = new StringWriter();
+        Marshaller marshaller = new Marshaller (stringWriter);
+        marshaller.setMapping(mapping);
+
+        Entity entity = new Entity();
+        entity.setElementHex(EXPECTED_HEX_ELEMENT_ARRAY);
+        entity.setAttributeHex(EXPECTED_HEX_ATTRIBUTE_ARRAY);
+        entity.setElementBase64(EXPECTED_BASE64_ELEMENT_ARRAY);
+        entity.setAttributeBase64(EXPECTED_BASE64_ATTRIBUTE_ARRAY);
+        marshaller.marshal(entity);
+
+        String xml = stringWriter.toString();
+        assertEquals("XML marshalling produced invalid value",EXPECTED_XML.trim(),xml.trim());
+
+    }
+
+}
Index: src/bugs/xml/bug423/entity.xml
===================================================================
--- src/bugs/xml/bug423/entity.xml	(revision 0)
+++ src/bugs/xml/bug423/entity.xml	(revision 0)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<entity>
+    <elementHex attributeHex="010403020102">010403020101</elementHex>
+    <elementBase64 attributeBase64="aMkAAA==">aMkAAA==</elementBase64>
+</entity>
\ No newline at end of file
Index: src/bugs/xml/bug423/Entity.java
===================================================================
--- src/bugs/xml/bug423/Entity.java	(revision 0)
+++ src/bugs/xml/bug423/Entity.java	(revision 0)
@@ -0,0 +1,49 @@
+package xml.bug423;
+
+public final class Entity {
+
+    private byte[] _attributeHex;
+    private byte[] _attributeBase64;
+    private byte[] _elementHex;
+    private byte[] _elementBase64;
+   
+    public byte[] getAttributeHex()
+    {
+        return _attributeHex;
+    }
+
+    public void setAttributeHex(final byte[] attributeHex)
+    {
+        _attributeHex = attributeHex;
+    }
+
+    public byte[] getAttributeBase64()
+    {
+        return _attributeBase64;
+    }
+
+    public void setAttributeBase64(final byte[] attributeBase64)
+    {
+        _attributeBase64 = attributeBase64;
+    }
+
+    public byte[] getElementHex()
+    {
+        return _elementHex;
+    }
+
+    public void setElementHex(final byte[] elementHex)
+    {
+        _elementHex = elementHex;
+    }
+
+    public byte[] getElementBase64()
+    {
+        return _elementBase64;
+    }
+
+    public void setElementBase64(final byte[] elementBase64)
+    {
+        _elementBase64 = elementBase64;
+    }
+}
Index: src/main/java/org/exolab/castor/xml/UnmarshalHandler.java
===================================================================
--- src/main/java/org/exolab/castor/xml/UnmarshalHandler.java	(revision 6884)
+++ src/main/java/org/exolab/castor/xml/UnmarshalHandler.java	(working copy)
@@ -50,6 +50,7 @@
 //-- Castor imports
 import org.castor.mapping.BindingType;
 import org.castor.util.Base64Decoder;
+import org.castor.util.Hex;
 import org.exolab.castor.util.Configuration;
 import org.exolab.castor.util.ObjectFactory;
 import org.exolab.castor.util.DefaultObjectFactory;
@@ -801,10 +802,17 @@
                 if (str == null)
                     state.object = new byte[0];
                 else {
-                    //-- Base64 decoding
+                    //-- Base64/HexBinary decoding
+                    if ("hexBinary".equals(descriptor.getSchemaType()))
+                    {
+                        state.object = Hex.decode(str);
+                    }
+                    else
+                    {
                     state.object = Base64Decoder.decode(str);
                 }
             }
+            }
             else if (state.args != null) {
             	state.object = createInstance(state.type, state.args);
             }
@@ -827,12 +835,17 @@
                     value = toPrimitiveObject(cdesc.getFieldType(), (String)value, state.fieldDesc);
                 else {
                     Class valueType = cdesc.getFieldType();
-                    //-- handle base64
+                    //-- handle base64/hexBinary
                     if (valueType.isArray()
                             && (valueType.getComponentType() == Byte.TYPE)) {
+                        if ("hexBinary".equals(descriptor.getSchemaType())) {
+                            value = Hex.decode((String) value);
+                        }
+                        else {
                         value = Base64Decoder.decode((String) value);
                     }
                 }
+                }
 
 
                 try {
@@ -3023,10 +3036,17 @@
                 if (attValue == null)
                     value = new byte[0];
                 else {
-                    //-- Base64 decoding
+                    //-- Base64/hexbinary decoding
+                    if ("hexBinary".equals(descriptor.getSchemaType()))
+                    {
+                        value = Hex.decode(attValue);
+                    }
+                    else
+                    {
                     value = Base64Decoder.decode(attValue);
                 }
             }
+            }
             
             //-- check if the value is a QName that needs to
             //-- be resolved (ns:value -> {URI}value)
Index: src/main/java/org/exolab/castor/xml/Marshaller.java
===================================================================
--- src/main/java/org/exolab/castor/xml/Marshaller.java	(revision 6884)
+++ src/main/java/org/exolab/castor/xml/Marshaller.java	(working copy)
@@ -55,6 +55,7 @@
 import org.castor.mapping.MappingUnmarshaller;
 import org.castor.util.Base64Encoder;
 import org.castor.util.Messages;
+import org.castor.util.Hex;
 import org.exolab.castor.mapping.CollectionHandler;
 import org.exolab.castor.mapping.MapItem;
 import org.exolab.castor.mapping.Mapping;
@@ -1633,8 +1634,15 @@
                     char[] chars = null;
                     Class objType = obj.getClass();
                     if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
-                        //-- handle base64 content
+                        //-- handle base64/hexbinary content
+                        final String schemaType = descriptor.getSchemaType();
+                        if ("hexBinary".equals(schemaType)) {
+                            chars = new String(Hex.encode((byte[]) obj)).toCharArray();
+                        }
+                        else {
                         chars = Base64Encoder.encode((byte[]) obj);
+                        }
+
                     } else {
                         //-- all other types
                         String str = obj.toString();
@@ -1667,11 +1675,23 @@
             }
             // special case for byte[]
             else if (byteArray) {
-                //-- Base64Encoding
-                char[] chars = Base64Encoder.encode((byte[]) object);
-                try {
+                //-- Base64Encoding / HexBinary
+                String schemaType = descriptor.getSchemaType();
+                char[] chars = new char[0];
+                if ("hexBinary".equals(schemaType))
+                {
+                    chars = new String(Hex.encode((byte[]) object)).toCharArray();
+                }
+                else
+                {
+                    chars = Base64Encoder.encode((byte[]) object);
+                }
+                try
+                {
                     handler.characters(chars, 0, chars.length);
-                } catch (org.xml.sax.SAXException sx) {
+                }
+                catch (org.xml.sax.SAXException sx)
+                {
                     throw new MarshalException(sx);
                 }
             }
@@ -2329,9 +2349,15 @@
             //-- handle base64 content
             Class objType = value.getClass();
             if (objType.isArray() && (objType.getComponentType() == Byte.TYPE)) {
-                value = Base64Encoder.encode((byte[]) value);
+                final String schemaType = attDescriptor.getSchemaType();
+                if ("hexBinary".equals(schemaType)) {
+                    value = new String(Hex.encode((byte[]) value));
             }
+                else {
+                    value = new String(Base64Encoder.encode((byte[]) value));
         }
+            }
+        }
 
         if (value != null) {
             //check if the value is a QName that needs to
Index: src/main/java/org/castor/util/Hex.java
===================================================================
--- src/main/java/org/castor/util/Hex.java	(revision 0)
+++ src/main/java/org/castor/util/Hex.java	(revision 0)
@@ -0,0 +1,217 @@
+package org.castor.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+
+/** Hex encoder/decoder implementation shamelessly borrowed from BouncyCastle.
+ *
+ * @author Johan Lindquist
+ * @version $Revision$
+ */
+public class Hex
+{
+    protected static final byte[] encodingTable =
+            {
+                    (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
+                    (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
+            };
+
+    /*
+    * set up the decoding table.
+    */
+    protected static final byte[] decodingTable = new byte[128];
+
+    protected static void initialiseDecodingTable()
+    {
+        for (int i = 0; i < encodingTable.length; i++)
+        {
+            decodingTable[encodingTable[i]] = (byte) i;
+        }
+
+        decodingTable['A'] = decodingTable['a'];
+        decodingTable['B'] = decodingTable['b'];
+        decodingTable['C'] = decodingTable['c'];
+        decodingTable['D'] = decodingTable['d'];
+        decodingTable['E'] = decodingTable['e'];
+        decodingTable['F'] = decodingTable['f'];
+    }
+
+    static
+    {
+        initialiseDecodingTable();
+    }
+
+    private Hex()
+    {
+        // Nothing to do ...
+    }
+
+    /**
+     * encode the input data producing a Hex output stream.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int encode(
+            byte[] data,
+            int off,
+            int length,
+            OutputStream out)
+            throws IOException
+    {
+        for (int i = off; i < (off + length); i++)
+        {
+            int v = data[i] & 0xff;
+
+            out.write(encodingTable[(v >>> 4)]);
+            out.write(encodingTable[v & 0xf]);
+        }
+
+        return length * 2;
+    }
+
+    private static boolean ignore(
+            char c)
+    {
+        return (c == '\n' || c == '\r' || c == '\t' || c == ' ');
+    }
+
+    /**
+     * decode the Hex encoded byte data writing it to the given output stream,
+     * whitespace characters will be ignored.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int decode(
+            byte[] data,
+            int off,
+            int length,
+            OutputStream out)
+            throws IOException
+    {
+        byte b1, b2;
+        int outLen = 0;
+
+        int end = off + length;
+
+        while (end > off)
+        {
+            if (!ignore((char) data[end - 1]))
+            {
+                break;
+            }
+
+            end--;
+        }
+
+        int i = off;
+        while (i < end)
+        {
+            while (i < end && ignore((char) data[i]))
+            {
+                i++;
+            }
+
+            b1 = decodingTable[data[i++]];
+
+            while (i < end && ignore((char) data[i]))
+            {
+                i++;
+            }
+
+            b2 = decodingTable[data[i++]];
+
+            out.write((b1 << 4) | b2);
+
+            outLen++;
+        }
+
+        return outLen;
+    }
+
+    /**
+     * decode the Hex encoded String data writing it to the given output stream,
+     * whitespace characters will be ignored.
+     *
+     * @return the number of bytes produced.
+     */
+    public static int decode(
+            String data,
+            OutputStream out)
+            throws IOException
+    {
+        byte b1, b2;
+        int length = 0;
+
+        int end = data.length();
+
+        while (end > 0)
+        {
+            if (!ignore(data.charAt(end - 1)))
+            {
+                break;
+            }
+
+            end--;
+        }
+
+        int i = 0;
+        while (i < end)
+        {
+            while (i < end && ignore(data.charAt(i)))
+            {
+                i++;
+            }
+
+            b1 = decodingTable[data.charAt(i++)];
+
+            while (i < end && ignore(data.charAt(i)))
+            {
+                i++;
+            }
+
+            b2 = decodingTable[data.charAt(i++)];
+
+            out.write((b1 << 4) | b2);
+
+            length++;
+        }
+
+        return length;
+    }
+
+
+    public static String encode(final byte[] data)
+    {
+        try
+        {
+            final ByteArrayOutputStream out = new ByteArrayOutputStream();
+            encode(data,0,data.length, out);
+            out.close();
+            return new String(out.toByteArray());
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            throw new RuntimeException(e.getMessage(),e);
+        }
+    }
+
+    public static byte[] decode(final String data)
+    {
+        try
+        {
+            final ByteArrayOutputStream out = new ByteArrayOutputStream();
+            decode(data, out);
+            out.close();
+            return out.toByteArray();
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            throw new RuntimeException(e.getMessage(),e);
+        }
+    }
+
+
+}
Index: codegen/src/main/java/org/exolab/castor/builder/descriptors/DescriptorSourceFactory.java
===================================================================
--- codegen/src/main/java/org/exolab/castor/builder/descriptors/DescriptorSourceFactory.java	(revision 6884)
+++ codegen/src/main/java/org/exolab/castor/builder/descriptors/DescriptorSourceFactory.java	(working copy)
@@ -415,6 +415,8 @@
             addSpecialHandlerLogic(member, xsType, jsc);
         }
 
+        // Add the schema type as defined in the schema
+        jsc.add("desc.setSchemaType(\""+ xsType.getName() + "\");");
         jsc.add("desc.setHandler(handler);");
 
         //-- container

