All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.crabshue.commons.xslt.RelativeXsltUriResolver Maven / Gradle / Ivy

package com.crabshue.commons.xslt;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Stack;

import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import com.crabshue.commons.exceptions.SystemException;
import com.crabshue.commons.xslt.exceptions.XsltErrorContext;
import com.crabshue.commons.xslt.exceptions.XsltErrorType;
import lombok.NonNull;

/**
 * A URI resolver for resources relative to the current XSLT.
 */
public class RelativeXsltUriResolver implements URIResolver {

    private Stack xsltFileStack = new Stack<>();

    RelativeXsltUriResolver(@NonNull URI currentXsltUri) {

        this.xsltFileStack.push(currentXsltUri);
    }

    @Override
    public Source resolve(@NonNull final String s,
                          @NonNull final String s1) throws TransformerException {

        URI currentXsltUri;
        try {
            while (!uriReferenceExists((currentXsltUri = resolveUri(xsltFileStack.peek(), s))) && !xsltFileStack.empty()) {

                xsltFileStack.pop();
            }
            xsltFileStack.push(currentXsltUri);

            return new StreamSource(currentXsltUri.toURL().openStream());
        } catch (IOException e) {
            throw new SystemException(XsltErrorType.ERROR_FINDING_XSLT, e)
                .addContextValue(XsltErrorContext.XSLT, s);
        }
    }

    /**
     * Resolve a path against an URI (even when opaque, i.e. in a jar).
     *
     * @param uri the URI.
     * @param s   the path.
     * @return the resolved URI.
     */
    private URI resolveUri(@NonNull final URI uri,
                           @NonNull final String s) {

        // if URI describes a resource inside a jar, resolve URI manually.
        return uri.isOpaque() ?
            URI.create(FilenameUtils.getFullPath(uri.toString()) + s) : uri.resolve(s);
    }

    private boolean uriReferenceExists(@NonNull final URI uri) {

        InputStream inputStream = null;
        try {
            inputStream = uri.toURL().openStream();
        } catch (IOException e) {
            return false;
        } finally {
            if (inputStream != null) {
                IOUtils.closeQuietly(inputStream);
            }
        }
        return true;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy