com.adobe.xfa.agent.Agent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.agent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.List;
import java.util.StringTokenizer;
import com.adobe.xfa.AppModel;
import com.adobe.xfa.Attribute;
import com.adobe.xfa.ArrayNodeList;
import com.adobe.xfa.Document;
import com.adobe.xfa.Element;
import com.adobe.xfa.LogMessage;
import com.adobe.xfa.LogMessenger;
import com.adobe.xfa.Model;
import com.adobe.xfa.ModelFactory;
import com.adobe.xfa.Node;
import com.adobe.xfa.NodeList;
import com.adobe.xfa.Packet;
import com.adobe.xfa.STRS;
import com.adobe.xfa.XFA;
import com.adobe.xfa.XSLTranslator;
import com.adobe.xfa.configuration.ConfigurationModel;
import com.adobe.xfa.configuration.ConfigurationModelFactory;
import com.adobe.xfa.configuration.ConfigurationValue;
import com.adobe.xfa.configuration.ConfigurationSchema;
import com.adobe.xfa.connectionset.ConnectionSetModel;
import com.adobe.xfa.data.DataModel;
import com.adobe.xfa.data.DataModelFactory;
import com.adobe.xfa.service.storage.XMLStorage;
import com.adobe.xfa.service.storage.PacketHandler;
import com.adobe.xfa.template.TemplateModel;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.BooleanHolder;
import com.adobe.xfa.ut.StringUtils;
import com.adobe.xfa.ut.trace.Trace;
/**
* A base class to represent XFA agents. Derived classes would
* embody significant XFA form processor capabilities.
*
* @exclude from published api.
*
*/
public abstract class Agent implements PacketHandler {
/**
* Completion code for success.
*/
public static final int SUCCESS = 0;
/**
* Completion code for failure.
*/
public static final int FAIL = 1;
/**
* Completion code for success with warning.
*/
public static final int SUCCESS_WITH_WARNINGS = 2;
/**
* Completion code for success with information.
*/
public static final int SUCCESS_WITH_INFORMATION = 3;
/*
* Model Types
*/
/**
* @exclude from published api.
*/
protected static final int UNKNOWN = 0;
/**
* @exclude from published api.
*/
protected static final int CONFIG = 1;
/**
* @exclude from published api.
*/
protected static final int DATA = 2;
/**
* @exclude from published api.
*/
protected static final int TEMPLATE = 3;
/**
* @exclude from published api.
*/
protected static final int XDC = 4;
/**
* @exclude from published api.
*/
protected static final int SOURCESET = 5;
/**
* @exclude from published api.
*/
protected static final int CONNECTIONSET = 6;
/**
* @exclude from published api.
*/
protected static final int XDP = 7;
/**
* @exclude from published api.
*/
protected static final int LOCALESET = 8;
/**
* @exclude from published api.
*/
protected static final int XSL = 9;
private boolean mbXDPLoadedConfig = false;
private boolean mbXDPLoadedConnectionSet = false;
private boolean mbXDPLoadedData = false;
//private boolean mbXDPLoadedLocaleSet = false;
private boolean mbXDPLoadedSourceSet = false;
private boolean mbXDPLoadedTemplate = false;
private boolean mbXDPLoadedXDC = false;
//private boolean mbXDPLoadedXSL = false;
private boolean mbIsDataIncremental = false;
private AppModel moAppModel = null;
private ConfigurationModelFactory moConfigFactory = null;
private DataModelFactory moDataFactory = null;
private final LogMessenger moMessenger = new LogMessenger();
// Javaport: TODO: Ensure that these streams get closed (e.g., when an exception is thrown)
private InputStream moConfigurationStream = null;
private InputStream moXDPStream = null;
private String msPacketList = null;
private static final Trace goGeneralTrace
= new Trace("general", ResId.GeneralTraceHelp);
/**
* Instantiates an agent.
*/
public Agent() {
//mbXDPLoadedConfig = false;
//mbXDPLoadedConnectionSet = false;
//mbXDPLoadedData = false;
//mbXDPLoadedLocaleSet = false;
//mbXDPLoadedSourceSet = false;
//mbXDPLoadedTemplate = false;
//mbXDPLoadedXDC = false;
//mbXDPLoadedXSL = false;
reset();
}
/**
* @exclude from published api.
*/
protected void reset() {
moAppModel = new AppModel(moMessenger);
moDataFactory = new DataModelFactory();
moAppModel.addFactory(moDataFactory);
moConfigFactory = new ConfigurationModelFactory();
moAppModel.addFactory(moConfigFactory);
setPacketList("");
}
/**
* Activates tracing based on configuration file settings
*/
void activateTracing() {
}
/**
* @exclude from published api.
*/
protected void checkXDPOptions(BooleanHolder oSaveAsXDP,
BooleanHolder oIsMergedXDP,
BooleanHolder oEmbedRenderedOutput) {
Node oContextNode = getContextNode();
oSaveAsXDP.value = false;
oIsMergedXDP.value = false;
//
// native
//
String sOutputType = "native";
Node oResolvedNode = null;
if (oContextNode != null)
oResolvedNode = oContextNode.resolveNode("output.type");
if (oResolvedNode instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue
= (ConfigurationValue) oResolvedNode;
sOutputType = oConfigurationValue.getValue().toString();
if (sOutputType.equalsIgnoreCase("xdp")) {
oSaveAsXDP.value = true;
}
else if (sOutputType.equalsIgnoreCase("mergedXDP")) {
oSaveAsXDP.value = true;
oIsMergedXDP.value = true;
}
}
oEmbedRenderedOutput.value = false;
if (sOutputType.equalsIgnoreCase("xdp")) {
//
//
// 1
// *
//
//
oResolvedNode
= oContextNode.resolveNode("xdp.embedRenderedOutput");
if (oResolvedNode instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue
= (ConfigurationValue) oResolvedNode;
String sEmbed = oConfigurationValue.getValue().toString();
if (sEmbed.equalsIgnoreCase("1")) {
oEmbedRenderedOutput.value = true;
}
}
}
}
/**
* An XFA PacketHandler to filter out empty nodes and/or
* user-specified nodes in an XDP file.
* This method gets called for each packet in an XDP that is being loaded.
*
* @exclude from published api.
*/
public void filterPackets(Node oPacket, Object data) {
//
// Check for XFAPackets based on our factories.
// We don't touch packets we don't know about.
//
Element oPacketNode = null;
if (oPacket instanceof Element)
oPacketNode = (Element) oPacket;
if (oPacketNode != null) {
String sLocalName = oPacketNode.getLocalName();
String sPackets = getPacketList();
//
// exclude all packets listed if list starts with "-"
//
boolean bExclude = sPackets.startsWith("-");
//
// If a packet list was specified, remove any unwanted packets.
//
if (sPackets.length() != 0 && ! sPackets.equals("*")) {
boolean bInList = sPackets.contains(sLocalName);
if ((bInList && bExclude) || (! bInList && ! bExclude)) {
oPacketNode.getXMLParent().removeChild(oPacketNode);
return;
}
}
//
// packet is to be loaded, check if it corresponds to a model
//
AppModel oApp = getAppModel();
List factories = oApp.factories();
for (int i = 0; i < factories.size(); i++) {
ModelFactory oFactory = factories.get(i);
//
// root of an XFA Model,
// must call isRootName becasue isRootNode for XFA-Data
// will always return true
//
if (oFactory.isRootName(sLocalName)) {
// Remove empty models.
if (oPacketNode.getFirstXMLChild() == null) {
oPacketNode.getXMLParent().removeChild(oPacketNode);
//
// prevent further processing -- oPacketNode is gone!
//
return;
}
else if (oFactory instanceof ConfigurationModelFactory) {
// load config model
// load starting at dom peer
//
// JavaPort: we don't have an XFA DOM to load in Java.
// oApp.loadNode(oApp, oPacketNode, new Generator("", ""));
//
// set the data loading options
//
setDataLoadOptions(null);
//
// Update the messenger with any messages from
// the config DOM. These can be set to mask out
// or map messageID severities appropriately.
//
LogMessenger oMessenger = getMessenger();
if (oMessenger != null) {
oMessenger.updateMessaging(
ConfigurationModel.getConfigurationModel(oApp,
false));
}
//
// Activate trace configuration settings
//
activateTracing();
//
// We have loaded config, now remove it.
//
// JavaPort: we can't remove config from our XML DOM!
// Element oParent = oPacketNode.getParent();
// if (oParent != null)
// oParent.removeChild(oPacketNode);
return;
}
//
// Special data packets, make sure you set the data
// options prior to loading.
//
else if (oFactory instanceof DataModelFactory) {
setDataLoadOptions(null);
}
break;
}
}
}
}
/**
* Convenience method to get the XFAApp model.
* @return an XFA App model.
*
* @exclude from published api.
*/
protected AppModel getAppModel() {
return moAppModel;
}
/**
* @exclude from published api.
*/
protected int getCompletionStatus(LogMessenger oMessenger) {
int cc = SUCCESS;
int eSeverity = (oMessenger == null) ? LogMessage.MSG_FATAL_ERROR
: oMessenger.getSeverity();
switch (eSeverity) {
case LogMessage.MSG_INFORMATION:
cc = SUCCESS_WITH_INFORMATION;
break;
case LogMessage.MSG_WARNING:
case LogMessage.MSG_VALIDATION_WARNING:
case LogMessage.MSG_VALIDATION_ERROR:
cc = SUCCESS_WITH_WARNINGS;
break;
case LogMessage.MSG_FATAL_ERROR:
cc = FAIL;
}
return cc;
}
/**
* Gets the agent's configuration model.
*
* @exclude from published api.
*/
protected ConfigurationModel getConfigModel() {
return ConfigurationModel.getConfigurationModel(getAppModel(), false);
}
/**
* Gets the agent's connectionset model.
*
* @exclude from published api.
*/
protected ConnectionSetModel getConnectionSetModel() {
return ConnectionSetModel.getConnectionSetModel(getAppModel(), false);
}
/**
* Retrieve the configuration schema tag name where the config options
* are stored for this agent.
*
* @exclude from published api.
*/
public abstract String getConfigSchemaName();
/**
* return the context node represented by sContext. Create the
* config model if it doesn't exist.
*
* @exclude from published api.
*/
protected Node getContextNode() {
ConfigurationModel oConfigModel = getConfigModel();
//
// If there was no default xci file supplied and no
// xci files specified on the command line then
// create an empty XFA-Configuration DOM.
//
if (oConfigModel == null) {
oConfigModel
= ConfigurationModel.getConfigurationModel(getAppModel(),
true);
}
//
// Get node specified by SOM expression.
// Searching will start at this node.
//
return oConfigModel.getCommonNode(getConfigSchemaName());
}
/**
* Accessor for the agents data model
*
* @exclude from published api.
*/
protected DataModel getDataModel() {
for (Node node = moAppModel.getFirstXFAChild(); node != null; node = node.getNextXFASibling()) {
if (node.getClassName() == "dataModel") {
return (DataModel)node;
}
}
return null;
}
String getDefaultConfiguration(String sSchemaName) {
ConfigurationSchema oSchema = new ConfigurationSchema();
return oSchema.printConfigSchema(getConfigSchemaName(), "", false);
}
/**
* @exclude from published api.
*/
protected LogMessenger getMessenger() {
return moMessenger;
}
/**
* Get the list of XFA packets for the XDP.
*
* @exclude from published api.
*/
public String getPacketList() {
return msPacketList;
}
/**
* Gets the agent's template model.
*
* @exclude from published api.
*/
protected TemplateModel getTemplateModel() {
return TemplateModel.getTemplateModel(getAppModel(), false);
}
/**
* @exclude from published api.
*/
protected String getXDCDest(boolean bReportError /* =true */) {
// Get the destination, pdf, ps, pcl, etc.
String sXDCDest = "";
Node oContextNode = getContextNode();
if (oContextNode != null) {
Node resolvedNode = oContextNode.resolveNode("destination");
if (resolvedNode instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue
= (ConfigurationValue) resolvedNode;
sXDCDest = oConfigurationValue.getValue().toString();
}
if (bReportError && sXDCDest.length() == 0)
throw new ExFull(ResId.DestinationNotSpecifiedError);
}
return sXDCDest;
}
/*
* Return the uri from the Config dome for a specific XFA Model.
*/
@FindBugsSuppress(code="SF")
String getXFAModelConfigURI(int eType) {
StringBuilder sConfigURI = new StringBuilder();
switch (eType) {
case XDC: // For XDC it's .xdc.uri
sConfigURI.append(getXDCDest(true));
sConfigURI.append('.');
/* fallthru */
case DATA: // For these models it's .uri
case TEMPLATE:
case SOURCESET:
case CONNECTIONSET:
sConfigURI.append(getXFAModelName(eType));
sConfigURI.append('.');
/* fallthru */
case XDP: // For XDP, uri tag is at the context node level.
sConfigURI.append(XFA.URI);
/* fallthru */
case CONFIG: // Doesn't make sense for Config.
/* fallthru */
}
return sConfigURI.toString();
}
int getXFAModelMessageFileNotFound(int eType) {
switch(eType) {
case CONFIG:
return ResId.ConfigFileNotFound;
case XDC:
return ResId.XDCFileNotFound;
case TEMPLATE:
return ResId.TemplateFileNotFound;
case SOURCESET:
return ResId.SourceSetFileNotFound;
case CONNECTIONSET:
return ResId.ConnectionSetFileNotFound;
case XDP:
return ResId.XDPFileNotFound;
case DATA:
default:
return ResId.DataFileNotFound;
}
}
int getXFAModelMessageFileNotSpecified(int eType) {
switch(eType) {
case XDC:
return ResId.XDCFileNotSpecified;
case DATA:
return ResId.DataFileNotSpecified;
case TEMPLATE:
return ResId.TemplateFileNotSpecified;
case SOURCESET:
return ResId.SourceSetFileNotSpecified;
case CONNECTIONSET:
return ResId.ConnectionSetFileNotSpecified;
case XDP:
return ResId.XDPFileNotSpecified;
case CONFIG:
default:
return ResId.ConfigFileNotSpecified;
}
}
/*
* Return the name of a specific XFA Model.
* @return an interned string containing the model name.
*/
String getXFAModelName(int eType) {
switch (eType) {
case CONFIG:
return XFA.CONFIG;
case XDC:
return XFA.XDC;
case DATA:
return XFA.DATA;
case TEMPLATE:
return XFA.TEMPLATE;
case SOURCESET:
return XFA.SOURCESET;
case CONNECTIONSET:
return XFA.CONNECTIONSET;
case LOCALESET:
return XFA.LOCALESET;
case XSL:
return XFA.XSL;
default:
return null;
}
}
/*
* Return the input stream for a specific XFA Model.
*/
InputStream getXFAModelStream(int eType) {
switch (eType) {
case CONFIG:
return moConfigurationStream;
case XDP:
return moXDPStream;
default:
return null;
}
}
/*
* Return the type of a specific XFA Model.
*/
int getXFAModelType(String sModelName) {
if (sModelName.equals(XFA.CONFIG))
return CONFIG;
else if (sModelName.equals(XFA.XDC))
return XDC;
else if (sModelName.equals(XFA.DATA))
return DATA;
else if (sModelName.equals(STRS.DATASETS))
return DATA;
else if (sModelName.equals(XFA.TEMPLATE))
return TEMPLATE;
else if (sModelName.equals(XFA.SOURCESET))
return SOURCESET;
else if (sModelName.equals(XFA.CONNECTIONSET))
return CONNECTIONSET;
else if (sModelName.equals(XFA.LOCALESET))
return LOCALESET;
else if (sModelName.equals(XFA.XSL))
return XSL;
else
return UNKNOWN;
}
boolean getXFAPacketLoaded(int eType) {
switch (eType) {
case XDC:
return mbXDPLoadedXDC;
case CONFIG:
return mbXDPLoadedConfig;
case TEMPLATE:
return mbXDPLoadedTemplate;
case DATA:
return mbXDPLoadedData;
case SOURCESET:
return mbXDPLoadedSourceSet;
case CONNECTIONSET:
return mbXDPLoadedConnectionSet;
case XDP:
default:
return false;
}
}
/*
* Get any XSL specific info from the config DOM if specified.
*/
void getXSLOptions(String sModelName,
StringBuilder sLoadOptions, StringBuilder sDebugXSL) {
//
// Get any XSL specific info from the config DOM if specified.
//
Node oContextNode = getContextNode();
if (oContextNode != null) {
//
// Retrieve the XSL Script if any. It a script was specified, then
// put it in the name=value format so that it is handled properly
// by the loader as a load option.
//
Node resolvedNode = oContextNode.resolveNode(sModelName + ".xsl.uri");
if (resolvedNode instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue = (ConfigurationValue) resolvedNode;
String sValue = oConfigurationValue.getValue().toString();
if (!StringUtils.isEmpty(sValue))
sLoadOptions.append(" XSL=\"").append(sValue).append('\"');
}
//
// Retrieve the debug uri where to write the output XML after the XSL
// script has been issued. If only the debug path was given, and no
// XSL was given, the debug file will still be created, but will not
// contain any useful information.
//
resolvedNode = oContextNode.resolveNode(sModelName + ".xsl.debug.uri");
if (resolvedNode instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue = (ConfigurationValue) resolvedNode;
String sValue = oConfigurationValue.getValue().toString();
if (sValue.length() != 0)
sDebugXSL.append(sValue);
}
}
}
/*
* Verify that the model type specified has been loaded.
*/
boolean isPacketLoaded(int eType, boolean bRemove /* =false */) {
if (isXFAModelLoaded(eType, bRemove)) {
setXFAPacketLoaded(eType, ! bRemove);
return true;
}
setXFAPacketLoaded(eType, false);
return false;
}
/*
* Verify that the model(s) specified have been loaded.
*/
boolean isPacketLoaded(String oPacketList, boolean bRemove /* =false */) {
//
// Loop through each of the packets in the packet list
//
if (oPacketList != null) {
if (oPacketList.length() == 0 || oPacketList.equals("*"))
return true;
if (oPacketList.charAt(0) == '-')
return true;
StringTokenizer sTemp = new StringTokenizer(oPacketList);
while (sTemp.hasMoreTokens()) {
String sToken = sTemp.nextToken();
int eType = getXFAModelType(sToken);
if (! isPacketLoaded(eType, bRemove)) {
if (! bRemove)
return false;
}
}
}
return true;
}
/*
* Determine if the specified XFA Model exists in the XDP, note that the
* model has to be loaded from the XDP to determine this.
*/
boolean isXFAModelInXDP(int eType, boolean bMergeConfig /* =false */) {
if (moXDPStream == null) {
Node oContextNode = getContextNode();
if (oContextNode != null) {
Node resolvedNode = oContextNode.resolveNode(XFA.URI);
if (resolvedNode instanceof ConfigurationValue) {
// Use the source specified in the config model.
ConfigurationValue oConfigurationValue
= (ConfigurationValue) resolvedNode;
String sConfigSourceFile
= oConfigurationValue.getValue().toString();
if (!StringUtils.isEmpty(sConfigSourceFile))
setXFAInput(XDP, sConfigSourceFile);
}
}
}
if (moXDPStream != null) {
XMLStorage oXMLStorage = new XMLStorage();
//
// Return if we've already loaded the packet.
//
if (getXFAPacketLoaded(eType))
return true;
//
// remove old config from the appmodel,
// this way if the xdp contains a config section
// it will not over write the settings passed via command line
// or config options.
ConfigurationModel oOldConfig = null;
if (bMergeConfig) {
oOldConfig = getConfigModel();
oOldConfig.remove();
}
//
// Load the packet from the XDP.
//
AppModel oApp = getAppModel();
if (eType == DATA) {
setDataLoadOptions(oXMLStorage);
String sLoadOptions = "Model=\"" + STRS.DATASETS + '\"';
oXMLStorage.loadModel(oApp, moXDPStream, sLoadOptions, null);
}
else {
setPacketList(getXFAModelName(eType));
oApp.setPacketList(getPacketList());
oXMLStorage.loadXDP(oApp, moXDPStream, null, null, true);
}
//
// Merge the old config on top of the one found in the xdp
//
if (bMergeConfig) {
ConfigurationModel oNewConfig
= ConfigurationModel.getConfigurationModel(oApp, true);
oNewConfig.mergeModel(oOldConfig);
}
//
// Verify that the packet got loaded properly.
//
if (isPacketLoaded(eType, false))
return true;
}
return false;
}
/*
* isXFAModelLoaded - Verify that the model model has been loaded.
*/
@FindBugsSuppress(code="ES")
boolean isXFAModelLoaded(int eType, boolean bRemove /* =false */) {
String aExpectedModelName = null;
if (eType == DATA)
aExpectedModelName = STRS.DATASETS;
else
aExpectedModelName = getXFAModelName(eType);
for (Node oChild = getAppModel().getFirstXFAChild(); oChild != null; oChild = oChild.getNextXFASibling()) {
if (oChild.getName() == aExpectedModelName) {
if (bRemove) {
oChild.remove();
return true;
}
if (oChild.getFirstXFAChild() != null) {
// Data is special case, we need to look one
// extra level for the data node.
if (eType == DATA) {
if (oChild.getFirstXFAChild().getFirstXFAChild() == null)
break;
}
return true;
}
}
}
return false;
}
boolean isXFAModelRequired(int eType) {
switch (eType) {
case XDC:
case CONFIG:
case TEMPLATE:
return true;
case DATA:
case SOURCESET:
case CONNECTIONSET:
case XDP:
default:
return false;
}
}
/**
* Load a stream of XFA Model contents into the app model.
*
* @exclude from published api.
*/
protected boolean loadXFAModel(InputStream is,
String oPacketList,
boolean bReload) {
//
// Have to resolve general loadXDP issues such as how to specify
// an XSL for each specific model.
//
XMLStorage oXMLStorage = new XMLStorage();
//
// Set the packetlist to filter on.
//
if (oPacketList != null) {
setPacketList(oPacketList);
getAppModel().setPacketList(oPacketList);
if (bReload)
isPacketLoaded(oPacketList, true);
}
//
// mark current position in case we need to rewind.
//
if (is.markSupported())
is.mark(Integer.MAX_VALUE);
//
// Attempt to load the XFA Model(s).
//
if (! oXMLStorage.loadXDP(getAppModel(), is, null, null, true)) {
// not in xdp format, so try loading it as data if allowed
if (oPacketList == null
|| oPacketList.length() == 0
|| oPacketList.equals("*")
|| oPacketList.contains(STRS.DATASETS)) {
StringBuilder sLoadOptions = new StringBuilder();
sLoadOptions.append("Model=\"");
sLoadOptions.append(XFA.DATA);
sLoadOptions.append('\"');
//
// Set XSL options from config, if present.
//
StringBuilder sDebugXSL = new StringBuilder();
getXSLOptions(XFA.DATA, sLoadOptions, sDebugXSL);
//
// Set other config data loading options.
//
setDataLoadOptions(oXMLStorage);
//
// Trying rewinding the input source.
//
try {
is.reset();
} catch (IOException e) {
return false;
}
//
// Load into data model.
//
oXMLStorage.loadModel(getAppModel(), is,
sLoadOptions.toString(),
sDebugXSL.toString());
if (getDataModel() == null)
return false;
}
}
//
// Verify that the specified packets got loaded properly.
//
if (! isPacketLoaded(oPacketList, false))
return false;
return true;
}
/**
* Load the specified XFA Model type into the app model.
*
* @exclude from published api.
*/
protected boolean loadXFAModel(int eType, boolean bReload /* = false */) {
StringBuilder sSOMName = new StringBuilder();
//
// Verify that there is a valid input source...
// note that this will load the model
// from the XDP if that it the source.
//
InputStream oInputStream = resolveModelInput(eType, sSOMName);
if (oInputStream == null)
return false;
//
// Output a trace message for the model.
//
outputTraceMessage(ResId.GeneralTraceLoadDom, getXFAModelName(eType));
//
// Load the data from the specified stream
//
XMLStorage oXMLStorage = new XMLStorage();
if (bReload)
isPacketLoaded(eType, true);
//
// If the model was not loaded from the xdp then load it.
//
if (! getXFAPacketLoaded(eType)) {
// Set the load options to only load the specified model.
String sExpectedModelName;
if (eType == DATA)
sExpectedModelName = STRS.DATASETS;
else
sExpectedModelName = getXFAModelName(eType);
StringBuilder sLoadOptions = new StringBuilder();
sLoadOptions.append("Model=\"");
sLoadOptions.append(sExpectedModelName);
sLoadOptions.append('\"');
//
// Get any XSL specific info from the config DOM if specified.
//
StringBuilder sDebugXSL = new StringBuilder();
getXSLOptions(sSOMName.toString(), sLoadOptions, sDebugXSL);
//
// Special model-specific handling...
// TODO: Move this behaviour elsewhere.
//
if (eType == TEMPLATE) {
// Normalize the template stream
// JavaPort: all that XMLNormalize does over and above what
// we already handle is decode base64 gzipped files.
// We aren't planning to support this legacy feature.
// XMLNormalize oNormalXML(oInputStream, false);
// oInputStream = oNormalXML.output();
}
else if (eType == DATA) {
// Set Data load options for the data stream
setDataLoadOptions(oXMLStorage);
}
//
// Load the model.
//
oXMLStorage.loadModel(getAppModel(), oInputStream,
sLoadOptions.toString(),
sDebugXSL.toString());
//
// OK, the model is loaded. There's no reason to hold onto
// a file handle, so close it. We will not touch
// XDP files, as there is special processing done for XDP's
// that contain PDF's.
//
if (eType == XDP) {
if (moXDPStream != null) {
try {
moXDPStream.close();
}
catch (IOException e) {
}
moXDPStream = null;
}
}
//
// Ensure that the proper model got loaded...
//
if (isXFAModelLoaded(eType, false))
return true;
MsgFormatPos formatError
= new MsgFormatPos(ResId.XFAAgentWrongFileType);
formatError.format(getXFAModelName(eType));
throw new ExFull(formatError);
}
return true;
}
void outputTraceMessage(int nResId, String sInput) {
if (goGeneralTrace.isEnabled(1)) {
MsgFormatPos oFormatPos = new MsgFormatPos(nResId);
if (sInput.length() > 0) {
oFormatPos.format(sInput);
}
goGeneralTrace.trace(1, oFormatPos);
}
}
InputStream resolveModelInput(int eType, StringBuilder oSOMName) {
//
// Get the model input stream and SOM Name.
//
InputStream oInputStream = getXFAModelStream(eType);
oSOMName.append(getXFAModelName(eType));
//
// Use the config file if the input stream is not already set.
//
if (oInputStream == null) {
//
// Check if we have an XFA model-specific file specified
// in our config model first.
//
if (setConfigInputStream(eType))
oInputStream = getXFAModelStream(eType);
//
// Now try the XDP if there was one specified.
//
if (oInputStream == null) {
if (isXFAModelInXDP(eType, false)) {
oInputStream = getXFAModelStream(XDP);
}
}
if (oInputStream == null && isXFAModelRequired(eType)) {
LogMessage oMessage = new LogMessage();
MsgFormatPos formatError
= new MsgFormatPos(getXFAModelMessageFileNotFound(eType));
formatError.format(getXFAModelConfigURI(eType));
oMessage.insertMessage(formatError,
LogMessage.MSG_FATAL_ERROR, "");
getMessenger().sendMessage(oMessage);
return null;
}
}
if (oInputStream != null) {
if (isXFAModelRequired(eType)) {
LogMessage oMessage = new LogMessage();
MsgFormatPos formatError
= new MsgFormatPos(getXFAModelMessageFileNotSpecified(eType));
oMessage.insertMessage(formatError,
LogMessage.MSG_FATAL_ERROR, "");
getMessenger().sendMessage(oMessage);
}
return null;
}
return oInputStream;
}
/**
* Save the current XFADataModel instance to an output streamfile
* NOTE: same context node as loadDataModel
*/
void saveDataModel(OutputStream oStream) {
XMLStorage xml = new XMLStorage();
// get the data model.
Model oDataModel = getDataModel();
Node oContextNode = getContextNode();
if (oContextNode != null) {
Node oResolvedNode
= oContextNode.resolveNode("data.outputXSL.uri");
if (oResolvedNode instanceof ConfigurationValue) {
// grab the name of the output xsl script
ConfigurationValue oConfigurationValue
= (ConfigurationValue) oResolvedNode;
String sFile = oConfigurationValue.getValue().toString();
//
// ensure the file exists
//
if (!StringUtils.isEmpty(sFile)) {
File oFileID = new File(sFile);
if (! oFileID.exists()) {
throw new ExFull(new MsgFormatPos(ResId.XSLFileNotFound, sFile));
}
FileInputStream oXSLStream = null;
try {
//
// Save data to temp file, then apply xsl
//
ByteArrayOutputStream oTempOutput = new ByteArrayOutputStream();
xml.saveModelAs(oDataModel, oTempOutput, "");
ByteArrayInputStream oTempInput = new ByteArrayInputStream(oTempOutput.toByteArray());
//
// Apply xsl on the stream.
//
oXSLStream = new FileInputStream(oFileID);
XSLTranslator translator = new XSLTranslator(oXSLStream);
//
// translate specified stream into a the output file stream
//
translator.process(oTempInput, oStream);
return; // done
} catch (IOException e) {
throw new ExFull(e);
}
finally {
try {
if (oXSLStream != null) oXSLStream.close();
}
catch (IOException ex) {
}
}
}
}
}
// save normaly
xml.saveModelAs(oDataModel, oStream, "");
}
void saveSimpleXDP(String sPacketList, OutputStream oStream) {
NodeList oNodesToSave = new ArrayNodeList();
boolean bIncludeData = true;
AppModel oAppModel = getAppModel();
//
// get the models
//
ConfigurationModel oConfigModel = getConfigModel(); //always
TemplateModel oTemplateModel = getTemplateModel(); //always
// JavaPort: not yet available.
// SourceSetModel oSSModel = getSourceSetModel();
ConnectionSetModel oCSModel = getConnectionSetModel();
//
// Embed the config file.
// get config ns
String sConfigNS = ConfigurationModel.configurationNS();
//
// create acrobat section
// will set the validate attr
//
Element oAcrobat = oConfigModel.createElement(oConfigModel, null,
sConfigNS, XFA.ACROBAT, XFA.ACROBAT,
null, 0, null);
//
// create common tag
//
Element oCommon = oConfigModel.createElement(oAcrobat, null,
sConfigNS, XFA.COMMON, XFA.COMMON,
null, 0, null);
//
// set the data options
//
Node oDataOptions = getContextNode().resolveNode("common.data");
if (oDataOptions instanceof ConfigurationValue) {
// Must be done before se modify config so we can set the xsl uri
// for all agents. If there is an input XSL file, embed it as well
ConfigurationValue oConfigValue
= (ConfigurationValue) oDataOptions.resolveNode("xsl.uri");
if (oConfigValue != null && oConfigValue.getXFAChildCount() == 1) {
String sXSLFile = oConfigValue.getValue().toString();
File oXSLFileID = new File(sXSLFile);
if (oXSLFileID.exists()) {
FileInputStream oXSLStream = null;
try {
oXSLStream = new FileInputStream(oXSLFileID);
Document oDoc = oAppModel.getDocument();
Element oRoot = oDoc.loadIntoDocument(oXSLStream);
Node oChild = oRoot.getFirstXMLChild();
while (oChild != null) {
if (oChild instanceof Element) {
//
// add xsl packet to the xfa
//
Packet oDataInputXSL = new Packet(oAppModel, null);
oDataInputXSL.setXmlPeer(oChild);
//
// set the id of the xsl
//
oDataInputXSL.setAttribute("XFADataInputXSL", "id");
oNodesToSave.append(oDataInputXSL);
break;
}
oChild = oChild.getNextXMLSibling();
}
} catch (IOException e) {
throw new ExFull(e);
}
finally {
try {
if (oXSLStream != null) oXSLStream.close();
}
catch (IOException ex) {
}
}
}
}
//
// save the output xsl stream
//
oConfigValue = (ConfigurationValue)
oDataOptions.resolveNode("outputXSL.uri");
if (oConfigValue != null && oConfigValue.getXFAChildCount() == 1) {
String sXSLFile = oConfigValue.getValue().toString();
File oXSLFileID = new File(sXSLFile);
if (oXSLFileID.exists()) {
FileInputStream oXSLStream = null;
try {
oXSLStream = new FileInputStream(oXSLFileID);
Document oDoc = oAppModel.getDocument();
Element oRoot = oDoc.loadIntoDocument(oXSLStream);
Node oChild = oRoot.getFirstXMLChild();
while (oChild != null) {
if (oChild instanceof Element) {
//
// add xsl packet to the xfa
//
Packet oDataOutputXSL
= new Packet(oAppModel, oChild);
//
// set the id of the xsl
//
oDataOutputXSL.setAttribute("XFADataOutputXSL",
"id");
oNodesToSave.append(oDataOutputXSL);
break;
}
oChild = oChild.getNextXMLSibling();
}
} catch (IOException e) {
throw new ExFull(e);
}
finally {
try {
if (oXSLStream != null) oXSLStream.close();
}
catch (IOException ex) {
}
}
}
}
if (mbIsDataIncremental) {
bIncludeData = false;
}
//
// clone common section and append it to the acrobat section.
//
Node oClone
= ((ConfigurationValue) oDataOptions).clone(null, true);
oCommon.getNodes().append(oClone);
oNodesToSave.append(oConfigModel);
}
//
// set the template options
//
Node oTemplateOptions = getContextNode().resolveNode("common.template");
if (oTemplateOptions instanceof ConfigurationValue) {
// clone common section and append it to the acrobat section.
Node oClone
= ((ConfigurationValue) oTemplateOptions).clone(null, true);
oCommon.getNodes().append(oClone);
}
//
// embed the template
//
oNodesToSave.append(oTemplateModel);
//
// Add the sourceSet model (if there is one) to the PDF.
//
// JavaPort: no support for SourceSetModel
// if (oSSModel != null) {
// oNodesToSave.append(oSSModel);
// }
//
// Add the connection Set model (if there is one) to the PDF.
//
if (oCSModel != null) {
oNodesToSave.append(oCSModel);
}
if (bIncludeData) { // always have dataModel.
DataModel oDataModel = getDataModel();
if (oDataModel != null) {
// Add the data file (if there was one) to the PDF.
oNodesToSave.append(oDataModel);
// JavaPort: TODO
// // Just to delineate this workaround, which should be
// // resolved more elegantly after alpha...
// // In XDP format, we need the entire data structure
// // (datasets/data/root) to be present and connected
// // to the same XML DOM document. If we add
// // a peer to the root element, this structure will be
// // created automatically for us by xfadata. If we
// // then remove the node this work is not undone.
// oDataModel.getAliasNode().getImpl().connectPeerToParent();
// // force recalc of record depth
// oDataModel.getDataWindow().getImpl().resetRecordDepth();
}
}
//
// Mark the encryption passwords as transient - they are never
// to be saved out in the xfa stream!
//
Element oUser = null;
Element oMaster = null;
Node oPDFEncryption = oConfigModel.resolveNode("$config.present.pdf.encryption");
if (oPDFEncryption instanceof Element) {
if (((Element) oPDFEncryption).isPropertySpecified(XFA.USERPASSWORDTAG, true, 0)) {
oUser = ((Element) oPDFEncryption).getElement(XFA.USERPASSWORDTAG, false, 0, false, false);
oUser.isHidden(true);
}
if (((Element) oPDFEncryption).isPropertySpecified(XFA.MASTERPASSWORDTAG, true, 0)) {
oMaster = ((Element) oPDFEncryption).getElement(XFA.MASTERPASSWORDTAG, false, 0, false, false);
oMaster.isHidden(true);
}
}
//
// Allow fine control over which packets are saved. Note that
// we're resetting oNodesToSave if xdp.packets is specified, which
// makes some of the above code a waste. However it keeps this
// feature much cleaner if we keep it here, and the waste is minimal.
//
String sPackets = sPacketList;
if (sPackets.length() == 0) {
Node oPackets = getContextNode().resolveNode("xdp.packets");
if (oPackets instanceof ConfigurationValue) {
ConfigurationValue oConfigurationValue
= (ConfigurationValue) oPackets;
sPackets = oConfigurationValue.getValue().toString();
}
}
if (sPackets.length() != 0) {
boolean bAllPackets = (sPackets.equals("*"));
oNodesToSave = new ArrayNodeList(); // reset list
for (Node oChild = oAppModel.getFirstXFAChild(); oChild != null; oChild = oChild.getNextXFASibling()) {
//
// See if the packet's name is in the list of packets to save.
// Models are considered to be packets here, for consistency
// with XDPTK.
//
if (bAllPackets) {
oNodesToSave.append(oChild);
continue;
}
String packetName = oChild.getName();
StringTokenizer sPacketsCopy = new StringTokenizer(sPackets);
while (sPacketsCopy.hasMoreTokens()) {
String sToken = sPacketsCopy.nextToken();
if (sToken.equals(packetName)) {
oNodesToSave.append(oChild);
break;
}
}
}
}
//
//Save the nodes
//
XMLStorage oStorage = new XMLStorage();
oStorage.saveAggregate(null, oStream, oNodesToSave, "");
//
// Re-enable the passwords (?)
//
if (oUser != null)
oUser.isHidden(false);
if (oMaster != null)
oMaster.isHidden(false);
}
boolean setConfigInputStream(int eType) {
String sConfigURI = getXFAModelConfigURI(eType);
Node oContextNode = getContextNode();
if (oContextNode != null && !StringUtils.isEmpty(sConfigURI)) {
Node resolvedNode = oContextNode.resolveNode(sConfigURI);
if (resolvedNode instanceof ConfigurationValue) {
// Use the source specified in the config model.
ConfigurationValue oConfigurationValue
= (ConfigurationValue) resolvedNode;
String sConfigSourceFile
= oConfigurationValue.getValue().toString();
if (!StringUtils.isEmpty(sConfigSourceFile)) {
setXFAInput(eType, sConfigSourceFile);
return true;
}
}
}
return false;
}
/*
* Set data load options.
* The section of the configuration file we are interested in:
*
*
*
* c:\dp\xfd\flatten.xml
*
* 0
*
*
*
*
*
* ignore
*
*
*
*
*/
void setDataLoadOptions(XMLStorage oXMLStorage) {
Node oContextNode = getContextNode();
//
// set the options
//
Node oResolvedNode = null;
// Reset data loading options.
// Watson# 2420783. Appending to existing list of data transformation options had
// a severe performance impact for heterogenous batches (where the data loading options
// are applied each time a template is loaded [i.e. once per record]). So now, the
// call to reset() will clear this existing list rather than appending to it.
moDataFactory.reset();
if (oContextNode != null) {
oResolvedNode = oContextNode.resolveNode("data");
if (oResolvedNode != null) {
if (oResolvedNode.getFirstXFAChild() == null)
return;
StringBuilder sExclNS = new StringBuilder();
for (Node node = oResolvedNode.getFirstXFAChild(); node != null; node = node.getNextXFASibling()) {
if (!(node instanceof Element))
continue;
Element child = (Element)node;
String sName = child.getName();
if (sName.equals("transform")) {
//Transformation options are in the form
//name1='value1' name2='value2' ....
String sOptionName = "data_transform";
StringBuilder sTransform = new StringBuilder();
sTransform.append(XFA.REF);
sTransform.append("=\'");
sTransform.append(child.getAttribute(XFA.REFTAG).toString());
sTransform.append('\'');
for (ConfigurationValue oConfigVal = (ConfigurationValue)child.getFirstXFAChild(); child != null; child = (ConfigurationValue)child.getNextXFASibling()) {
sTransform.append(' ');
Attribute oValue = oConfigVal.getValue();
sTransform.append(oConfigVal.getName());
sTransform.append("=\'");
sTransform.append(oValue.toString());
sTransform.append('\'');
}
moDataFactory.setOption(sOptionName,
sTransform.toString(), false);
}
else if (! child.isContainer()) {
String sValue = "";
if (child instanceof ConfigurationValue)
sValue = ((ConfigurationValue) child).getValue().toString();
if (sName.equals("uri")) {
// we have already opened the data file
continue;
}
else if (sName.equals("excludeNS") && !StringUtils.isEmpty(sValue)) {
//excludeNS is 0-N, so accummulate namespaces
if (sExclNS.length() != 0)
sExclNS.append(' ');
sExclNS.append(sValue);
moDataFactory.setOption("excludeNS",
sExclNS.toString(), false);
}
else if (!StringUtils.isEmpty(sValue)) {
if (sName.equals(XFA.ADJUSTDATA))
continue;
//should check if it's an acceptable option
moDataFactory.setOption(sName, sValue, false);
}
}
}
}
}
}
/**
* Set the DataModel instance that this agent will use when executing.
* Implementation is deferred for the time being.
*/
void setDataModel(Model oModel) {
}
/*
* Set the list of XFA packets for the XDP.
*/
void setPacketList(String sPacketList) {
msPacketList = sPacketList;
}
/**
* Store the input source for the various XFA models.
*
* @exclude from published api.
*/
protected void setXFAInput(int eModel, String sInputFile) {
if (StringUtils.isEmpty(sInputFile))
return;
InputStream oStream = null;
try {
oStream = (new URL(sInputFile)).openStream();
} catch (Exception e) {
try {
oStream = new FileInputStream(sInputFile);
} catch (IOException f) {
}
}
setXFAInput(eModel, oStream);
}
/**
* Store the input source for the various XFA models.
*
* @exclude from published api.
*/
protected void setXFAInput(int eModel, InputStream oStream) {
if (oStream != null) {
switch (eModel) {
case CONFIG:
moConfigurationStream = oStream;
break;
case XDP:
moXDPStream = oStream;
break;
}
}
}
void setXFAPacketLoaded(int eType, boolean bLoaded) {
switch (eType) {
case XDC:
mbXDPLoadedXDC = bLoaded;
break;
case CONFIG:
mbXDPLoadedConfig = bLoaded;
break;
case TEMPLATE:
mbXDPLoadedTemplate = bLoaded;
break;
case DATA:
mbXDPLoadedData = bLoaded;
break;
case SOURCESET:
mbXDPLoadedSourceSet = bLoaded;
break;
case CONNECTIONSET:
mbXDPLoadedConnectionSet = bLoaded;
break;
case XSL:
//mbXDPLoadedXSL = bLoaded;
break;
case LOCALESET:
//mbXDPLoadedLocaleSet = bLoaded;
break;
case XDP:
default:
break;
}
}
}