📄 xmlscriptinterpreter.java
字号:
/*------------------------------------------------------------------------------Name: XmlScriptInterpreter.javaProject: xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE file------------------------------------------------------------------------------*/package org.xmlBlaster.client.script;import java.util.logging.Logger;import java.util.logging.Level;import org.xmlBlaster.client.key.UpdateKey;import org.xmlBlaster.client.qos.UpdateQos;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.def.Constants;import org.xmlBlaster.util.def.ErrorCode;import org.xmlBlaster.util.def.MethodName;import org.xmlBlaster.util.xbformat.MsgInfo;import org.xmlBlaster.util.EncodableData;import org.xmlBlaster.util.I_ReplaceVariable;import org.xmlBlaster.util.MsgUnit;import org.xmlBlaster.util.MsgUnitRaw;import org.xmlBlaster.util.ReplaceVariable;import org.xmlBlaster.util.SaxHandlerBase;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.StopParseException;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.OutputStream;import java.io.Reader;import java.util.ArrayList;import java.util.HashSet;import java.util.HashMap;import java.util.Properties;import java.io.File;/** * Parse email body. * * <subscribe> * <key>....</key> * <qos>...</qos> * </subscribe> * * <unSubscribe> * <key> * </key> * </unSubscribe> * * <publish> * <key></key> * <content link='ff'></content> * <qos>...</qos> * </publish> * * <publishArr> * <key></key> * <content link='ff'></content> * <qos>...</qos> * <key></key> * <content link='ff'></content> * <qos>...</qos> * ....... * <key></key> * <content link='ff'></content> * <qos>...</qos> * </publishArr> * * <erase> * <key></key> * <qos>...</qos> * </erase> * * <erase> * <key></key> * <qos>...</qos> * </erase> *//** * Abstract class to parse and construct a XML represantation of xmlBlaster invocations for scripting. * <p> * Example for command line scripting usage: * </p> * <p> * <tt> * java javaclients.XmlScript -requestFile inFile.xml -responseFile outFile.xml -updateFile updFile.xml * </tt> * </p> * @author <a href="mailto:michele@laghi.eu">Michele Laghi</a> * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/client.script.html">The client.script requirement</a> */public abstract class XmlScriptInterpreter extends SaxHandlerBase { private final String ME = "XmlScriptInterpreter"; private static Logger log = Logger.getLogger(XmlScriptInterpreter.class.getName()); protected Global glob; /** a set of names of allowed commands */ private HashSet commandsToFire = new HashSet(); protected StringBuffer qos = new StringBuffer(); protected StringBuffer key = new StringBuffer(); private StringBuffer content = new StringBuffer(); // To access use contentData protected StringBuffer cdata = new StringBuffer(); /** Replace e.g. ${ICAO} with command line setting '-ICAO EDDI' */ private boolean replaceQosTokens; private boolean replaceKeyTokens; private boolean replaceContentTokens; /** Replace tokens in wait or echo markup */ private boolean replaceTokens; /** Encapsulates the content of the current message (useful for encoding) */ protected EncodableData contentData; // private boolean inQos, inKey, inContent; private int inQos, inKey, inContent, inCDATA; private String link; private String sessionId; private String requestId; private byte type; // I=invoke R=response E=exception private String propertyName; private boolean inProperty; /** the attachments (some contents can be in the attachments) */ private HashMap attachments; /** used to accumulate all messages to be sent with publishArr */ protected ArrayList messageList; /** buffer used as a place holder for the responses of the xmlBlaster invocations */ protected StringBuffer response; protected boolean needsRootEndTag; protected OutputStream out; protected Object waitMutex = new Object(); protected long updateCounter; protected int waitNumUpdates; /** * Set true to send a simple exception format like <pre> <update type='E'> <qos><state id='ERROR' info='user'/></qos> </update> </pre> <p>Note: The errorCode is stripped to the main category</p> */ protected boolean sendSimpleExceptionFormat; public final static String ROOT_TAG = "xmlBlaster"; public final static String ROOTRESPONSE_TAG = "xmlBlasterResponse"; public final String KEY_TAG = MsgUnitRaw.KEY_TAG; public final String CONTENT_TAG = MsgUnitRaw.CONTENT_TAG; public final String QOS_TAG = MsgUnitRaw.QOS_TAG; public final String ECHO_TAG = "echo"; public final String INPUT_TAG = "input"; public final String WAIT_TAG = "wait"; /** * You need to call initialize() if using this default constructor. */ public XmlScriptInterpreter() { } /** * This constructor is the most generic one (more degrees of freedom) * @param glob the global to use * @param attachments the attachments where to search * when a content is stored in the attachment * (with the 'link' attribute); can be null * @param out the OutputStream where to send the responses of the invocations done to xmlBlaster */ public XmlScriptInterpreter(Global glob, HashMap attachments, OutputStream out) { super(glob); initialize(glob, attachments, out); } /** * @param glob the global to use * @param attachments the attachments where to search when a content is stored in the attachment (with the 'link' attribute) * @param out the OutputStream where to send the responses of the invocations done to xmlBlaster */ public void initialize(Global glob, HashMap attachments, OutputStream out) { this.glob = glob; setUseLexicalHandler(true); this.commandsToFire.add(MethodName.GET.toString()); this.commandsToFire.add(MethodName.CONNECT.toString()); this.commandsToFire.add(MethodName.PING.toString()); this.commandsToFire.add(MethodName.SUBSCRIBE.toString()); this.commandsToFire.add(MethodName.UNSUBSCRIBE.toString()); this.commandsToFire.add(MethodName.PUBLISH.toString()); this.commandsToFire.add(MethodName.PUBLISH_ARR.toString()); this.commandsToFire.add(MethodName.PUBLISH_ONEWAY.toString()); this.commandsToFire.add(MethodName.UPDATE.toString()); this.commandsToFire.add(MethodName.UPDATE_ONEWAY.toString()); this.commandsToFire.add(MethodName.ERASE.toString()); this.commandsToFire.add(MethodName.DISCONNECT.toString()); this.commandsToFire.add(MethodName.EXCEPTION.toString()); this.attachments = attachments; this.out = out; this.needsRootEndTag = false; // will be true when start tag is written } /** * converts the tag sctart to a string * @param qName * @param attr * @return */ protected String writeElementStart(String qName, Attributes attr) { StringBuffer buf = new StringBuffer("<"); buf.append(qName); int nmax = attr.getLength(); for (int i=0; i < nmax; i++) { String name = attr.getQName(i); String value = attr.getValue(i); buf.append(' '); buf.append(name); buf.append("='"); buf.append(value); buf.append('\''); } buf.append('>'); return buf.toString(); } /** * Parses the given reader and executes the specified commands. * @param in the reader from which to read the xml input. * @throws XmlBlasterException */ public synchronized void parse(Reader in) throws XmlBlasterException { this.inQos = 0; this.inKey = 0; this.inContent = 0; this.inCDATA = 0; if (this.out != null) { try { this.out.flush(); } catch (IOException ex) { throw new XmlBlasterException(this.glob, ErrorCode.INTERNAL_UNKNOWN, ME + ".parse: could not flush the output stream: original message: '" + ex.toString() + "'"); } } super.init(new InputSource(in)); // parse with SAX } public void characters(char[] ch, int start, int length) { // append on the corresponding buffer if (this.inCDATA > 0) { this.cdata.append(ch, start, length); } else if (this.inQos > 0) { this.qos.append(ch, start, length); } else if (this.inKey > 0) { this.key.append(ch, start, length); } else if (this.inContent > 0) { this.content.append(ch, start, length); } else super.characters(ch, start, length); } /** * Increments the corresponding counter only if it is already in one such element * @param qName */ private void incrementInElementCounters(String qName) { if (QOS_TAG.equals(qName) && this.inQos > 0) this.inQos++; else if (KEY_TAG.equals(qName) && this.inKey > 0) this.inKey++; else if (CONTENT_TAG.equals(qName) && this.inContent > 0) this.inContent++; } public void startElement(String namespaceURI, String localName, String qName, Attributes atts) { checkNestedTags(); if (this.inQos > 0) { this.qos.append(writeElementStart(qName, atts)); incrementInElementCounters(qName); return; } if (this.inKey > 0) { this.key.append(writeElementStart(qName, atts)); incrementInElementCounters(qName); return; } if (this.inContent > 0) { this.content.append(writeElementStart(qName, atts)); incrementInElementCounters(qName); return; } if (this.commandsToFire.contains(qName)) { this.character = new StringBuffer(); this.character.append(this.writeElementStart(qName, atts)); if (MethodName.PUBLISH_ARR.equals(qName) || MethodName.PUBLISH_ONEWAY.equals(qName)) this.messageList = new ArrayList(); this.sessionId = atts.getValue("sessionId");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -