Java tutorial
/* * Copyright 2012 Devoteam http://www.devoteam.com * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * * This file is part of Multi-Protocol Test Suite (MTS). * * Multi-Protocol Test Suite (MTS) is free software: you can redistribute * it and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of the * License. * * Multi-Protocol Test Suite (MTS) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Multi-Protocol Test Suite (MTS). * If not, see <http://www.gnu.org/licenses/>. * */ package com.devoteam.srit.xmlloader.h248; import java.util.HashSet; import org.dom4j.Element; import com.devoteam.srit.xmlloader.core.Parameter; import com.devoteam.srit.xmlloader.core.Runner; import com.devoteam.srit.xmlloader.core.exception.ExecutionException; import com.devoteam.srit.xmlloader.core.protocol.Msg; import com.devoteam.srit.xmlloader.core.protocol.Stack; import com.devoteam.srit.xmlloader.core.protocol.StackFactory; import com.devoteam.srit.xmlloader.core.protocol.Trans; import com.devoteam.srit.xmlloader.core.protocol.TransactionId; import com.devoteam.srit.xmlloader.core.utils.Utils; import com.devoteam.srit.xmlloader.h248.data.Header; import com.devoteam.srit.xmlloader.h248.data.ABNFParser; import com.devoteam.srit.xmlloader.h248.data.AuthHeader; import com.devoteam.srit.xmlloader.h248.data.Descriptor; import com.devoteam.srit.xmlloader.h248.data.Dictionary; /** * * @author fhenry */ public class MsgH248 extends Msg { private String message; private AuthHeader authHeader; private Header header; private Descriptor descr = null; // List of descriptor name for the type of message private static HashSet<String> typeDescriptor = new HashSet<String>(); private TransactionId responseTransactionId; private boolean isResponseTransactionIsSet; /** Creates a new instance */ public MsgH248(Stack stack) { super(stack); typeDescriptor.add("A"); typeDescriptor.add("MF"); typeDescriptor.add("S"); typeDescriptor.add("MV"); typeDescriptor.add("AV"); typeDescriptor.add("AC"); typeDescriptor.add("N"); typeDescriptor.add("SC"); } /** * Return true if the message is a request else return false */ @Override public boolean isRequest() throws Exception { // errorDescriptor Parameter param = getParameter("descr.*.n"); if (param.length() <= 0) { return true; } String descr = (String) param.get(0); // errorDescriptor if ("ER".equals(descr)) { return false; } // ReplyDescriptor if ("P".equals(descr)) { return false; } // PendingDescriptor if ("PN".equals(descr)) { return false; } return true; } /** * Get the type of the message * Used for message filtering with "type" attribute and for statistic counters */ @Override public String getType() throws Exception { // case Transaction or Reply Parameter param = getParameter("descr.*.C.*.n"); String type = getType(param); if (type != null) { return type; } // case TransactionResponseAck param = getParameter("descr.K.n"); if (param.length() > 0) { return "TransactionResponseAck"; } // case Segment param = getParameter("descr.SM.n"); if (param.length() > 0) { return "Segment"; } // case TransactionPending or other if (!isRequest()) { Trans trans = getTransaction(); if (trans == null) { return "null"; } Msg request = trans.getBeginMsg(); if (request == null) { return "null"; } return request.getType(); } return "null"; } /** Get the command code of this message */ private String getType(Parameter var) throws Exception { for (int i = 0; i < var.length(); i++) { String type = (String) var.get(i); // delete a prefix int pos = type.indexOf(ABNFParser.MINUS); if (pos >= 0) { type = type.substring(pos + 1); } String resolvedType = Dictionary.getInstance().getLongToken(type); if (typeDescriptor.contains(type)) { return resolvedType; } } return null; } /** Get the complete type (with dictionary conversion) of this message */ public String getTypeComplete() throws Exception { String type = getType(); String resolvedType = Dictionary.getInstance().getShortToken(type); String complete = type; if (!resolvedType.equals(type)) { complete = type + ":" + resolvedType; } return complete; } /** * Get the result of the message (null if request) * Used for message filtering with "result" attribute and for statistic counters */ @Override public String getResult() throws Exception { // case Error Parameter trans = getParameter("descr.ER.value"); if (trans.length() > 0) { return (String) trans.get(0); } // Reply/Error trans = getParameter("descr.P.ER.value"); if (trans.length() > 0) { return (String) trans.get(0); } // case Reply/Context/Error trans = getParameter("descr.P.C.ER.value"); if (trans.length() > 0) { return (String) trans.get(0); } // case Reply/Context/<command>/Error trans = getParameter("descr.P.C.*.ER.value"); if (trans.length() > 0) { return (String) trans.get(0); } // case transactionPending trans = getParameter("descr.PN.value"); if (trans.length() > 0) { return "Pending"; } return "Reply"; } /** Get the complete result (with dictionary conversion) of this message */ public String getResultComplete() throws Exception { String result = getResult(); String resolvedResult = Dictionary.getInstance().getShortToken(result); String complete = result; if (!resolvedResult.equals(result)) { complete = result + ":" + resolvedResult; } return complete; } /** Get the transaction Identifier of this message */ @Override public TransactionId getTransactionId() throws Exception { if (!this.isTransactionIdSet) { // transactionRequest, transactionReply, transactionPending, segmentReply String transID = ""; Parameter trans = getParameter("descr.*.value"); if (trans.length() <= 0) { // transactionResponseAck trans = getParameter("descr.*.parameters"); } if (trans.length() > 0) { transID = trans.get(0).toString(); // transactionReply token // remove the [SLASH segmentNumber [SLASH SegmentationCompleteToken]] string ( int pos = transID.indexOf(ABNFParser.SLASH); if (pos >= 0) { transID = transID.substring(0, pos).trim(); } // transactionResponseAck token // remove the *(COMMA transactionAck) string ( pos = transID.indexOf(ABNFParser.COMMA); if (pos >= 0) { transID = transID.substring(0, pos).trim(); } // transactionAck token // remove / (TransactionID MINUS TransactionID) pos = transID.indexOf(ABNFParser.MINUS); if (pos >= 0) { transID = transID.substring(0, pos).trim(); } } this.transactionId = new TransactionId(transID); this.isTransactionIdSet = true; } return this.transactionId; } /** Get the segment number of this message */ public String getSegmentNumber() throws Exception { Parameter transID = getParameter("descr.*.value"); String trans = ""; if (transID.length() > 0) { trans = (String) transID.get(0); } int pos = trans.indexOf(ABNFParser.SLASH); if (pos >= 0) { int pos1 = trans.indexOf(ABNFParser.SLASH, pos + 1); if (pos1 < 0) { pos1 = trans.length(); } return trans.substring(pos + 1, pos1); } return null; } /** Get the segmentation complete of this message */ public String getSegmentComplete() throws Exception { Parameter transID = getParameter("descr.*.value"); String trans = ""; if (transID.length() > 0) { trans = (String) transID.get(0); } int pos = trans.indexOf(ABNFParser.SLASH); if (pos >= 0) { int pos1 = trans.indexOf(ABNFParser.SLASH, pos + 1); if (pos1 >= 0) { String ret = trans.substring(pos1 + 1); String resolvedRet = Dictionary.getInstance().getLongToken(ret); return resolvedRet; } } return null; } /** Get the transaction Identifier of this message */ public TransactionId getResponseTransactionId() throws Exception { if (!this.isResponseTransactionIsSet) { // transactionRequest, transactionReply, transactionPending, segmentReply Parameter trans = getParameter("descr.*.n"); if (trans.length() > 0) { String name = (String) trans.get(0); if ("K".equals(name) || "SM".equals(name) || ("P".equals(name))) { this.responseTransactionId = new TransactionId( this.getTransactionId() + "|" + this.getSegmentNumber()); } } this.isResponseTransactionIsSet = true; } return this.responseTransactionId; } /** * Tell whether the message shall be retransmitted or not * (= true by default) */ public boolean shallBeRetransmitted() throws Exception { String type = getType(); if (isRequest()) { if ("TransactionResponseAck".equals(type)) { return false; } if ("Segment".equals(type)) { return false; } } else { String result = getResult(); if ("Pending".equals(result)) { return false; } } return true; } /** * Tell whether the message shall be stop the automatic * retransmission mechanism or not * (= true by default) */ public boolean shallStopRetransmit() throws Exception { String type = getType(); if (isRequest()) { if ("TransactionResponseAck".equals(type)) { return true; } if ("Segment".equals(type)) { return true; } return false; } else { return true; } } /** * Tell whether the request begins the transaction or not * (= true by default) */ public boolean beginTransaction() throws Exception { String status = getType(); if ("TransactionResponseAck".equals(status)) { return false; } if ("Segment".equals(status)) { return false; } return true; } /** * Tell whether the response ends the transaction or not * (= true by default) */ public boolean endTransaction() throws Exception { String method = getType(); if ("TransactionResponseAck".equals(method)) { return true; } String status = getResult(); if ("Reply".equals(status)) { return true; } return false; } //------------------------------------------------- // methods for the encoding / decoding of the message //------------------------------------------------- /** * encode the message to binary data */ @Override public byte[] encode() throws Exception { return message.getBytes(); } /** * decode the message from binary data */ public void decode(byte[] data) throws Exception { String text = new String(data); this.message = text; // remove the comment block : from ";" char to the end of line text = text.replaceAll(";[^\r\n]*", " "); // check the MEGACO token int index = ABNFParser.indexOfKWDictionary(text, ABNFParser.MEGACOP_TOKEN, 0); if (index >= 0) { // parse the authentication header String authHeader = text.substring(0, index).trim(); if (authHeader.length() > 0) { this.authHeader = new AuthHeader(); this.authHeader.parseHeader(authHeader + " ", 0); } // parse the message header this.header = new Header(); index = this.header.parseHeader(text, index); index = index + 1; } else { index = 0; } if (index >= 0) { // parse the message descriptors list String descriptors = text.substring(index, text.length()).trim(); descriptors = "descr{" + descriptors + "}"; this.descr = new Descriptor(); this.descr.parseDescriptors(descriptors, 0, false); } } //--------------------------------------------------------------------- // methods for the XML display / parsing of the message //--------------------------------------------------------------------- /** Returns a short description of the message. Used for logging as INFO level */ /** This methods HAS TO be quick to execute for performance reason */ @Override public String toShortString() throws Exception { String ret = super.toShortString(); ret += "\n"; Parameter param = getParameter("descr.*.name"); if (param.length() > 0) { ret += (String) param.get(0) + "="; } ret += getTransactionId(); String segnum = getSegmentNumber(); if (segnum != null) { ret += "/" + segnum; } String segcomp = getSegmentComplete(); if (segcomp != null) { ret += "/" + segcomp; } param = getParameter("descr.*.Context.value"); if (param.length() > 0) { ret += " C=" + (String) param.get(0); } String action = getType(); ret += " " + action; param = getParameter("descr.*.*." + action + ".value"); if (param.length() > 0) { ret += "=" + param.get(0); } return ret; } /** * Convert the message to XML document */ @Override public String toXml() throws Exception { String ret = null; if (this.authHeader != null) { ret += this.authHeader.toString() + "\n"; } if (this.header != null) { ret += this.header.toString() + "\n"; } if (this.descr != null) { ret += this.descr.toString(); } return ret; } /** * Parse the message from XML element */ @Override public void parseFromXml(Boolean request, Element root, Runner runner) throws Exception { String text = root.getText().trim(); if ("CRLF".equals(((StackH248) this.stack).endLineCharacters)) { text = Utils.replaceNoRegex(text, "\n", "\r\n"); } else if ("CR".equals(((StackH248) this.stack).endLineCharacters)) { text = Utils.replaceNoRegex(text, "\n", "\r"); } else if ("LF".equals(((StackH248) this.stack).endLineCharacters)) { } else { throw new ExecutionException( "The \"END_LINE_CHARACTERS\" configuration parameter should be a string from the list {CRLF, LF, CR}"); } decode(text.getBytes()); } //------------------------------------------------------ // method for the "setFromMessage" <parameter> operation //------------------------------------------------------ /** * Get a parameter from the message */ public Parameter getParameter(String path) throws Exception { Parameter var = super.getParameter(path); if (var != null) { return var; } var = new Parameter(); path = path.trim(); String[] params = Utils.splitPath(path); if (params[0].equalsIgnoreCase("header")) { if (params.length == 1) { var.add(header.getLine()); } else { header.addParameter(var, params[1]); } } else if (params[0].equalsIgnoreCase("authHeader")) { if (params.length == 1) { var.add(authHeader.getLine()); } else { authHeader.addParameter(var, params[1]); } } else if (params[0].equalsIgnoreCase("descr")) { if (params[1].equalsIgnoreCase("segmentNumber")) { var.add(this.getSegmentNumber()); } else if (params[1].equalsIgnoreCase("segmentComplete")) { var.add(this.getSegmentComplete()); } else { Descriptor des = this.descr; String[] p = Utils.splitNoRegex(params[0], "="); if ((des != null) && (des.getNameValue() != null) && (des.getNameValue().equalsParameter(p))) { if (!des.findAddParameters(var, params, 1)) { Parameter.throwBadPathKeywordException(path); } } } } else { Parameter.throwBadPathKeywordException(path); } return var; } }