📄 pdu.java
字号:
throw new InvalidPDUException(this, e);
} catch (TerminatingZeroNotFoundException e) {
throw new InvalidPDUException(this, e);
} catch (PDUException e) {
e.setPDU(this);
throw e;
} catch (Exception e) {
// transform generic exception into InvalidPDUException
throw new InvalidPDUException(this, e);
}
if (buffer.length() != (initialBufLen - getCommandLength())) {
// i.e. we've parsed out different number of bytes
// than is specified by command length in the pdu's header
throw new InvalidPDUException(this, "The parsed size of the message is not equal to command_length.");
}
}
/**
* Construct the binary PDU for sending to SMSC.
* First creates the mandatory part using <code>getBody</code> method,
* which has to be implemented in the derived classes (if they
* represent PDU with body), then creates the optional part of the PDU
* using <code>getOptionalBody</code>, which is common for all PDUs.
* Calculates the size of the PDU and then creates the header using
* <code>getHeader</code> and returns the full binary PDU.
* @see #getBody()
* @see #getOptionalBody(Vector)
* @see #getHeader()
* @see #setData(ByteBuffer)
*/
public ByteBuffer getData() throws ValueNotSetException {
// prepare all body
ByteBuffer bodyBuf = new ByteBuffer();
bodyBuf.appendBuffer(getBody());
bodyBuf.appendBuffer(getOptionalBody());
// get its size and add size of the header; set the result as length
setCommandLength(bodyBuf.length() + Data.PDU_HEADER_SIZE);
ByteBuffer pduBuf = getHeader();
pduBuf.appendBuffer(bodyBuf);
if (debug.active(DPDU)) {
debug.write(DPDU, "PDU.getData() build up data " + pduBuf.getHexDump());
}
return pduBuf;
}
/** Sets if the PDU contains correctly formated data. */
public void setValid(byte valid) {
this.valid = valid;
}
/** Returns if the PDU contains correctly formated data. */
public byte getValid() {
return valid;
}
/**
* Returns if the parsing of the binary PDU data successfully parsed
* complete PDU.
*/
public boolean isValid() {
return getValid() == VALID_ALL;
}
/**
* Returns if the parsing of the binary PDU data ended before parsing
* of the header.
*/
public boolean isInvalid() {
return getValid() == VALID_NONE;
}
/** Returns if at least the header of the binary PDU data was correct. */
public boolean isHeaderValid() {
return getValid() >= VALID_HEADER;
}
/**
* Parses the header from the buffer.
* Also sets the flag that the sequence number was changed as it was read
* from the binary buffer.
* @param buffer the buffer which contains the PDU
* @see PDUHeader#setData(ByteBuffer)
*/
private void setHeader(ByteBuffer buffer) throws NotEnoughDataInByteBufferException {
checkHeader();
header.setData(buffer);
sequenceNumberChanged = true;
}
/** Creates the binary PDU header from the header fields of the PDU. */
private ByteBuffer getHeader() {
checkHeader();
return header.getData();
}
/**
* Parses the binary buffer and obtains all optional parameters
* which the buffer contains, sets the optional parameter fields.
* The optional parameter fields which the PDU can contain must be
* registered by the derived class using <code>registerOptional</code>.
* Or there can be extra optional parameters with application/smsc specific tags,
* which aren't defined in the SMPP specification.
* The optional parameters defined in SMPP are accessible using appropriate
* getter functions in the derived PDU classes, the extra optional
* parameters are accessible with generic function <code>getExtraOptional</code>.
* The buffer can't contain another data then the optional parameters.
*
* @param buffer the buffer with the optional parameters
* @exception UnexpectedOptionalParameterException if the optional
* parameter read from the buffer cna't be contained
* int this PDU
* @see #getOptionalBody()
* @see #getExtraOptional(short)
* @see TLV
*/
private void setOptionalBody(ByteBuffer buffer)
throws NotEnoughDataInByteBufferException, UnexpectedOptionalParameterException, TLVException {
short tag;
short length;
ByteBuffer tlvHeader;
ByteBuffer tlvBuf;
TLV tlv = null;
while (buffer.length() > 0) {
// we prepare buffer with one parameter
tlvHeader = buffer.readBytes(Data.TLV_HEADER_SIZE);
tag = tlvHeader.removeShort();
tlv = findOptional(optionalParameters, tag);
if (tlv == null) {
// ok, got extra optional parameter not defined in SMPP spec
// will keep it as octets
tlv = new TLVOctets(tag);
registerExtraOptional(tlv);
}
length = tlvHeader.removeShort();
tlvBuf = buffer.removeBuffer(Data.TLV_HEADER_SIZE + length);
tlv.setData(tlvBuf);
}
}
/**
* Creates buffer with all the optional parameters which have set
* their value, both from the optional parameters defined in SMPP
* and extra optional parameters.
* @see #setOptionalBody(ByteBuffer)
* @see TLV#hasValue()
* @see TLV#getData()
* @see TLV
*/
private ByteBuffer getOptionalBody() throws ValueNotSetException {
ByteBuffer optBody = new ByteBuffer();
optBody.appendBuffer(getOptionalBody(optionalParameters));
optBody.appendBuffer(getOptionalBody(extraOptionalParameters));
return optBody;
}
/**
* Creates buffer with all the optional parameters contained in
* the <code>optionalParameters</code> list which have set
* their value. For getting data of the optional parameter calls
* a method <code>getData</code> of the <code>TLV</code> class.
* @see #setOptionalBody(ByteBuffer)
* @see TLV#hasValue()
* @see TLV#getData()
* @see TLV
*/
private ByteBuffer getOptionalBody(Vector optionalParameters) throws ValueNotSetException {
ByteBuffer optBody = new ByteBuffer();
int size = optionalParameters.size();
TLV tlv = null;
for (int i = 0; i < size; i++) {
tlv = (TLV) optionalParameters.get(i);
if ((tlv != null) && tlv.hasValue()) {
optBody.appendBuffer(tlv.getData());
}
}
return optBody;
}
/**
* Registeres a TLV as an optional parameter which can be containd in
* the PDU. Derived classes are expected that they will define appropriate
* TLVs and register them using this method. Only registered TLVs
* can be read as optional parameters from binary PDU received from SMSC.
* @param tlv the TLV to be registered as an optional parameter
* @see TLV
*/
protected void registerOptional(TLV tlv) {
if (tlv != null) {
optionalParameters.add(tlv);
}
}
/**
* Registeres a TLV as an extra optional parameter which can be contained in
* the PDU. Extra optional parameter is TLV not defined in SMPP spec.
* The reason for this method is that if you know what type and size
* certain extra optional parameter has to be, then you can create an instance
* of appropriate TLV class, e.g. <code>TLVInt</code> class and register it as
* the carrying TLV instead of using the generic <code>TLVOctets</code> class.
* @param tlv the TLV to be registered as an extra optional parameter
* @see TLV
*/
protected void registerExtraOptional(TLV tlv) {
if (tlv != null) {
extraOptionalParameters.add(tlv);
}
}
/**
* Searches for registered or extra TLV with the given TLV tag.
* Returns the found TLV or null if not found. Used when parsing
* the optional part of the binary PDU data.
* @param tag the tag of the TLV required
* @return the found TLV
* @see #setOptionalBody(ByteBuffer)
* @see #registerOptional(TLV)
* @see #registerExtraOptional(TLV)
* @see TLV
*/
private TLV findOptional(Vector optionalParameters, short tag) {
int size = optionalParameters.size();
TLV tlv = null;
for (int i = 0; i < size; i++) {
tlv = (TLV) optionalParameters.get(i);
if (tlv != null) {
if (tlv.getTag() == tag) {
return tlv;
}
}
}
return null;
}
/**
* Replaces the TLV in the extra optional parameters list with the
* new tlv provided as a parameter. If the tlv doesn't exist in the list,
* adds it to the list.
*/
private void replaceExtraOptional(TLV tlv) {
int size = extraOptionalParameters.size();
TLV existing = null;
short tlvTag = tlv.getTag();
for (int i = 0; i < size; i++) {
existing = (TLV) extraOptionalParameters.get(i);
if ((existing != null) && (existing.getTag() == tlvTag)) {
extraOptionalParameters.set(i, tlv);
return;
}
}
registerExtraOptional(tlv); // the optional param wasn't found
}
/**
* Sets the extra optional parameter.
*/
public void setExtraOptional(TLV tlv) {
replaceExtraOptional(tlv);
}
/**
* Creates new generic extra optional parameter with tag and data provided;
* uses TLVOctets for the parameter.
*/
public void setExtraOptional(short tag, ByteBuffer data) throws TLVException {
TLV tlv = new TLVOctets(tag, data);
setExtraOptional(tlv);
}
/**
* Finds and returns extra optional parameter with the provided
* tag; if not found returns null.
*/
public TLV getExtraOptional(short tag) {
TLV tlv = findOptional(extraOptionalParameters, tag);
return tlv;
}
/** Checks if the header field is null and if not, creates it. */
private void checkHeader() {
if (header == null) {
header = new PDUHeader();
}
}
/**
* Returns the length of this PDU.
* The length is only valid if you probe the PDU which was parsed from
* binary data received from SMSC. If you created the PDU and filled in the
* filds of the PDU, the length returned by this function will be very
* likely incorrect.
*/
public int getCommandLength() {
checkHeader();
return header.getCommandLength();
}
/**
* Returns the command id of the PDU object.
* The command id can be either read from the binary data received from SMSC
* or can be set by derived class as the command id of the PDU which is
* represented by the class.
*/
public int getCommandId() {
checkHeader();
return header.getCommandId();
}
/** Returns the command status of the PDU. */
public int getCommandStatus() {
checkHeader();
return header.getCommandStatus();
}
/**
* Returns the sequence number of the PDU.
* If the PDU is created by yourself and not parsed from binary data
* received from SMSC, then the sequence number will be very likely
* incorrect until you didn't set it previously by calling function
* <code>assignSequenceNumber</code> or <code>setSequenceNumber</code>.
* @see #assignSequenceNumber()
* @see #setSequenceNumber(int)
*/
public int getSequenceNumber() {
checkHeader();
return header.getSequenceNumber();
}
/**
* Sets the length of the PDU. Don't do it manually, it won't have
* any wffect.
*/
public void setCommandLength(int cmdLen) {
checkHeader();
header.setCommandLength(cmdLen);
}
/** Sets the command id. */
public void setCommandId(int cmdId) {
checkHeader();
header.setCommandId(cmdId);
}
/**
* Sets the command status, i.e. error status of the PDU.
*/
public void setCommandStatus(int cmdStatus) {
checkHeader();
header.setCommandStatus(cmdStatus);
}
/**
* Sets the sequence number of the PDU.
* For PDUs whic are about to be sent to SMSC the sequence number is
* generated automatically in the <code>Transmitter</code> class and
* under normal cicumstances there is no need to set it explicitly.
*/
public void setSequenceNumber(int seqNr) {
checkHeader();
header.setSequenceNumber(seqNr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -