/**
* Copyright (C) 2010 Orbeon, Inc.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version
* 2.1 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 Lesser General Public License for more details.
*
* The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
*/
package org.orbeon.oxf.xforms.processor;
import org.orbeon.dom.Document;
import org.orbeon.oxf.common.OXFException;
import org.orbeon.oxf.common.OrbeonLocationException;
import org.orbeon.oxf.http.Credentials;
import org.orbeon.oxf.pipeline.api.PipelineContext;
import org.orbeon.oxf.processor.ProcessorImpl;
import org.orbeon.oxf.processor.URIProcessorOutputImpl;
import org.orbeon.oxf.processor.transformer.TransformerURIResolver;
import org.orbeon.oxf.resources.URLFactory;
import org.orbeon.oxf.util.IndentedLogger;
import org.orbeon.oxf.xforms.Loggers;
import org.orbeon.oxf.xml.TransformerUtils;
import org.orbeon.oxf.xml.XMLParsing;
import org.orbeon.oxf.xml.XMLReaderToReceiver;
import org.orbeon.oxf.xml.dom4j.LocationData;
import org.orbeon.saxon.Configuration;
import org.orbeon.saxon.om.DocumentInfo;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import javax.xml.transform.TransformerException;
import javax.xml.transform.sax.SAXSource;
import java.net.URL;
/**
* URI resolver used during XForms initialization.
*
* This URI resolver is able to use a username and password for HTTP and HTTPS, and works in conjunction with
* URIProcessorOutputImpl.
*/
public class XFormsURIResolver extends TransformerURIResolver {
private static final IndentedLogger indentedLogger = Loggers.getIndentedLogger("resolver");
private URIProcessorOutputImpl processorOutput;
public XFormsURIResolver(ProcessorImpl processor, URIProcessorOutputImpl processorOutput, PipelineContext pipelineContext,
String prohibitedInput, XMLParsing.ParserConfiguration parserConfiguration) {
super(processor, pipelineContext, prohibitedInput, parserConfiguration);
this.processorOutput = processorOutput;
}
@Override
public SAXSource resolve(String href, String base) throws TransformerException {
// Use global definition for headers to forward
return resolve(href, base, null);
}
public SAXSource resolve(String href, String base, final Credentials credentials) throws TransformerException {
final String inputName = ProcessorImpl.getProcessorInputSchemeInputName(href);
if (inputName != null) {
// Use parent resolver if accessing a processor input
return super.resolve(href, base);
} else {
// This is a regular URL
final URL url = URLFactory.createURL(base, href);
final String protocol = url.getProtocol();
final boolean isHttpProtocol = protocol.equals("http") || protocol.equals("https");
if (isHttpProtocol) {
// Override the behavior to read into the state
final String urlString = url.toExternalForm();
final URIProcessorOutputImpl.URIReferencesState state = (URIProcessorOutputImpl.URIReferencesState) getProcessor().getState(getPipelineContext());
// First, put in state if necessary
processorOutput.readURLToStateIfNeeded(getPipelineContext(), url, state, credentials);
// Then try to read from state
if (state.isDocumentSet(urlString, credentials)) {// not sure why this would not be the case
// This means the document requested is already available. We use the cached document.
final XMLReader xmlReader = new XMLReaderToReceiver() {
public void parse(String systemId) throws SAXException {
state.getDocument(urlString, credentials).replay(createXMLReceiver());
}
};
if (indentedLogger.isDebugEnabled())
indentedLogger.logDebug("", "resolving resource through initialization resolver", "uri", urlString);
return new SAXSource(xmlReader, new InputSource(urlString));
} else {
throw new OXFException("Cannot find document in state for URI: " + urlString);
}
} else {
// Use parent resolver for other protocols
return super.resolve(href, base);
}
}
}
public Document readAsDom4j(String urlString, Credentials credentials) {
try {
final SAXSource source = (SAXSource) resolve(urlString, null, credentials);
// XInclude handled by source if needed
return TransformerUtils.readDom4j(source, false);
} catch (Exception e) {
throw OrbeonLocationException.wrapException(e, new LocationData(urlString, -1, -1));
}
}
public DocumentInfo readAsTinyTree(Configuration configuration, String urlString, Credentials credentials) {
try {
final SAXSource source = (SAXSource) resolve(urlString, null, credentials);
// XInclude handled by source if needed
return TransformerUtils.readTinyTree(configuration, source, false);
} catch (Exception e) {
throw OrbeonLocationException.wrapException(e, new LocationData(urlString, -1, -1));
}
}
}