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