/* ESXX - The friendly ECMAscript/XML Application Server Copyright (C) 2007-2015 Martin Blom <martin@blom.org> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.esxx.util; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Collection; import java.util.LinkedList; import javax.xml.transform.Source; import javax.xml.transform.TransformerException; import org.esxx.ESXX; import org.w3c.dom.ls.LSException; import org.w3c.dom.ls.LSInput; import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; public class URIResolver implements javax.xml.transform.URIResolver, LSResourceResolver, EntityResolver { public URIResolver(ESXX esxx, URI base_uri, Collection<URI> log_visited) { this.esxx = esxx; baseURI = base_uri; logVisited = log_visited; openedStreams = new LinkedList<InputStream>(); } public void closeAllStreams() { for (InputStream is : openedStreams) { try { is.close(); } catch (IOException ignored) {} } } @Override /* URIResolver */ public Source resolve(String href, String base) throws TransformerException { try { URI uri = getURI(href, base); return new javax.xml.transform.stream.StreamSource(getIS(uri), uri.toString()); } catch (IOException ex) { throw new TransformerException("Failed to resolve resource " + href + ": " + ex.getMessage(), ex); } } @Override /* LSResourceResolver */ public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { try { LSInput lsi = esxx.getDOMImplementationLS().createLSInput(); URI uri = getURI(systemId, baseURI); lsi.setSystemId(uri.toString()); lsi.setByteStream(getIS(uri)); return lsi; } catch (IOException ex) { throw new LSException(LSException.PARSE_ERR, "Failed to resolve resource " + systemId + ": " + ex.getMessage()); } } @Override /* EntityResolver */ public InputSource resolveEntity(String publicId, String systemId) throws IOException { if (systemId == null) { throw new IOException("System ID missing"); } // return new InputSource(getIS(getURI(systemId, null))); URI uri = getURI(systemId, null); InputSource result = new InputSource(getIS(uri)); result.setSystemId(uri.toString()); return result; } private URI getURI(String uri, String base_uri) throws IOException { try { URI base = baseURI; if (base_uri != null) { base = new URI(base_uri); } return base.resolve(uri); } catch (java.net.URISyntaxException ex) { throw new IOException(ex.getMessage(), ex); } } private InputStream getIS(URI uri) throws IOException { InputStream is = esxx.openCachedURI(uri); if (logVisited != null) { // Log visited URIs if successfully opened logVisited.add(uri); } openedStreams.add(is); return is; } private ESXX esxx; private URI baseURI; private Collection<URI> logVisited; private Collection<InputStream> openedStreams; }