/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */

/*
 * Copyright  1999-2004 The Apache Software Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package com.sun.org.apache.xml.internal.security.utils;



import java.io.IOException;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;



/**
 * DOM and XML accessibility and comfort functions.
 *
 * @author Christian Geuer-Pollmann
 */
public class XMLUtils {

   /**
    * Constructor XMLUtils
    *
    */
   private XMLUtils() {

      // we don't allow instantiation
   }


   /**
    * @param rootNode
    * @param result
    * @param exclude
    * @param com wheather comments or not
    */
   public static void getSet(Node rootNode,Set result,Node exclude ,boolean com) {
          if ((exclude!=null) && isDescendantOrSelf(exclude,rootNode)){
                return;
      }
      getSetRec(rootNode,result,exclude,com);
   }
   static final void getSetRec(final Node rootNode,final Set result,
        final Node exclude ,final boolean com) {
           //Set result = new HashSet();
       if (rootNode==exclude) {
          return;
       }
           switch (rootNode.getNodeType()) {
                case Node.ELEMENT_NODE:
                                result.add(rootNode);
                        Element el=(Element)rootNode;
                if (el.hasAttributes()) {
                                NamedNodeMap nl = ((Element)rootNode).getAttributes();
                                for (int i=0;i<nl.getLength();i++) {
                                        result.add(nl.item(i));
                                }
                }
                //no return keep working
                case Node.DOCUMENT_NODE:
                                for (Node r=rootNode.getFirstChild();r!=null;r=r.getNextSibling()){
                                        if (r.getNodeType()==Node.TEXT_NODE) {
                                                result.add(r);
                                                while ((r!=null) && (r.getNodeType()==Node.TEXT_NODE)) {
                                                        r=r.getNextSibling();
                                                }
                                                if (r==null)
                                                        return;
                                        }
                                        getSetRec(r,result,exclude,com);
                                }
                                return;
                        case Node.COMMENT_NODE:
                                if (com) {
                                        result.add(rootNode);
                                }
                            return;
                        case Node.DOCUMENT_TYPE_NODE:
                                return;
                        default:
                                result.add(rootNode);
           }
           return;
   }


   /**
    * Outputs a DOM tree to an {@link OutputStream}.
    *
    * @param contextNode root node of the DOM tree
    * @param os the {@link OutputStream}
    */
   public static void outputDOM(Node contextNode, OutputStream os) {
      XMLUtils.outputDOM(contextNode, os, false);
   }

   /**
    * Outputs a DOM tree to an {@link OutputStream}. <I>If an Exception is
    * thrown during execution, it's StackTrace is output to System.out, but the
    * Exception is not re-thrown.</I>
    *
    * @param contextNode root node of the DOM tree
    * @param os the {@link OutputStream}
    * @param addPreamble
    */
   public static void outputDOM(Node contextNode, OutputStream os,
                                boolean addPreamble) {

      try {
         if (addPreamble) {
            os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".getBytes());
         }

         os.write(
            Canonicalizer.getInstance(
               Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(
               contextNode));
      } catch (IOException ex) {}
      catch (InvalidCanonicalizerException ex) {
         ex.printStackTrace();
      } catch (CanonicalizationException ex) {
         ex.printStackTrace();
      }
   }

   /**
    * Serializes the <CODE>contextNode</CODE> into the OutputStream, <I>but
    * supresses all Exceptions</I>.
    * <BR />
    * NOTE: <I>This should only be used for debugging purposes,
    * NOT in a production environment; this method ignores all exceptions,
    * so you won't notice if something goes wrong. If you're asking what is to
    * be used in a production environment, simply use the code inside the
    * <code>try{}</code> statement, but handle the Exceptions appropriately.</I>
    *
    * @param contextNode
    * @param os
    */
   public static void outputDOMc14nWithComments(Node contextNode,
           OutputStream os) {

      try {
         os.write(
            Canonicalizer.getInstance(
               Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(
               contextNode));
      } catch (IOException ex) {

         // throw new RuntimeException(ex.getMessage());
      } catch (InvalidCanonicalizerException ex) {

         // throw new RuntimeException(ex.getMessage());
      } catch (CanonicalizationException ex) {

         // throw new RuntimeException(ex.getMessage());
      }
   }


   /**
    * Method getFullTextChildrenFromElement
    *
    * @param element
    * @return the string of chi;ds
    */
   public static String getFullTextChildrenFromElement(Element element) {

      StringBuffer sb = new StringBuffer();
      NodeList children = element.getChildNodes();
      int iMax = children.getLength();

      for (int i = 0; i < iMax; i++) {
         Node curr = children.item(i);

         if (curr.getNodeType() == Node.TEXT_NODE) {
            sb.append(((Text) curr).getData());
         }
      }

      return sb.toString();
   }


   /**
    * Creates an Element in the XML Signature specification namespace.
    *
    * @param doc the factory Document
    * @param elementName the local name of the Element
    * @return the Element
    */
   public static Element createElementInSignatureSpace(Document doc,
           String elementName) {

      if (doc == null) {
         throw new RuntimeException("Document is null");
      }

      String ds = Constants.getSignatureSpecNSprefix();

      if ((ds == null) || (ds.length() == 0)) {
         Element element = doc.createElementNS(Constants.SignatureSpecNS,
                                               elementName);

         element.setAttributeNS(Constants.NamespaceSpecNS, "xmlns",
                                Constants.SignatureSpecNS);

         return element;
      }
         Element element = doc.createElementNS(Constants.SignatureSpecNS,
                                               ds + ":" + elementName);

         element.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + ds,
                                Constants.SignatureSpecNS);

         return element;

   }


   /**
    * Returns true if the element is in XML Signature namespace and the local
    * name equals the supplied one.
    *
    * @param element
    * @param localName
    * @return true if the element is in XML Signature namespace and the local name equals the supplied one
    */
   public static boolean elementIsInSignatureSpace(Element element,
           String localName) {

      if ((element == null) ||
          !Constants.SignatureSpecNS.equals(element.getNamespaceURI()) ){
         return false;
      }

      if (!element.getLocalName().equals(localName)) {
         return false;
      }

      return true;
   }

   /**
    * Returns true if the element is in XML Encryption namespace and the local
    * name equals the supplied one.
    *
    * @param element
    * @param localName
    * @return true if the element is in XML Encryption namespace and the local name equals the supplied one
    */
   public static boolean elementIsInEncryptionSpace(Element element,
           String localName) {

      if ((element == null) ||
            !EncryptionConstants.EncryptionSpecNS.equals(element.getNamespaceURI())
          ){
         return false;
      }

      if (!element.getLocalName().equals(localName)) {
         return false;
      }

      return true;
   }

   /**
    * This method returns the owner document of a particular node.
    * This method is necessary because it <I>always</I> returns a
    * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
    * if the {@link Node} is a {@link Document}.
    *
    * @param node
    * @return the owner document of the node
    */
   public static Document getOwnerDocument(Node node) {

      if (node.getNodeType() == Node.DOCUMENT_NODE) {
         return (Document) node;
      }
         try {
            return node.getOwnerDocument();
         } catch (NullPointerException npe) {
            throw new NullPointerException(I18n.translate("endorsed.jdk1.4.0")
                                           + " Original message was \""
                                           + npe.getMessage() + "\"");
         }

   }

    /**
     * This method returns the first non-null owner document of the Node's in this Set.
     * This method is necessary because it <I>always</I> returns a
     * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
     * if the {@link Node} is a {@link Document}.
     *
     * @param xpathNodeSet
     * @return the owner document
     */
    public static Document getOwnerDocument(Set xpathNodeSet) {
       NullPointerException npe = null;
       Iterator iterator = xpathNodeSet.iterator();
       while(iterator.hasNext()) {
           Node node = (Node) iterator.next();
           int nodeType =node.getNodeType();
           if (nodeType == Node.DOCUMENT_NODE) {
              return (Document) node;
           }
              try {
                 if (nodeType==Node.ATTRIBUTE_NODE) {
                    return ((Attr)node).getOwnerElement().getOwnerDocument();
                 }
                 return node.getOwnerDocument();
              } catch (NullPointerException e) {
                  npe = e;
              }

       }
       throw new NullPointerException(I18n.translate("endorsed.jdk1.4.0")
                                       + " Original message was \""
                                       + (npe == null ? "" : npe.getMessage()) + "\"");
    }



   /**
    * Method createDSctx
    *
    * @param doc
    * @param prefix
    * @param namespace
    * @return the element.
    */
   public static Element createDSctx(Document doc, String prefix,
                                     String namespace) {

      if ((prefix == null) || (prefix.trim().length() == 0)) {
         throw new IllegalArgumentException("You must supply a prefix");
      }

      Element ctx = doc.createElementNS(null, "namespaceContext");

      ctx.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + prefix.trim(),
                         namespace);

      return ctx;
   }



