diff options
Diffstat (limited to 'src/com/memberwebs/ldapxml/map')
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXAttribute.java | 78 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXBase.java | 261 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXClass.java | 116 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXEntry.java | 130 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXMap.java | 167 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXMapException.java | 56 | ||||
-rw-r--r-- | src/com/memberwebs/ldapxml/map/LXSAXHandler.java | 488 |
7 files changed, 1296 insertions, 0 deletions
diff --git a/src/com/memberwebs/ldapxml/map/LXAttribute.java b/src/com/memberwebs/ldapxml/map/LXAttribute.java new file mode 100644 index 0000000..8d95770 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXAttribute.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + + + +/** + * Represents an <attribute> or <element> in an LX map. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXAttribute + extends LXBase +{ + /** + * Construct an LXAttribute object. Can only be constructed + * from within the package. + * + * @param parent The parent in the map tree. + * @param isElement Set to true if this is object represents an + * <element>, otherwise an <attribute>. + */ + LXAttribute(LXBase parent, boolean isElement) + { + super(parent); + m_isElement = isElement; + } + + /** + * Check whether this object represents an <element> + * or <attribute>. + * + * @return The state. + */ + public final boolean isElement() + { + return m_isElement; + } + + protected boolean m_isElement; +}; diff --git a/src/com/memberwebs/ldapxml/map/LXBase.java b/src/com/memberwebs/ldapxml/map/LXBase.java new file mode 100644 index 0000000..82b3d09 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXBase.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * A base class for all objects in an LX map tree. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXBase +{ + /** + * Constructs an LXBase object. + * + * @param parent The parent object in the LX map tree. + */ + LXBase(LXBase parent) + { + m_name = null; + m_xmlName = null; + m_nameSpace = null; + m_ns = null; + m_parent = parent; + m_isUseable = true; + + // If we have a parent and it doesn't have any children set + // Then give it child capabilities. + if(parent != null && parent.m_children == null) + parent.m_children = new Hashtable(); + } + + /** + * Get the full XML name for this object. This includes any namespace + * prefixes prepended to the name. + * + * @return The XML name. + */ + public String getXmlName() + { + String xmlName = m_xmlName; + if(xmlName == null) + xmlName = m_name; + + if(xmlName != null) + { + String prefix = getPrefix(); + if(prefix != null) + xmlName = prefix + ":" + xmlName; + } + + return xmlName; + } + + + /** + * Get the name of this object. + * + * @return The name. + */ + public final String getName() + { + return m_name; + } + + + /** + * Set the name of this object. Updates the parent (if any) + * to reflect this change in tree structure. + * + * @param name The new name + */ + void setName(String name) + { + if(m_name != null && m_parent != null) + m_parent.m_children.remove(m_name); + + if(name != null) + { + if(m_parent != null) + m_parent.m_children.put(name, this); + + m_name = name; + } + } + + /** + * Get the namespace prefix for this object. If this object has + * no namespaces info set, returns the parent objects namespace + * prefix. + * + * @return The namespace prefix, or null if there is no prefix. + */ + public String getPrefix() + { + // If we have a namespace then return + // the ns value regardless + if(m_nameSpace != null) + return m_ns; + + if(m_ns != null) + return m_ns; + + if(m_parent != null) + return m_parent.getPrefix(); + + return null; + } + + /** + * Get the full namespace URI for this object. + * + * @param here If set to true, then parent namespaces will + * be returned if none is set on this object. + * @return The namespace. + */ + public String getNamespace(boolean here) + { + if(m_nameSpace != null || here) + return m_nameSpace; + + if(m_parent != null) + return m_parent.getNamespace(); + + return null; + } + + /** + * Get the full namespace URI for this node. + * If this object has no namespace, it's parent will + * be queried. + * + * @return The namespace. + */ + public String getNamespace() + { + return getNamespace(false); + } + + /** + * Get this object's parent in the LX map tree. + * + * @return The parent, or null if this object has no parent. + */ + public final LXBase getParent() + { + return m_parent; + } + + /** + * Get a child of this object in the LX map tree. + * + * @param name The child's name. + * @return The child, or null if no such child is present. + */ + public final LXBase getChild(String name) + { + if(m_children == null) + return null; + + return (LXBase)m_children.get(name); + } + + /** + * Get the names of all the child objects. + * + * @return An enumeraton of the child attribute names. + */ + public final Enumeration getChildNames() + { + if(m_children == null) + return null; + + return m_children.keys(); + } + + /** + * Check whether this object has been marked unusable. + * + * @return Usability status. + */ + public final boolean isUseable() + { + return m_isUseable; + } + + /** + * Get the LX hook for this object. If this + * object has no hook, then the parent will be queried. + * + * @return The class name of the LX hook. + */ + public String getHook() + { + if(m_hook == null && m_parent != null) + return m_parent.getHook(); + + return m_hook; + } + + // The name to be used when creating XML for this object. + String m_xmlName; + + // Namespace information for this object + String m_nameSpace; + String m_ns; + + // The hook for this object and below + String m_hook; + + // Is this object useable or not + boolean m_isUseable; + + // This object's parent in the LX map + private LXBase m_parent; + + // This object's name + private String m_name; + + // Children in the LX map tree of this object. + private Hashtable m_children; +}; diff --git a/src/com/memberwebs/ldapxml/map/LXClass.java b/src/com/memberwebs/ldapxml/map/LXClass.java new file mode 100644 index 0000000..94e0da9 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXClass.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + + + +/** + * Represents a <class> in an LX map. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXClass + extends LXBase +{ + /** + * Construct a new LXClass. + * + * @param parent This class's parent object in the LX map tree. + */ + LXClass(LXBase parent) + { + super(parent); + m_isInline = true; + m_isInclusive = true; + } + + /** + * Returns an attribute of this class. + * + * @param name The attribute's name + * @return The attrtibute, or null if no such attribute is present. + */ + public LXAttribute getAttribute(String name) + { + LXAttribute attr = (LXAttribute)getChild(name); + + // If there is no such attribute and we're allowed + // to just include everything, then... + if(attr == null) + { + if(m_isInclusive) + { + // ... just create it on the fly. + attr = new LXAttribute(this, true); + attr.setName(name); + } + } + + // Check if we haven't been marked as unusable + else if(!attr.isUseable()) + { + attr = null; + } + + return attr; + } + + /** + * Checks if this class' attributes go inline + * or if the class gets it's own element in XML. + * + * @return Inline or not. + */ + public final boolean isInline() + { + return m_isInline; + } + + public final boolean isInclusive() + { + return m_isInclusive; + } + + // Include all attributes not otherwise specified + boolean m_isInclusive; + + // Create a class element around attributes in XML. + boolean m_isInline; +}; diff --git a/src/com/memberwebs/ldapxml/map/LXEntry.java b/src/com/memberwebs/ldapxml/map/LXEntry.java new file mode 100644 index 0000000..cf1760b --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXEntry.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Map; + + + +/** + * Represents an <entry> object in an LX map. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXEntry + extends LXBase +{ + private Map m_xmlMap; + private Map m_nameMap; + + /** + * Constructs a new LXEntry object. + * + * @param parent The parent of this entry in the LX map tree. + */ + LXEntry(LXBase parent) + { + super(parent); + } + + /** + * Gets a class in this entry. + * + * @param name The name of the class. + * @return The class, or null if no such class is present. + */ + public LXClass getClass(String name) + { + LXClass cls = (LXClass)getChild(name); + + if(cls != null && !cls.isUseable()) + cls = null; + + return cls; + } + + /** + * Resolve an XML name to an attribute. + */ + public LXAttribute resolveXMLName(String name) + { + loadNameMaps(); + return (LXAttribute)m_xmlMap.get(name); + } + + public LXAttribute resolveName(String name) + { + loadNameMaps(); + return (LXAttribute)m_nameMap.get(name); + } + + private void loadNameMaps() + { + // Note: This should never be called internally until the map + // is completely built. It relies on the map remaining static + // after this point, as there is no method for syncinc the + // cached map created below. + + if(m_xmlMap == null || m_nameMap == null) + { + m_xmlMap = new Hashtable(); + m_nameMap = new Hashtable(); + + Enumeration e = getChildNames(); + while(e != null && e.hasMoreElements()) + { + LXClass cls = getClass((String)e.nextElement()); + + Enumeration e2 = cls.getChildNames(); + while(e2 != null && e2.hasMoreElements()) + { + LXAttribute attr = cls.getAttribute((String)e2.nextElement()); + if(attr != null) + { + m_xmlMap.put(attr.getXmlName(), attr); + m_nameMap.put(attr.getName(), attr); + } + } + } + } + } +}; diff --git a/src/com/memberwebs/ldapxml/map/LXMap.java b/src/com/memberwebs/ldapxml/map/LXMap.java new file mode 100644 index 0000000..2676f18 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXMap.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + + +/** + * The in memory representation of an LX map. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXMap + extends LXBase +{ + // Cache of the name map + private Map m_nameMap; + + // Cache of the name set + private Set m_nameSet; + + /** + * Constructs a new LXMap object. + */ + LXMap(Map nameMap, Set nameSet) + { + super(null); + m_nameMap = nameMap; + m_nameSet = nameSet; + } + + + /** + * Get an entry in this LX map by name. + * + * @param name The entry name. + * @return The entry, or null if no such entry is present + */ + public LXEntry getEntry(String name) + { + LXEntry entry = (LXEntry)getChild(name); + + if(entry != null && !entry.isUseable()) + entry = null; + + return entry; + } + + /** + * Get public (XML) to private (LDAP) name mappings + * for the first entry. + * + * @return The name map. + */ + public final Map getNameMap() + { + return m_nameMap; + } + + /** + * Get the minimum set of LDAP attributes required + * to retrieve items via this map. + */ + public final Set getNameSet() + { + return m_nameSet; + } + + /** + * Load an LX map from an XML data stream + * + * @param source The source of the XML data. + */ + public static LXMap loadMap(InputSource source) + throws LXMapException, IOException + { + try + { + XMLReader xr = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); + + // We require some form of validation on the document + // as our internal checks are lax + xr.setFeature("http://xml.org/sax/features/validation", true); + + // Parse and load the map. + LXSAXHandler handler = new LXSAXHandler(); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + xr.parse(source); + + LXMap map = handler.getMap(); + return map; + } + catch(SAXException e) + { + Exception inside = e.getException(); + + if(inside != null) + { + inside.printStackTrace(); + if(inside instanceof LXMapException) + throw (LXMapException)inside; + else if(inside.getMessage() != null) + throw new LXMapException(inside.getMessage()); + else + throw new LXMapException(inside.getClass().getName()); + } + + throw new LXMapException(e.getMessage()); + } + } + + /** + * Load an LX map from a uri. + * + * @param uri The fully qualified uri of the file. + */ + public static LXMap loadMap(String uri) + throws LXMapException, IOException + { + return loadMap(new InputSource(uri)); + } +} diff --git a/src/com/memberwebs/ldapxml/map/LXMapException.java b/src/com/memberwebs/ldapxml/map/LXMapException.java new file mode 100644 index 0000000..4dd24b4 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXMapException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + +import com.memberwebs.ldapxml.LXException; + +/** + * Thrown when an error occurs parsing an LX map file. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +public class LXMapException + extends LXException +{ + public LXMapException(String message) + { + super(message); + } +} diff --git a/src/com/memberwebs/ldapxml/map/LXSAXHandler.java b/src/com/memberwebs/ldapxml/map/LXSAXHandler.java new file mode 100644 index 0000000..d81c240 --- /dev/null +++ b/src/com/memberwebs/ldapxml/map/LXSAXHandler.java @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2004, Nate Nielsen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * + * CONTRIBUTORS + * Nate Nielsen <nielsen@memberwebs.com> + * + */ + +package com.memberwebs.ldapxml.map; + +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +/** + * Parses an XML file into an in memory LX map representation. + * + * @author nielsen@memberwebs.com + * @version 0.5 + */ +class LXSAXHandler + extends DefaultHandler +{ + private static final String EL_ROOT = "lxmap"; + private static final String EL_ENTRY = "entry"; + private static final String EL_CLASS = "class"; + private static final String EL_ELEMENT = "element"; + private static final String EL_ATTRIBUTE = "attribute"; + private static final String EL_RENAME = "rename"; + private static final String EL_IGNORE = "ignore"; + private static final String AT_NAME = "name"; + private static final String AT_CLASS = "class"; + private static final String AT_MODE = "mode"; + private static final String AT_NAMESPACE = "namespace"; + private static final String AT_NS = "ns"; + private static final String AT_PLACE = "place"; + private static final String AT_HOOK = "hook"; + private static final String AT_ROOT = "root"; + private static final String VAL_INCLUSIVE = "inclusive"; + private static final String VAL_EXCLUSIVE = "exclusive"; + private static final String VAL_INLINE = "inline"; + private static final String VAL_BLOCK = "block"; + private static final String AT_VERSION = "version"; + private static final String VAL_VERSION = "1.0"; + + private static final String INTERNAL_ERROR = "LX Map parser invalid internal state"; + + // The root of the map being built + private LXMap m_map; + + // The current LX map object being acted on. + private LXBase m_cur; + + // Stack of LX objects + private Stack m_elStack; + + // public (XML) to private (LDAP) name mappings + private Hashtable m_nameMap; + + // All the LDAP attributes required for this map + private HashSet m_nameSet; + + /** + * Constructs a new LXSAXHandler object. + */ + public LXSAXHandler() + { + m_elStack = new Stack(); + m_nameMap = new Hashtable(); + m_nameSet = null; + } + + /** + * Called at the start of the XML document. + */ + public void startDocument() + throws SAXException + { + m_cur = null; + m_map = null; + m_nameMap.clear(); + m_nameSet = new HashSet(); + } + + /** + * Called at the end of the XML document. + */ + public void endDocument() + throws SAXException + { + // The current LX object should be null as we're back + // to the root. If not then something went wrong. + if(m_cur != null) + throw new SAXException(new LXMapException(INTERNAL_ERROR)); + } + + + /** + * Called when a new element is encountered in the XML file. + * + * @param uri The element namespace + * @param localName The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + */ + public void startElement(String uri, String localName, String qName, + Attributes attributes) + throws SAXException + { + try + { + // Push the current LX object on a stack so it can + // be popped as we encounter the end of elements. + + // Since null doesn't work with the collection classes + // we use 'this' to represent it. (See endElement) + if(m_cur == null) + m_elStack.push(this); + else + m_elStack.push(m_cur); + + // Now depending on what kind of LX Object we have around + // we hand of parsing to different functions. + if(m_cur == null) + { + rootHandler(uri, localName, qName, attributes); + } + else if(m_cur instanceof LXMap) + { + entryHandler(uri, localName, qName, attributes); + } + else if(m_cur instanceof LXEntry) + { + if(!classHandler(uri, localName, qName, attributes)) + actionHandler(uri, localName, qName, attributes); + } + else if(m_cur instanceof LXClass) + { + if(!attributeHandler(uri, localName, qName, attributes)) + actionHandler(uri, localName, qName, attributes); + } + else if(m_cur instanceof LXAttribute) + { + actionHandler(uri, localName, qName, attributes); + } + else + throw new LXMapException(INTERNAL_ERROR); + + } + catch(LXMapException e) + { + throw new SAXException(e); + } + } + + /** + * Called when the end of an element is encountered. + * + * @param uri The namespace of this element. + * @param localName The plain name of this element. + * @param qName The fully qualified name of this element. + */ + public void endElement(String uri, String localName, String qName) + throws SAXException + { + // Add the current element to the naming stack + if(m_cur instanceof LXAttribute) + addName(m_cur); + + // Pop the current LX object off the stack + Object obj = m_elStack.pop(); + if(obj == null) + throw new SAXException(new LXMapException(INTERNAL_ERROR)); + + // If it's set to 'this' then it's actually + // 'null' (See startElement) + if(obj == this) + m_cur = null; + else + m_cur = (LXBase)obj; + } + + /** + * Handles elements at the root document level. + * + * @param uri The element namespace + * @param localname The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + * @return Returns true if element was processed. + */ + private boolean rootHandler(String uri, String localName, String qName, + Attributes attributes) + throws LXMapException + { + if(qName.equals(EL_ROOT)) + { + if(!attributes.getValue(AT_VERSION).equals(VAL_VERSION)) + throw new LXMapException("Invalid LX Map version"); + + m_map = new LXMap(m_nameMap, m_nameSet); + m_cur = m_map; + + nameAttrHandler(attributes, AT_ROOT); + commonAttrHandler(attributes); + + + // Put some exceptions into the name map + m_nameMap.put("class", "objectClass"); + + String prefix = m_cur.getPrefix(); + if(prefix != null) + m_nameMap.put(prefix + ":class", "objectClass"); + + + return true; + } + + return false; + } + + /** + * Handles entry elements at the map root level. + * + * @param uri The element namespace + * @param localname The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + * @return Returns true if element was processed. + */ + private boolean entryHandler(String uri, String localName, String qName, + Attributes attributes) + throws LXMapException + { + if(qName.equals(EL_ENTRY)) + { + LXEntry entry = new LXEntry(m_cur); + m_cur = entry; + nameAttrHandler(attributes, AT_CLASS); + commonAttrHandler(attributes); + return true; + } + + return false; + } + + /** + * Handles class elements at the map entry level. + * + * @param uri The element namespace + * @param localname The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + * @return Returns true if element was processed. + */ + private boolean classHandler(String uri, String localName, String qName, + Attributes attributes) + throws LXMapException + { + if(qName.equals(EL_CLASS)) + { + LXClass cls = new LXClass(m_cur); + m_cur = cls; + nameAttrHandler(attributes, null); + commonAttrHandler(attributes); + classAttrHandler(attributes); + return true; + } + + return false; + } + + /** + * Handles attribute elements at the map class level. + * + * @param uri The element namespace + * @param localname The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + * @return Returns true if element was processed. + */ + private boolean attributeHandler(String uri, String localName, String qName, + Attributes attributes) + throws LXMapException + { + if(qName.equals(EL_ATTRIBUTE)) + { + LXAttribute attr = new LXAttribute(m_cur, false); + m_cur = attr; + nameAttrHandler(attributes, null); + return true; + } + else if(qName.equals(EL_ELEMENT)) + { + LXAttribute attr = new LXAttribute(m_cur, true); + m_cur = attr; + nameAttrHandler(attributes, null); + return true; + } + + return false; + } + + /** + * Handles action elements at various levels. + * + * @param uri The element namespace + * @param localname The plain element name. + * @param qName The fully quallified element name. + * @param attributes The element's attributes. + * @return Returns true if element was processed. + */ + private boolean actionHandler(String uri, String localName, String qName, + Attributes attributes) + throws LXMapException + { + if(qName.equals(EL_IGNORE)) + { + m_cur.m_isUseable = false; + return true; + } + else if(qName.equals(EL_RENAME)) + { + m_cur.m_xmlName = attributes.getValue(AT_NAME); + + if(m_cur.m_xmlName == null) + throw new LXMapException("LX map element requires a '" + AT_NAME + "' attribute"); + } + + return false; + } + + /** + * Handles an element's name. + * + * @param attributes The element's attributes. + */ + private void nameAttrHandler(Attributes attributes, String attr) + throws LXMapException + { + if(attr == null) + attr = AT_NAME; + + m_cur.setName(attributes.getValue(attr)); + + if(m_cur.getName() == null) + throw new LXMapException("LX map element requires a '" + attr + "' attribute"); + } + + /** + * Handles an element's namespace and other basic info. + * + * @param attributes The element's attributes. + */ + private void commonAttrHandler(Attributes attributes) + throws LXMapException + { + m_cur.m_nameSpace = attributes.getValue(AT_NAMESPACE); + m_cur.m_ns = attributes.getValue(AT_NS); + m_cur.m_hook = attributes.getValue(AT_HOOK); + } + + /** + * Handles various attributes for class elements. + * + * @param attributes The element's attributes. + */ + private void classAttrHandler(Attributes attributes) + throws LXMapException + { + if(!(m_cur instanceof LXClass)) + throw new LXMapException(INTERNAL_ERROR); + + LXClass cls = (LXClass)m_cur; + + String inc = attributes.getValue(AT_MODE); + if(inc == null || inc.equals(VAL_EXCLUSIVE)) + { + cls.m_isInclusive = false; + } + else if(inc.equals(VAL_INCLUSIVE)) + { + // We don't know the list of names + m_nameSet = null; + cls.m_isInclusive = true; + } + else + throw new LXMapException("LX map invalid value for '" + AT_MODE + "' attribute"); + + String place = attributes.getValue(AT_PLACE); + if(place != null) + { + if(place.equals(VAL_INLINE)) + cls.m_isInline = true; + else if(place.equals(VAL_BLOCK)) + cls.m_isInline = false; + else + throw new LXMapException("LX map invalid value for '" + AT_PLACE + "' attribute"); + } + } + + /** + * Get the resulting LX Map. + * + * @return The map. + */ + public final LXMap getMap() + { + return m_map; + } + + /** + * Get public (XML) to private (LDAP) name mappings + * for the first entry. + * + * @return The name map. + */ + public final Map getNameMap() + { + return m_nameMap; + } + + /** + * Gets a listing of the minimum set of attributes required + * to satisfy this map, or null when not known + */ + public final Set getNameSet() + { + return m_nameSet; + } + + /** + * Add an LX object to the name map. This adds both + * the prefixed name as well as the local name. + * + * @param base The LX object whose name to add. + */ + private void addName(LXBase base) + { + String name = base.getName(); + if(base.m_xmlName != null && !m_nameMap.contains(base.m_xmlName)) + m_nameMap.put(base.m_xmlName, name); + + String xmlName = base.getXmlName(); + if(xmlName != null && !m_nameMap.contains(xmlName)) + m_nameMap.put(xmlName, name); + + if(m_nameSet != null) + m_nameSet.add(name); + } +} |