String inclusionSystemId = url.toExternalForm();
// check to see if the document that is about to be processed has
// already been included. If it has then
if (isCyclicInclusion(url)) {
// cannot enter a cyclic inclusion
Locator locator = context.getCurrentLocator();
CyclicInclusionException ce =
new CyclicInclusionException("Cyclic Inclusion encountered " +
inclusionSystemId, locator);
target.fatalError(ce);
return;
}
// As this XML Document can contain pipeline mark-up we need
// to ensure that the parsed document enters a pipeline so that
// it is processed correctly.
XMLPipelineFactory factory = context.getPipelineFactory();
// create a new pipeline.
XMLPipeline pipeline = factory.createDynamicPipeline(context);
XMLProcess cup = factory.createContextUpdatingProcess();
cup.setPipeline(target.getPipeline());
XMLProcess pipelineProcess = pipeline.getPipelineProcess();
cup.setNextProcess(pipelineProcess);
// set up the XMLReader so that the inclusion can be read.
XMLReader reader = createXMLReader();
reader.setErrorHandler(cup);
reader.setContentHandler(cup);
// Chain the new pipeline process to the target process
pipelineProcess.setNextProcess(target);
URLContentManager manager = PipelineURLContentManager.retrieve(
context);
try {
final URLConfiguration urlConfiguration =
URLConfigurationFactory.getURLConfiguration(url, context);
URLContent content =
manager.getURLContent(url, timeout, urlConfiguration);
// InputSource for content that we are trying to include.
InputSource source = new InputSource(content.getInputStream());
// Ensure that the systemID property is set for the
// InputSource. The XMLReader will need this in order to
// resolve relative URIs
source.setSystemId(inclusionSystemId);
// add dependency to the dependency context
final DependencyContext dependencyContext =
context.getDependencyContext();
if (dependencyContext != null &&
dependencyContext.isTrackingDependencies()) {
dependencyContext.addDependency(content.getDependency());
}
// perform the inclusion
reader.parse(source);
} catch (SAXException e) {
// If the parser encounters a truly fatal error (e.g. an entity it
// does not understand), it will throw an exception even if the
// pipeline try operation prevents the error handler from doing so.
// This basically defeats our currently useless try operation and
// allows the entire pipeline to crash. So we must catch any
// exceptions here manually and deal with them ourselves. Sigh.
//
// If we fixed VBM:2004030305 then this code would hopefully not be
// required.
uridFetchTransaction.stop(MonitoredTransaction.FAILED,
url.toExternalForm());
// If the pipeline is already handling this error,
if (context.inErrorRecoveryMode()) {
// Then we assume that there is a containing try operation that
// needs help to avoid the pipeline crashing, so we need to
// mask the exception. So just continue on and hope the
// pipeline error handling will save us. Note that we cannot
// re-report it via fatalError or the flow control manager
// objects.
if (logger.isDebugEnabled()) {
logger.debug("Fetch encountered XML parsing exception " +
"while error recovery is in progress, ignoring", e);
}
} else {
// Else we assume that there is no containing try operation.
// In this case just let the exception propogate up and cause
// the pipeline to die.
if (logger.isDebugEnabled()) {
logger.debug("Fetch encountered XML parsing exception " +
"while no error recovery is in progress, rethrowing",
e);
}
throw e;
}
} catch (IOException ioe) {
uridFetchTransaction.stop(MonitoredTransaction.FAILED, url.toExternalForm());
// get hold of the current locator
Locator currentLocator = context.getCurrentLocator();
// this is a streaming error as the part of the document might
// have been included.
ResourceNotFoundException se =
new ResourceNotFoundException(