001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: WebtopParser.java,v 1.3 2008/06/25 05:41:29 qcheng Exp $
026 *
027 */
028/**
029 * Portions Copyrighted 2012 ForgeRock Inc
030 */
031package com.iplanet.dpro.parser;
032
033
034import com.sun.identity.shared.xml.XMLUtils;
035import java.io.ByteArrayInputStream;
036import java.io.FileInputStream;
037import java.io.IOException;
038import java.io.InputStream;
039import java.io.UnsupportedEncodingException;
040import java.util.Hashtable;
041import java.util.Vector;
042import javax.xml.parsers.DocumentBuilder;
043import javax.xml.parsers.ParserConfigurationException;
044import org.w3c.dom.Document;
045import org.w3c.dom.Element;
046import org.w3c.dom.NamedNodeMap;
047import org.w3c.dom.Node;
048import org.xml.sax.SAXException;
049import org.xml.sax.SAXParseException;
050
051/**
052 * XMLParser provides a way for applications to handle a hook into
053 * applications and applications and its server.
054 *
055 * @supported.all.api
056 */
057public class WebtopParser {
058    private Hashtable elemmap = new Hashtable();
059    private boolean useGenericClass = false;
060
061    static public void main(String argv[]) throws Exception {
062        WebtopParser wp = new WebtopParser(true);
063        GenericNode n = (GenericNode) wp.parse(new FileInputStream(argv[0]));
064        System.out.println("FINAL:"+n.toString());
065    }
066
067    /**
068     * Parses and processes a Node.
069     *
070     * @param nd The Node to parse.
071     * @return the parsed object for the node.
072     * @throws Exception if node cannot be parsed or <code>ParseOutput</code>
073     *         object cannot be instantiated.
074     */
075    ParseOutput walkTree(Node nd)
076        throws Exception
077    {
078        Vector elements = new Vector();
079        Vector retelements;
080        String pcdata = null;
081        Hashtable atts = new Hashtable();
082        NamedNodeMap nd_map = nd.getAttributes();
083        if (nd_map != null) {
084            for (int i=0; i < nd_map.getLength(); i++) {
085                Node att = nd_map.item(i);
086                atts.put(att.getNodeName(), att.getNodeValue());
087            }
088        }
089        for (Node ch = nd.getFirstChild();
090        ch != null; ch = ch.getNextSibling()) {
091            switch (ch.getNodeType()) {
092                case Node.ELEMENT_NODE :
093                    elements.addElement(walkTree(ch));
094                    break;
095                case Node.TEXT_NODE :
096                    String tmp  = stripWhitespaces(ch.getNodeValue());
097                    if (tmp != null && tmp.length() !=0) {
098                        pcdata = tmp;
099                    }
100                    break;
101                default :
102            }
103        }
104        // lookup hash
105        String po_name = (String) elemmap.get(nd.getNodeName());
106        ParseOutput po;
107        if (po_name == null) {
108            if (useGenericClass) {
109                po = (ParseOutput) new GenericNode();
110            } else {
111                throw new Exception("No class registered for"+nd.getNodeName());
112            }
113        } else {
114            try {
115                po = (ParseOutput) Class.forName(po_name).newInstance();
116            } catch(Exception ex) {
117                StringBuilder buf = new StringBuilder();
118                buf.append("Got Exception while creating class instance of ");
119                buf.append(nd.getNodeName());
120                buf.append(" :");
121                buf.append(ex.toString());
122                throw new Exception(buf.toString());
123            }
124        }
125        po.process(nd.getNodeName(), elements, atts, pcdata);
126        return po;
127    }
128
129    /**
130     * Removes leading and trailing whitespace.
131     *
132     * @param s String from which to remove whitespace.
133     * @return String with leading and trailing whitespace removed.
134     */
135    String stripWhitespaces(String s) {
136        return s.trim();
137    }
138
139    /**
140     * Constructs a <code>WebtopParser</code> instance.
141     */
142    public WebtopParser() {
143    }
144
145    /**
146     * Sets whether to use the default <code>GenericNode</code> as the node
147     * type.
148     *
149     * @param usegeneric <code>true</code> if <code>GenericNode</code> type is
150     *        to be used.
151     */
152    public WebtopParser(boolean usegeneric) {
153        useGenericClass = usegeneric;
154    }
155
156    /**
157     * Parses an XML document from a String variable.
158     *
159     * @param s The XML document.
160     * @throws Exception if there are unsupported encoding issues.
161     */
162    public Object parse(String s) throws Exception {
163        ByteArrayInputStream bin = null;
164        String st = stripWhitespaces(s);
165        try {
166            bin = new ByteArrayInputStream(st.getBytes("UTF-8"));
167        } catch(UnsupportedEncodingException ex) {
168            throw new Exception("Encoding not supported:" + ex.toString());
169        }
170        return parse(bin);
171    }
172
173    /**
174     * Parses an XML document.
175     *
176     * @param xmlin the XML document.
177     * @return the ParseOutput object from walking and processing the node.
178     * @throws Exception if there are IO or XML parsing exceptions.
179     */
180    public Object parse(InputStream xmlin)
181        throws Exception
182    {
183        DocumentBuilder db = null;
184        try {
185            db = XMLUtils.getSafeDocumentBuilder(false);
186        } catch (ParserConfigurationException e) {
187            throw new Exception("DBG:Got ParserConfigurationException:" +
188                e.toString());
189        }
190
191        Document doc = null;
192        try {
193            doc = db.parse(xmlin);
194        } catch(SAXParseException e) {
195            throw new Exception("DBG:Got SAXParseException:" +
196                e.toString() + "line:" +e.getLineNumber() +
197                " col :" + e.getColumnNumber());
198        } catch (SAXException e) {
199            throw new Exception("DBG:Got SAXException:" +e.toString());
200        } catch (IOException ex) {
201            throw new Exception("DBG: Got IOException:" + ex.toString());
202        }
203
204        Element elem = doc.getDocumentElement();
205        return(walkTree(elem));
206    }
207
208    /**
209     * Registers a call back function.
210     *
211     * @param elemname The tag name of this node.
212     * @param classname The call back function.
213     */
214    public void register(String elemname, String classname) {
215        if (elemmap == null) {
216            elemmap = new Hashtable();
217        }
218        elemmap.put(elemname, classname);
219    }
220}
221