/* * Copyright (C) 2005 Luca Veltri - University of Parma - Italy * * This file is part of MjSip (http://www.mjsip.org) * * MjSip 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 2 of the License, or * (at your option) any later version. * * MjSip 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 MjSip; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author(s): * Luca Veltri (luca.veltri@unipr.it) */ package org.zoolu.sip.message; import org.zoolu.sip.provider.*; import org.zoolu.sip.header.*; import org.zoolu.sip.address.*; import org.zoolu.sip.message.SipMethods; import org.zoolu.net.UdpPacket; import java.util.*; /** Class BaseMessageOtp implements a generic SIP Message. * It extends class BaseMessage adding one-time-parsing functionality * (it parses the entire Message just when it is costructed). * <p/> At the contrary, class BaseMessage works in a just-in-time manner * (it parses the message each time a particular header field is requested). */ public abstract class BaseMessageOtp extends BaseMessage { protected RequestLine request_line; protected StatusLine status_line; protected Vector headers; protected String body; /** Inits empty Message */ private void init() { request_line=null; status_line=null; headers=null; body=null; } /** Costructs a new empty Message */ public BaseMessageOtp() { init(); headers=new Vector(); } /** Costructs a new Message */ public BaseMessageOtp(byte[] data, int offset, int len) { init(); parseIt(new String(data,offset,len)); } /** Costructs a new Message */ public BaseMessageOtp(UdpPacket packet) { init(); parseIt(new String(packet.getData(),packet.getOffset(),packet.getLength())); } /** Costructs a new Message */ public BaseMessageOtp(String str) { init(); parseIt(str); } /** Costructs a new Message */ public BaseMessageOtp(BaseMessageOtp msg) { init(); remote_addr=msg.remote_addr; remote_port=msg.remote_port; transport_proto=msg.transport_proto; connection_id=msg.connection_id; //packet_length=msg.packet_length; request_line=msg.request_line; status_line=msg.status_line; headers=new Vector(); for (int i=0; i<msg.headers.size(); i++) headers.addElement(msg.headers.elementAt(i)); body=msg.body; } /** Sets the entire message */ public void setMessage(String str) { parseIt(str); } /** Parses the Message from a String. */ private void parseIt(String str) { SipParser par=new SipParser(str); String version=str.substring(0,4); if (version.equalsIgnoreCase("SIP/")) status_line=par.getStatusLine(); else request_line=par.getRequestLine(); headers=new Vector(); Header h=par.getHeader(); while (h!=null) { headers.addElement(h); h=par.getHeader(); } ContentLengthHeader clh=getContentLengthHeader(); if (clh!=null) { int len=clh.getContentLength(); body=par.getString(len); } else if (getContentTypeHeader()!=null) { body=par.getRemainingString(); if (body.length()==0) body=null; } } /** Gets string representation of Message */ public String toString() { StringBuffer str=new StringBuffer(); if (request_line!=null) str.append(request_line.toString()); else if (status_line!=null) str.append(status_line.toString()); for (int i=0; i<headers.size(); i++) str.append(((Header)headers.elementAt(i)).toString()); str.append("\r\n"); if (body!=null) str.append(body); return str.toString(); } /** Gets message length */ public int getLength() { return toString().length(); } //**************************** Requests ****************************/ /** Whether Message is a Request */ public boolean isRequest() { if (request_line!=null) return true; else return false; } /** Whether Message is a <i>method</i> request */ public boolean isRequest(String method) { if (request_line!=null && request_line.getMethod().equalsIgnoreCase(method)) return true; else return false; } /** Whether Message has Request-line */ protected boolean hasRequestLine() { return request_line!=null; } /** Gets RequestLine in Message (Returns null if called for no request message) */ public RequestLine getRequestLine() { return request_line; } /** Sets RequestLine of the Message */ public void setRequestLine(RequestLine rl) { request_line=rl; } /** Removes RequestLine of the Message */ public void removeRequestLine() { request_line=null; } //**************************** Responses ****************************/ /** Whether Message is a Response */ public boolean isResponse() throws NullPointerException { if (status_line!=null) return true; else return false; } /** Whether Message has Status-line */ protected boolean hasStatusLine() { return status_line!=null; } /** Gets StautsLine in Message (Returns null if called for no response message) */ public StatusLine getStatusLine() { return status_line; } /** Sets StatusLine of the Message */ public void setStatusLine(StatusLine sl) { status_line=sl; } /** Removes StatusLine of the Message */ public void removeStatusLine() { status_line=null; } //**************************** Generic Headers ****************************/ /** Removes Request\Status Line of the Message */ protected void removeFirstLine() { removeRequestLine(); removeStatusLine(); } /** Gets the position of header <i>hname</i>. */ protected int indexOfHeader(String hname) { for (int i=0; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) return i; } return -1; } /** Gets the first Header of specified name (Returns null if no Header is found) */ public Header getHeader(String hname) { int i=indexOfHeader(hname); if (i<0) return null; else return (Header)headers.elementAt(i); } /** Gets a Vector of all Headers of specified name (Returns empty Vector if no Header is found) */ public Vector getHeaders(String hname) { Vector v=new Vector(); for (int i=0; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) v.addElement(h); } return v; } /** Adds Header at the top/bottom. * The bottom is considered before the Content-Length and Content-Type headers */ public void addHeader(Header header, boolean top) { if (top) headers.insertElementAt(header,0); else headers.addElement(header); } /** Adds a Vector of Headers at the top/bottom */ public void addHeaders(Vector headers, boolean top) { for (int i=0; i<headers.size(); i++) if (top) this.headers.insertElementAt(headers.elementAt(i),i); else this.headers.addElement(headers.elementAt(i)); } /** Adds MultipleHeader(s) <i>mheader</i> at the top/bottom */ public void addHeaders(MultipleHeader mheader, boolean top) { if (mheader.isCommaSeparated()) addHeader(mheader.toHeader(),top); else addHeaders(mheader.getHeaders(),top); } /** Adds Header before the first header <i>refer_hname</i> * . <p>If there is no header of such type, it is added at top */ public void addHeaderBefore(Header new_header, String refer_hname) { int i=indexOfHeader(refer_hname); if (i<0) i=0; headers.insertElementAt(new_header,i); } /** Adds MultipleHeader(s) before the first header <i>refer_hname</i> * . <p>If there is no header of such type, they are added at top */ public void addHeadersBefore(MultipleHeader mheader, String refer_hname) { if (mheader.isCommaSeparated()) addHeaderBefore(mheader.toHeader(),refer_hname); else { int index=indexOfHeader(refer_hname); if (index<0) index=0; Vector hs=mheader.getHeaders(); for (int k=0; k<hs.size(); k++) headers.insertElementAt(hs.elementAt(k),index+k); } } /** Adds Header after the first header <i>refer_hname</i> * . <p>If there is no header of such type, it is added at bottom */ public void addHeaderAfter(Header new_header, String refer_hname) { int i=indexOfHeader(refer_hname); if (i>=0) i++; else i=headers.size(); headers.insertElementAt(new_header,i); } /** Adds MultipleHeader(s) after the first header <i>refer_hname</i> * . <p>If there is no header of such type, they are added at bottom */ public void addHeadersAfter(MultipleHeader mheader, String refer_hname) { if (mheader.isCommaSeparated()) addHeaderAfter(mheader.toHeader(),refer_hname); else { int index=indexOfHeader(refer_hname); if (index>=0) index++; else index=headers.size(); Vector hs=mheader.getHeaders(); for (int k=0; k<hs.size(); k++) headers.insertElementAt(hs.elementAt(k),index+k); } } /** Removes first Header of specified name */ public void removeHeader(String hname) { removeHeader(hname,true); } /** Removes first (or last) Header of specified name. */ public void removeHeader(String hname, boolean first) { int index=-1; for (int i=0 ; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) { index=i; if (first) i=headers.size(); } } if (index>=0) headers.removeElementAt(index); } /** Removes all Headers of specified name */ public void removeAllHeaders(String hname) { for (int i=0 ; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) { headers.removeElementAt(i); i--; } } } /** Sets the Header <i>hd</i> removing any previous headers of the same type. */ public void setHeader(Header hd) { boolean first=true; String hname=hd.getName(); for (int i=0 ; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) { if (first) { // replace it headers.setElementAt(h,i); first=false; } else { // remove it headers.removeElementAt(i); i--; } } } if (first) headers.addElement(hd); } /** Sets MultipleHeader <i>mheader</i> */ public void setHeaders(MultipleHeader mheader) { if (mheader.isCommaSeparated()) setHeader(mheader.toHeader()); else { boolean first=true; String hname=mheader.getName(); for (int i=0 ; i<headers.size(); i++) { Header h=(Header)headers.elementAt(i); if (hname.equalsIgnoreCase(h.getName())) { if (first) { // replace it Vector hs=mheader.getHeaders(); for (int k=0; k<hs.size(); k++) headers.insertElementAt(hs.elementAt(k),i+k); first=false; i+=hs.size()-1; } else { // remove it headers.removeElementAt(i); i--; } } } } } //**************************** Specific Headers ****************************/ /** Whether Message has Body */ public boolean hasBody() { return this.body!=null; } /** Gets body(content) type */ public String getBodyType() { return getContentTypeHeader().getContentType(); } /** Sets the message body */ public void setBody(String content_type, String body) { removeBody(); if (body!=null && body.length()>0) { setContentTypeHeader(new ContentTypeHeader(content_type)); setContentLengthHeader(new ContentLengthHeader(body.length())); this.body=body; } else { setContentLengthHeader(new ContentLengthHeader(0)); this.body=null; } } /** Gets message body. The end of body is evaluated * from the Content-Length header if present (SIP-RFC compliant), * or from the end of message if no Content-Length header is present (non-SIP-RFC compliant) */ public String getBody() { return this.body; } /** Removes the message body (if it exists) and the final empty line */ public void removeBody() { removeContentLengthHeader(); removeContentTypeHeader(); this.body=null; } }