/*
 * 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.
 */

/* $Id: AFPStreamer.java 1681394 2015-05-23 22:51:40Z adelmelle $ */

package org.apache.fop.afp;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.io.TempResourceURIGenerator;

import org.apache.fop.afp.modca.ResourceGroup;
import org.apache.fop.afp.modca.StreamedResourceGroup;
import org.apache.fop.apps.io.InternalResourceResolver;

Manages the streaming of the AFP output
/** * Manages the streaming of the AFP output */
public class AFPStreamer implements Streamable {
Static logging instance
/** Static logging instance */
private static final Log LOG = LogFactory.getLog(AFPStreamer.class); private static final String DEFAULT_EXTERNAL_RESOURCE_FILENAME = "resources.afp"; private static final TempResourceURIGenerator TEMP_URI_GENERATOR = new TempResourceURIGenerator("AFPDataStream_"); private final Factory factory; private final InternalResourceResolver resourceResolver;
A mapping of external resource destinations to resource groups
/** A mapping of external resource destinations to resource groups */
private final Map<URI, ResourceGroup> pathResourceGroupMap = new HashMap<URI, ResourceGroup>(); private StreamedResourceGroup printFileResourceGroup;
Sets the default resource group file path
/** Sets the default resource group file path */
private URI defaultResourceGroupUri; private final URI tempUri;
temporary document outputstream
/** temporary document outputstream */
private OutputStream tempOutputStream;
the final outputstream
/** the final outputstream */
private OutputStream outputStream; private DataStream dataStream;
Main constructor
Params:
  • factory – a factory
  • resourceResolver – resource resolver
/** * Main constructor * * @param factory a factory * @param resourceResolver resource resolver */
public AFPStreamer(Factory factory, InternalResourceResolver resourceResolver) { this.factory = factory; this.resourceResolver = resourceResolver; this.tempUri = TEMP_URI_GENERATOR.generate(); defaultResourceGroupUri = URI.create(DEFAULT_EXTERNAL_RESOURCE_FILENAME); }
Creates a new DataStream
Params:
  • paintingState – the AFP painting state
Throws:
  • IOException – thrown if an I/O exception of some sort has occurred
Returns:a new DataStream
/** * Creates a new DataStream * * @param paintingState the AFP painting state * @return a new {@link DataStream} * @throws IOException thrown if an I/O exception of some sort has occurred */
public DataStream createDataStream(AFPPaintingState paintingState) throws IOException { this.tempOutputStream = new BufferedOutputStream(resourceResolver.getOutputStream(tempUri)); this.dataStream = factory.createDataStream(paintingState, tempOutputStream); return dataStream; }
Sets the default resource group URI.
Params:
  • uri – the default resource group URI
/** * Sets the default resource group URI. * * @param uri the default resource group URI */
public void setDefaultResourceGroupUri(URI uri) { this.defaultResourceGroupUri = uri; }
Returns the resource group for a given resource info
Params:
  • level – a resource level
Returns:a resource group for the given resource info
/** * Returns the resource group for a given resource info * * @param level a resource level * @return a resource group for the given resource info */
public ResourceGroup getResourceGroup(AFPResourceLevel level) { ResourceGroup resourceGroup = null; if (level.isInline()) { // no resource group for inline level return null; } if (level.isExternal()) { URI uri = level.getExternalURI(); if (uri == null) { LOG.warn("No file path provided for external resource, using default."); uri = defaultResourceGroupUri; } resourceGroup = pathResourceGroupMap.get(uri); if (resourceGroup == null) { OutputStream os = null; try { os = new BufferedOutputStream(resourceResolver.getOutputStream(uri)); } catch (IOException ioe) { LOG.error("Failed to create/open external resource group for uri '" + uri + "'"); } finally { if (os != null) { resourceGroup = factory.createStreamedResourceGroup(os); pathResourceGroupMap.put(uri, resourceGroup); } } } } else if (level.isPrintFile()) { if (printFileResourceGroup == null) { // use final outputstream for print-file resource group printFileResourceGroup = factory.createStreamedResourceGroup(outputStream); } resourceGroup = printFileResourceGroup; } else { // resource group in afp document datastream resourceGroup = dataStream.getResourceGroup(level); } return resourceGroup; }
Closes off the AFP stream writing the document stream
Throws:
  • IOException – if an an I/O exception of some sort has occurred
/** * Closes off the AFP stream writing the document stream * * @throws IOException if an an I/O exception of some sort has occurred */
// write out any external resource groups public void close() throws IOException { for (ResourceGroup resourceGroup : pathResourceGroupMap.values()) { // TODO - Why not a Map<URI, StreamedResourceGroup>, if all the elements are expected to be of that type? assert (resourceGroup instanceof StreamedResourceGroup); ((StreamedResourceGroup) resourceGroup).close(); } // close any open print-file resource group if (printFileResourceGroup != null) { printFileResourceGroup.close(); } // write out document writeToStream(outputStream); outputStream.close(); }
Sets the final outputstream
Params:
  • outputStream – an outputstream
/** * Sets the final outputstream * * @param outputStream an outputstream */
public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; }
{@inheritDoc}
/** {@inheritDoc} */
public void writeToStream(OutputStream os) throws IOException { tempOutputStream.close(); InputStream tempInputStream = resourceResolver.getResource(tempUri); IOUtils.copy(tempInputStream, os); //TODO this should notify the stream provider that it is safe to delete the temp data tempInputStream.close(); os.flush(); } }