1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /**
   5  * Licensed to the Apache Software Foundation (ASF) under one
   6  * or more contributor license agreements. See the NOTICE file
   7  * distributed with this work for additional information
   8  * regarding copyright ownership. The ASF licenses this file
   9  * to you under the Apache License, Version 2.0 (the
  10  * "License"); you may not use this file except in compliance
  11  * with the License. You may obtain a copy of the License at
  12  *
  13  * http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing,
  16  * software distributed under the License is distributed on an
  17  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18  * KIND, either express or implied. See the License for the
  19  * specific language governing permissions and limitations
  20  * under the License.
  21  */
  22 package com.sun.org.apache.xpath.internal.functions;
  23 
  24 import com.sun.org.apache.xml.internal.dtm.DTM;
  25 import com.sun.org.apache.xml.internal.utils.QName;
  26 import com.sun.org.apache.xpath.internal.NodeSetDTM;
  27 import com.sun.org.apache.xpath.internal.XPathContext;
  28 import com.sun.org.apache.xpath.internal.objects.XNodeSet;
  29 import com.sun.org.apache.xpath.internal.objects.XObject;
  30 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  31 import java.util.List;
  32 import javax.xml.transform.TransformerException;
  33 import org.w3c.dom.Document;
  34 import org.w3c.dom.Node;
  35 
  36 /**
  37  * Execute the XML Signature here() function.
  38  *
  39  * @LastModified: Oct 2017
  40  */
  41 public final class FuncHere extends Function {
  42 
  43     private static final long serialVersionUID = 4328660760070034592L;
  44 
  45     @Override
  46     public XObject execute(XPathContext xctxt) throws TransformerException {
  47         Node xpathOwnerNode = (Node)xctxt.getOwnerObject();
  48         if (xpathOwnerNode == null) {
  49             return null;
  50         }
  51 
  52         int xpathOwnerNodeDTM = xctxt.getDTMHandleFromNode(xpathOwnerNode);
  53         int currentNode = xctxt.getCurrentNode();
  54         DTM dtm = xctxt.getDTM(currentNode);
  55         int docContext = dtm.getDocument();
  56 
  57         if (docContext == DTM.NULL) {
  58             error(xctxt, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC, null);
  59         }
  60 
  61         // check whether currentNode and the node containing the XPath
  62         // expression are in the same document
  63         Document currentDoc = getOwnerDocument(dtm.getNode(currentNode));
  64         Document xpathOwnerDoc = getOwnerDocument(xpathOwnerNode);
  65 
  66         if (currentDoc != xpathOwnerDoc) {
  67             throw new TransformerException("Owner documents differ");
  68         }
  69 
  70         XNodeSet nodes = new XNodeSet(xctxt.getDTMManager());
  71         NodeSetDTM nodeSet = nodes.mutableNodeset();
  72 
  73         int hereNode = DTM.NULL;
  74 
  75         switch (dtm.getNodeType(xpathOwnerNodeDTM)) {
  76 
  77             case Node.ATTRIBUTE_NODE:
  78             case Node.PROCESSING_INSTRUCTION_NODE: {
  79                 // returns a node-set containing the attribute /  processing
  80                 // instruction node
  81                 hereNode = xpathOwnerNodeDTM;
  82                 nodeSet.addNode(hereNode);
  83                 break;
  84             }
  85             case Node.TEXT_NODE : {
  86                 // returns a node-set containing the parent element of the
  87                 // text node that directly bears the XPath expression
  88                 hereNode = dtm.getParent(xpathOwnerNodeDTM);
  89                 nodeSet.addNode(hereNode);
  90                 break;
  91             }
  92             default :
  93                 break;
  94         }
  95 
  96         /** $todo$ Do I have to do this detach() call? */
  97         nodeSet.detach();
  98 
  99         return nodes;
 100     }
 101 
 102     private static Document getOwnerDocument(Node node) {
 103         if (node.getNodeType() == Node.DOCUMENT_NODE) {
 104             return (Document)node;
 105         }
 106         return node.getOwnerDocument();
 107     }
 108 
 109     @Override
 110     public void fixupVariables(List<QName> vars, int globalsSize) { }
 111 }