/*
|
* %CopyrightBegin%
|
*
|
* Copyright Ericsson AB 2000-2010. All Rights Reserved.
|
*
|
* Licensed 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.
|
*
|
* %CopyrightEnd%
|
*/
|
package com.ericsson.otp.erlang;
|
|
/**
|
* <p>
|
* Provides a carrier for Erlang messages.
|
* </p>
|
* <p>
|
* <p>
|
* Instances of this class are created to package header and payload information
|
* in received Erlang messages so that the recipient can obtain both parts with
|
* a single call to {@link OtpMbox#receiveMsg receiveMsg()}.
|
* </p>
|
* <p>
|
* <p>
|
* The header information that is available is as follows:
|
* <ul>
|
* <li>a tag indicating the type of message
|
* <li>the intended recipient of the message, either as a {@link OtpErlangPid
|
* pid} or as a String, but never both.
|
* <li>(sometimes) the sender of the message. Due to some eccentric
|
* characteristics of the Erlang distribution protocol, not all messages have
|
* information about the sending process. In particular, only messages whose tag
|
* is {@link OtpMsg#regSendTag regSendTag} contain sender information.
|
* </ul>
|
* <p>
|
* <p>
|
* Message are sent using the Erlang external format (see separate
|
* documentation). When a message is received and delivered to the recipient
|
* {@link OtpMbox mailbox}, the body of the message is still in this external
|
* representation until {@link #getMsg getMsg()} is called, at which point the
|
* message is decoded. A copy of the decoded message is stored in the OtpMsg so
|
* that subsequent calls to {@link #getMsg getMsg()} do not require that the
|
* message be decoded a second time.
|
* </p>
|
*/
|
public class OtpMsg {
|
public static final int linkTag = 1;
|
public static final int sendTag = 2;
|
public static final int exitTag = 3;
|
public static final int unlinkTag = 4;
|
public static final int regSendTag = 6;
|
/* public static final int groupLeaderTag = 7; */
|
public static final int exit2Tag = 8;
|
protected int tag; // what type of message is this (send, link, exit etc)
|
protected OtpInputStream paybuf;
|
protected OtpErlangObject payload;
|
protected OtpErlangPid from;
|
protected OtpErlangPid to;
|
protected String toName;
|
|
// send has receiver pid but no sender information
|
OtpMsg(final OtpErlangPid to, final OtpInputStream paybuf) {
|
tag = sendTag;
|
from = null;
|
this.to = to;
|
toName = null;
|
this.paybuf = paybuf;
|
payload = null;
|
}
|
|
// send has receiver pid but no sender information
|
OtpMsg(final OtpErlangPid to, final OtpErlangObject payload) {
|
tag = sendTag;
|
from = null;
|
this.to = to;
|
toName = null;
|
paybuf = null;
|
this.payload = payload;
|
}
|
|
// send_reg has sender pid and receiver name
|
OtpMsg(final OtpErlangPid from, final String toName,
|
final OtpInputStream paybuf) {
|
tag = regSendTag;
|
this.from = from;
|
this.toName = toName;
|
to = null;
|
this.paybuf = paybuf;
|
payload = null;
|
}
|
|
// send_reg has sender pid and receiver name
|
OtpMsg(final OtpErlangPid from, final String toName,
|
final OtpErlangObject payload) {
|
tag = regSendTag;
|
this.from = from;
|
this.toName = toName;
|
to = null;
|
paybuf = null;
|
this.payload = payload;
|
}
|
|
// exit (etc) has from, to, reason
|
OtpMsg(final int tag, final OtpErlangPid from, final OtpErlangPid to,
|
final OtpErlangObject reason) {
|
this.tag = tag;
|
this.from = from;
|
this.to = to;
|
paybuf = null;
|
payload = reason;
|
}
|
|
// special case when reason is an atom (i.e. most of the time)
|
OtpMsg(final int tag, final OtpErlangPid from, final OtpErlangPid to,
|
final String reason) {
|
this.tag = tag;
|
this.from = from;
|
this.to = to;
|
paybuf = null;
|
payload = new OtpErlangAtom(reason);
|
}
|
|
// other message types (link, unlink)
|
OtpMsg(final int tag, final OtpErlangPid from, final OtpErlangPid to) {
|
// convert TT-tags to equiv non-TT versions
|
int atag = tag;
|
if (tag > 10) {
|
atag -= 10;
|
}
|
this.tag = atag;
|
this.from = from;
|
this.to = to;
|
}
|
|
/**
|
* Get the payload from this message without deserializing it.
|
*
|
* @return the serialized Erlang term contained in this message.
|
*/
|
OtpInputStream getMsgBuf() {
|
return paybuf;
|
}
|
|
/**
|
* <p>
|
* Get the type marker from this message. The type marker identifies the
|
* type of message. Valid values are the ``tag'' constants defined in this
|
* class.
|
* </p>
|
* <p>
|
* <p>
|
* The tab identifies not only the type of message but also the content of
|
* the OtpMsg object, since different messages have different components, as
|
* follows:
|
* </p>
|
* <p>
|
* <ul>
|
* <li>sendTag identifies a "normal" message. The recipient is a
|
* {@link OtpErlangPid Pid} and it is available through
|
* {@link #getRecipientPid getRecipientPid()}. Sender information is not
|
* available. The message body can be retrieved with {@link #getMsg
|
* getMsg()}.</li>
|
* <p>
|
* <li>regSendTag also identifies a "normal" message. The recipient here is
|
* a String and it is available through {@link #getRecipientName
|
* getRecipientName()}. Sender information is available through
|
* #getSenderPid getSenderPid()}. The message body can be retrieved with
|
* {@link #getMsg getMsg()}.</li>
|
* <p>
|
* <li>linkTag identifies a link request. The Pid of the sender is
|
* available, as well as the Pid to which the link should be made.</li>
|
* <p>
|
* <li>exitTag and exit2Tag messages are sent as a result of broken links.
|
* Both sender and recipient Pids and are available through the
|
* corresponding methods, and the "reason" is available through
|
* {@link #getMsg getMsg()}.</li>
|
* </ul>
|
*/
|
public int type() {
|
return tag;
|
}
|
|
/**
|
* <p>
|
* Deserialize and return a new copy of the message contained in this
|
* OtpMsg.
|
* </p>
|
* <p>
|
* <p>
|
* The first time this method is called the actual payload is deserialized
|
* and the Erlang term is created. Calling this method subsequent times will
|
* not cuase the message to be deserialized additional times, instead the
|
* same Erlang term object will be returned.
|
* </p>
|
*
|
* @return an Erlang term.
|
* @throws OtpErlangDecodeException if the byte stream could not be deserialized.
|
*/
|
public OtpErlangObject getMsg() throws OtpErlangDecodeException {
|
if (payload == null) {
|
payload = paybuf.read_any();
|
}
|
return payload;
|
}
|
|
/**
|
* <p>
|
* Get the name of the recipient for this message.
|
* </p>
|
* <p>
|
* <p>
|
* Messages are sent to Pids or names. If this message was sent to a name
|
* then the name is returned by this method.
|
* </p>
|
*
|
* @return the name of the recipient, or null if the recipient was in fact a
|
* Pid.
|
*/
|
public String getRecipientName() {
|
return toName;
|
}
|
|
/**
|
* <p>
|
* Get the Pid of the recipient for this message, if it is a sendTag
|
* message.
|
* </p>
|
* <p>
|
* <p>
|
* Messages are sent to Pids or names. If this message was sent to a Pid
|
* then the Pid is returned by this method. The recipient Pid is also
|
* available for link, unlink and exit messages.
|
* </p>
|
*
|
* @return the Pid of the recipient, or null if the recipient was in fact a
|
* name.
|
*/
|
public OtpErlangPid getRecipientPid() {
|
return to;
|
}
|
|
/**
|
* <p>
|
* Get the name of the recipient for this message, if it is a regSendTag
|
* message.
|
* </p>
|
* <p>
|
* <p>
|
* Messages are sent to Pids or names. If this message was sent to a name
|
* then the name is returned by this method.
|
* </p>
|
*
|
* @return the Pid of the recipient, or null if the recipient was in fact a
|
* name.
|
*/
|
public Object getRecipient() {
|
if (toName != null) {
|
return toName;
|
}
|
return to;
|
}
|
|
/**
|
* <p>
|
* Get the Pid of the sender of this message.
|
* </p>
|
* <p>
|
* <p>
|
* For messages sent to names, the Pid of the sender is included with the
|
* message. The sender Pid is also available for link, unlink and exit
|
* messages. It is not available for sendTag messages sent to Pids.
|
* </p>
|
*
|
* @return the Pid of the sender, or null if it was not available.
|
*/
|
public OtpErlangPid getSenderPid() {
|
return from;
|
}
|
}
|