nl.armatiek.xslweb.saxon.functions.ExtensionFunctionCall.java Source code

Java tutorial

Introduction

Here is the source code for nl.armatiek.xslweb.saxon.functions.ExtensionFunctionCall.java

Source

package nl.armatiek.xslweb.saxon.functions;

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import net.sf.saxon.Configuration;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.dom.DocumentWrapper;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.om.AxisInfo;
import net.sf.saxon.om.Item;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.om.SequenceTool;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.om.ZeroOrMore;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import net.sf.saxon.value.AtomicValue;
import net.sf.saxon.value.Base64BinaryValue;
import net.sf.saxon.value.BigIntegerValue;
import net.sf.saxon.value.BooleanValue;
import net.sf.saxon.value.DateTimeValue;
import net.sf.saxon.value.DecimalValue;
import net.sf.saxon.value.DoubleValue;
import net.sf.saxon.value.FloatValue;
import net.sf.saxon.value.Int64Value;
import net.sf.saxon.value.ObjectValue;
import net.sf.saxon.value.StringValue;
import nl.armatiek.xslweb.configuration.Attribute;
import nl.armatiek.xslweb.configuration.Definitions;
import nl.armatiek.xslweb.configuration.WebApp;
import nl.armatiek.xslweb.utils.Closeable;

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Node;

/**
 * @author Maarten Kroon
 *
 */
public abstract class ExtensionFunctionCall extends net.sf.saxon.lib.ExtensionFunctionCall {

    // http://en.wikipedia.org/wiki/XQuery_API_for_Java
    protected AtomicValue convertJavaObjectToAtomicValue(Object value) throws XPathException {
        try {
            AtomicValue atomicValue;
            if (value == null) {
                return null;
            } else if (value instanceof String) {
                atomicValue = new StringValue((String) value);
            } else if (value instanceof Boolean) {
                atomicValue = BooleanValue.get(((Boolean) value).booleanValue());
            } else if (value instanceof Integer) {
                atomicValue = new Int64Value(((Integer) value).intValue());
            } else if (value instanceof Long) {
                atomicValue = new Int64Value(((Long) value).longValue());
            } else if (value instanceof Double) {
                atomicValue = new DoubleValue(((Double) value).doubleValue());
            } else if (value instanceof Float) {
                atomicValue = new FloatValue(((Float) value).floatValue());
            } else if (value instanceof Date) { // includes java.sql.Date, java.sql.Time and java.sql.Timestamp
                Calendar calendar = new GregorianCalendar();
                calendar.setTime((Date) value);
                atomicValue = new DateTimeValue(calendar, true);
            } else if (value instanceof Byte) {
                atomicValue = new Int64Value(((Byte) value).byteValue());
            } else if (value instanceof Short) {
                atomicValue = new Int64Value(((Short) value).shortValue());
            } else if (value instanceof BigDecimal) {
                atomicValue = new DecimalValue((BigDecimal) value);
            } else if (value instanceof BigInteger) {
                atomicValue = new BigIntegerValue((BigInteger) value);
            } else if (value instanceof byte[]) {
                atomicValue = new Base64BinaryValue((byte[]) value);
            } else if (value instanceof java.sql.Clob) {
                atomicValue = new StringValue(IOUtils.toString(((java.sql.Clob) value).getCharacterStream()));
            } else if (value instanceof java.sql.Blob) {
                atomicValue = new Base64BinaryValue(IOUtils.toByteArray(((java.sql.Blob) value).getBinaryStream()));
            } else if (value instanceof java.sql.SQLXML) {
                atomicValue = new StringValue(IOUtils.toString(((java.sql.SQLXML) value).getCharacterStream())); // TODO: node() instead of atomic?
            } else if (value instanceof InputStream) {
                atomicValue = new StringValue(IOUtils.toString((InputStream) value, "UTF-8")); // TODO: get encoding from somewhere
            } else if (value instanceof Reader) {
                atomicValue = new StringValue(IOUtils.toString((Reader) value));
            } else {
                throw new XPathException("Java class not supported converting Java object to AtomicValue ("
                        + value.getClass().toString() + ")");
            }
            return atomicValue;
        } catch (XPathException xpe) {
            throw xpe;
        } catch (Exception e) {
            throw new XPathException("Error converting Java object to AtomicValue", e);
        }
    }

    protected NodeInfo unwrapNodeInfo(NodeInfo nodeInfo) {
        if (nodeInfo != null && nodeInfo.getNodeKind() == Type.DOCUMENT) {
            nodeInfo = nodeInfo.iterateAxis(AxisInfo.CHILD, NodeKindTest.ELEMENT).next();
        }
        return nodeInfo;
    }

    protected void serialize(NodeInfo nodeInfo, Result result, Properties outputProperties) throws XPathException {
        try {
            TransformerFactory factory = new TransformerFactoryImpl();
            Transformer transformer = factory.newTransformer();
            if (outputProperties != null) {
                transformer.setOutputProperties(outputProperties);
            }
            transformer.transform(nodeInfo, result);
        } catch (Exception e) {
            throw new XPathException(e);
        }
    }

    protected void serialize(Sequence seq, Writer w, Properties outputProperties) throws XPathException {
        try {
            SequenceIterator iter = seq.iterate();
            Item item;
            while ((item = iter.next()) != null) {
                if (item instanceof NodeInfo) {
                    serialize((NodeInfo) item, new StreamResult(w), outputProperties);
                } else {
                    w.append(item.getStringValue());
                }
            }
        } catch (Exception e) {
            throw new XPathException(e);
        }
    }

    protected void serialize(Sequence seq, OutputStream os, Properties outputProperties) throws XPathException {
        String encoding = "UTF-8";
        if (outputProperties != null) {
            encoding = outputProperties.getProperty("encoding", encoding);
        }
        try {
            SequenceIterator iter = seq.iterate();
            Item item;
            while ((item = iter.next()) != null) {
                if (item instanceof NodeInfo) {
                    serialize((NodeInfo) item, new StreamResult(os), outputProperties);
                } else {
                    new OutputStreamWriter(os, encoding).append(item.getStringValue());
                }
            }
        } catch (Exception e) {
            throw new XPathException(e);
        }
    }

    protected String serialize(NodeInfo nodeInfo, Properties props) throws XPathException {
        StringWriter sw = new StringWriter();
        serialize(nodeInfo, new StreamResult(sw), props);
        return sw.toString();
    }

    protected String serialize(NodeInfo nodeInfo) throws XPathException {
        Properties props = new Properties();
        props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        props.setProperty(OutputKeys.METHOD, "xml");
        props.setProperty(OutputKeys.INDENT, "no");
        return serialize(nodeInfo, props);
    }

    protected Properties getOutputProperties(NodeInfo paramsElem) {
        Properties props = new Properties();
        paramsElem = unwrapNodeInfo(paramsElem);
        AxisIterator iter = paramsElem.iterateAxis(AxisInfo.CHILD, NodeKindTest.ELEMENT);
        NodeInfo paramElem;
        while ((paramElem = iter.next()) != null) {
            props.put(paramElem.getLocalPart(), paramElem.getAttributeValue("", "value"));
        }
        return props;
    }

    protected Collection<Attribute> sequenceToAttributeCollection(Sequence seq) throws XPathException {
        ArrayList<Attribute> attrs = new ArrayList<Attribute>();
        Item item;
        SequenceIterator iter = seq.iterate();
        while ((item = iter.next()) != null) {
            Object value;
            String type;
            boolean isSerialized;
            if (item instanceof NodeInfo) {
                value = serialize((NodeInfo) item);
                type = "node()";
                isSerialized = true;
            } else {
                value = SequenceTool.convertToJava(item);
                ItemType itemType = Type.getItemType(item, null);
                type = itemType.toString();
                isSerialized = false;
            }
            attrs.add(new Attribute(value, type, isSerialized));
        }
        return attrs;
    }

    protected ZeroOrMore<Item> attributeCollectionToSequence(Collection<Attribute> attrs, XPathContext context)
            throws Exception {
        ArrayList<Item> results = new ArrayList<Item>();
        if (attrs != null) {
            for (Attribute attr : attrs) {
                Object value = attr.getValue();
                if (value instanceof Node) {
                    results.add(source2NodeInfo(new DOMSource((Node) value), context.getConfiguration()));
                } else {
                    results.add(convertJavaObjectToAtomicValue(value));
                }
            }
        }
        return new ZeroOrMore<Item>(results);
    }

    protected NodeInfo source2NodeInfo(Source source, Configuration configuration) {
        Node node = ((DOMSource) source).getNode();
        String baseURI = source.getSystemId();
        DocumentWrapper documentWrapper = new DocumentWrapper(node.getOwnerDocument(), baseURI, configuration);
        return documentWrapper.wrap(node);
    }

    protected HttpServletRequest getRequest(XPathContext context) {
        return (HttpServletRequest) ((ObjectValue<?>) context.getController()
                .getParameter(new StructuredQName("", Definitions.NAMESPACEURI_XSLWEB_REQUEST, "request")))
                        .getObject();
    }

    protected HttpServletResponse getResponse(XPathContext context) {
        return (HttpServletResponse) ((ObjectValue<?>) context.getController()
                .getParameter(new StructuredQName("", Definitions.NAMESPACEURI_XSLWEB_RESPONSE, "response")))
                        .getObject();
    }

    protected HttpSession getSession(XPathContext context) {
        return getRequest(context).getSession();
    }

    protected WebApp getWebApp(XPathContext context) {
        return (WebApp) ((ObjectValue<?>) context.getController()
                .getParameter(new StructuredQName("", Definitions.NAMESPACEURI_XSLWEB_WEBAPP, "webapp")))
                        .getObject();
    }

    @SuppressWarnings("unchecked")
    protected void addCloseable(Closeable closeable, XPathContext context) {
        HttpServletRequest request = getRequest(context);
        List<Closeable> closeables = (List<Closeable>) request.getAttribute("xslweb-closeables");
        if (closeables == null) {
            closeables = new ArrayList<Closeable>();
            request.setAttribute("xslweb-closeables", closeables);
        }
        closeables.add(closeable);
    }

}