   /**
    * Method addReturnToElement
    *
    * @param e
    */
   public static void addReturnToElement(Element e) {

      Document doc = e.getOwnerDocument();

      e.appendChild(doc.createTextNode("\n"));
   }

   /**
    * Method convertNodelistToSet
    *
    * @param xpathNodeSet
    * @return the set with the nodelist
    */
   public static Set convertNodelistToSet(NodeList xpathNodeSet) {

      if (xpathNodeSet == null) {
         return new HashSet();
      }

      int length = xpathNodeSet.getLength();
      Set set = new HashSet(length);

      for (int i = 0; i < length; i++) {
         set.add(xpathNodeSet.item(i));
      }

      return set;
   }


   /**
    * This method spreads all namespace attributes in a DOM document to their
    * children. This is needed because the XML Signature XPath transform
    * must evaluate the XPath against all nodes in the input, even against
    * XPath namespace nodes. Through a bug in XalanJ2, the namespace nodes are
    * not fully visible in the Xalan XPath model, so we have to do this by
    * hand in DOM spaces so that the nodes become visible in XPath space.
    *
    * @param doc
    * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">Namespace axis resolution is not XPath compliant </A>
    */
   public static void circumventBug2650(Document doc) {

      Element documentElement = doc.getDocumentElement();

      // if the document element has no xmlns definition, we add xmlns=""
      Attr xmlnsAttr =
         documentElement.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns");

      if (xmlnsAttr == null) {
         documentElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "");
      }

      XMLUtils.circumventBug2650internal(doc);
   }

   /**
    * This is the work horse for {@link #circumventBug2650}.
    *
    * @param node
    * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">Namespace axis resolution is not XPath compliant </A>
    */
   private static void circumventBug2650internal(Node node) {
           Node parent=null;
           Node sibling=null;
           final String namespaceNs=Constants.NamespaceSpecNS;
           do {
         switch (node.getNodeType()) {
         case Node.ELEMENT_NODE :
                 Element element = (Element) node;
             if (!element.hasChildNodes())
                 break;
             if (element.hasAttributes()) {
             NamedNodeMap attributes = element.getAttributes();
             int attributesLength = attributes.getLength();

             for (Node child = element.getFirstChild(); child!=null;
                child=child.getNextSibling()) {

                if (child.getNodeType() != Node.ELEMENT_NODE) {
                        continue;
                }
                Element childElement = (Element) child;

                for (int i = 0; i < attributesLength; i++) {
                        Attr currentAttr = (Attr) attributes.item(i);
                        if (!namespaceNs.equals(currentAttr.getNamespaceURI()))
                                continue;
                        if (childElement.hasAttributeNS(namespaceNs,
                                                        currentAttr.getLocalName())) {
                                        continue;
                        }
                        childElement.setAttributeNS(namespaceNs,
                                                currentAttr.getName(),
                                                currentAttr.getNodeValue());


                }
             }
             }
         case Node.ENTITY_REFERENCE_NODE :
         case Node.DOCUMENT_NODE :
                 parent=node;
                 sibling=node.getFirstChild();
             break;
         }
         while ((sibling==null) && (parent!=null)) {
                         sibling=parent.getNextSibling();
                         parent=parent.getParentNode();
                 };
       if (sibling==null) {
                         return;
                 }

         node=sibling;
         sibling=node.getNextSibling();
           } while (true);
   }

   /**
    * @param sibling
    * @param nodeName
    * @param number
    * @return nodes with the constrain
    */
   public static Element selectDsNode(Node sibling, String nodeName, int number) {
        while (sibling!=null) {
                if (nodeName.equals(sibling.getLocalName())
                                && Constants.SignatureSpecNS.equals(sibling.getNamespaceURI())) {
                        if (number==0){
                                return (Element)sibling;
                        }
                        number--;
                }
                sibling=sibling.getNextSibling();
        }
        return null;
   }

   /**
    * @param sibling
    * @param nodeName
    * @param number
    * @return nodes with the constrain
    */

   public static Element selectXencNode(Node sibling, String nodeName, int number) {
        while (sibling!=null) {
                if (nodeName.equals(sibling.getLocalName())
                                && EncryptionConstants.EncryptionSpecNS.equals(sibling.getNamespaceURI())) {
                        if (number==0){
                                return (Element)sibling;
                        }
                        number--;
                }
                sibling=sibling.getNextSibling();
        }
        return null;
   }


   /**
    * @param sibling
    * @param nodeName
    * @param number
    * @return nodes with the constrain
    */
   public static Text selectDsNodeText(Node sibling, String nodeName, int number) {
            Node n=selectDsNode(sibling,nodeName,number);
        if (n==null) {
                return null;
        }
        n=n.getFirstChild();
        while (n!=null && n.getNodeType()!=Node.TEXT_NODE) {
                n=n.getNextSibling();
        }
        return (Text)n;
   }

   /**
    * @param sibling
    * @param uri
    * @param nodeName
    * @param number
    * @return nodes with the constrain
    */
   public static Text selectNodeText(Node sibling, String uri, String nodeName, int number) {
        Node n=selectNode(sibling,uri,nodeName,number);
    if (n==null) {
        return null;
    }
    n=n.getFirstChild();
    while (n!=null && n.getNodeType()!=Node.TEXT_NODE) {
        n=n.getNextSibling();
    }
    return (Text)n;
   }

   /**
    * @param sibling
    * @param uri
    * @param nodeName
    * @param number
    * @return nodes with the constrain
    */
   public static Element selectNode(Node sibling, String uri,String nodeName, int number) {
        while (sibling!=null) {
                if (nodeName.equals(sibling.getLocalName())
                                && uri.equals(sibling.getNamespaceURI())) {
                        if (number==0){
                                return (Element)sibling;
                        }
                        number--;
                }
                sibling=sibling.getNextSibling();
        }
        return null;
   }

   /**
    * @param sibling
    * @param nodeName
    * @return nodes with the constrain
    */
   public static Element[] selectDsNodes(Node sibling,String nodeName) {
     return selectNodes(sibling,Constants.SignatureSpecNS,nodeName);
   }

   /**
    * @param sibling
    * @param uri
    * @param nodeName
    * @return nodes with the constrain
    */
    public static Element[] selectNodes(Node sibling,String uri,String nodeName) {
        int size=20;
        Element[] a= new Element[size];
        int curr=0;
        //List list=new ArrayList();
        while (sibling!=null) {
                if (nodeName.equals(sibling.getLocalName())
                                && uri.equals(sibling.getNamespaceURI())) {
                        a[curr++]=(Element)sibling;
                        if (size<=curr) {
                                int cursize= size<<2;
                                Element []cp=new Element[cursize];
                                System.arraycopy(a,0,cp,0,size);
                                a=cp;
                                size=cursize;
                        }
                }
                sibling=sibling.getNextSibling();
        }
        Element []af=new Element[curr];
        System.arraycopy(a,0,af,0,curr);
        return af;
   }

   /**
    * @param signatureElement
    * @param inputSet
    * @return nodes with the constrain
    */
    public static Set excludeNodeFromSet(Node signatureElement, Set inputSet) {
          Set resultSet = new HashSet();
          Iterator iterator = inputSet.iterator();

          while (iterator.hasNext()) {
            Node inputNode = (Node) iterator.next();

            if (!XMLUtils
                    .isDescendantOrSelf(signatureElement, inputNode)) {
               resultSet.add(inputNode);
            }
         }
         return resultSet;
     }

   /**
    * Returns true if the descendantOrSelf is on the descendant-or-self axis
    * of the context node.
    *
    * @param ctx
    * @param descendantOrSelf
    * @return true if the node is descendant
    */
   static public boolean isDescendantOrSelf(Node ctx, Node descendantOrSelf) {

      if (ctx == descendantOrSelf) {
         return true;
      }

      Node parent = descendantOrSelf;

      while (true) {
         if (parent == null) {
            return false;
         }

         if (parent == ctx) {
            return true;
         }

         if (parent.getNodeType() == Node.ATTRIBUTE_NODE) {
            parent = ((Attr) parent).getOwnerElement();
         } else {
            parent = parent.getParentNode();
         }
      }
   }
}
