/*
*
*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program 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 version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package com.sun.cdc.io.j2me.sip;
import com.sun.j2me.security.SecurityTokenInitializer;
import com.sun.j2me.security.TrustedClass;
import com.sun.j2me.security.Token;
import com.sun.j2me.io.ConnectionBaseInterface;
import gov.nist.core.ParseException;
import gov.nist.microedition.sip.StackConnector;
import gov.nist.siplite.address.SipURI;
import gov.nist.siplite.parser.URLParser;
import gov.nist.siplite.SIPConstants;
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.sip.SipException;
import com.sun.j2me.app.AppPackage;
import com.sun.j2me.security.SIPPermission;
import gov.nist.core.PushUtil;
/**
* This class implements the base necessary functionality
* for a SIP connection. Classes sip.Protocol and sips.Protocol
* are subclasses of ProtocolBase class
* This class is a thin wrapper around the NIST
* JSR180 implementation of the sip URI
* protocol handler.
* This class handles the security token
* intialization and invokes the NISt handler.
*/
public abstract class ProtocolBase
implements ConnectionBaseInterface {
/**
* Inner class to request security token from SecurityInitializer.
* SecurityInitializer should be able to check this inner class name.
*/
static private class SecurityTrusted
implements TrustedClass {};
/** Security token for SIP/SIPS protocol class */
private static Token classSecurityToken =
SecurityTokenInitializer.requestToken(new SecurityTrusted());
/**
* Checks if transport protocol is supported.
*
* @param protocol protocol name
*
* @return true when protocol is supported
*/
public boolean isProtocolSupported(String protocol) {
if (protocol == null) {
return false;
} else {
return protocol.equalsIgnoreCase(SIPConstants.TRANSPORT_UDP) ||
protocol.equalsIgnoreCase(SIPConstants.TRANSPORT_TCP);
}
}
/**
* Sets up the state of the connection, but
* does not actually connect to the server until there's something
* to do.
* <p>
* @param name the URL for the connection, without the
* without the protocol part.
* @param mode the access mode, ignored
* @param timeouts flag to indicate that the caller wants
* timeout exceptions, ignored
* @return reference to this connection
* @exception IllegalArgumentException if a parameter is invalid
* @exception ConnectionNotFoundException if the connection cannot be
* found
* @exception IOException if some other kind of I/O error occurs
*/
public abstract Connection openPrim(String name, int mode, boolean timeouts)
throws IOException, IllegalArgumentException,
ConnectionNotFoundException;
/**
* The Connector convenience methods to gain access to a specific
* input or output stream directly are not
* supported by the SIP API. The implementations MUST
* throw IOException if these methods are called with SIP URIs.
*/
/**
* Throw IOException on call openInputStream() method.
*
* @return nothing
* @exception IOException always throws
*
*/
public InputStream openInputStream() throws IOException {
throw new IOException("SIP connection doesn't support input stream");
}
/**
* Throw IOException on call openInputStream() method.
*
* @return nothing
* @exception IOException always throws
*
*/
public OutputStream openOutputStream() throws IOException {
throw new IOException("SIP connection doesn't support output stream");
}
/**
* Throw IOException on call openInputStream() method.
*
* @return nothing
* @exception IOException always throws
*
*/
public DataInputStream openDataInputStream() throws IOException {
throw new IOException("SIP connection doesn't support input stream");
}
/**
* Throw IOException on call openInputStream() method.
*
* @return nothing
* @exception IOException always throws
*
*/
public DataOutputStream openDataOutputStream() throws IOException {
throw new IOException("SIP connection doesn't support output stream");
}
/**
* Checks for the required permission.
* @param name resource to insert into the permission question
* @param protocol protocol name
* @param permission value of the permission constant
* @exception InterruptedIOException if another thread interrupts the
* calling thread while this method is waiting to preempt the
* display.
*/
static public void checkForPermission(String name, String protocol,
String permission) throws InterruptedIOException {
name = protocol + ":" + name;
try {
AppPackage.getInstance().checkForPermission(new SIPPermission(permission,
name));
} catch (InterruptedException ie) {
throw new InterruptedIOException(
"Interrupted while trying to ask the user permission");
}
}
/**
* Open a client or server socket connection.
*
* @param name the [{target}][{params}] for the connection
* @param scheme the scheme name (sip or sips)
*
* @return client or server SIPS connection
*
* @exception IOException if an I/O error occurs.
* @exception ConnectionNotFoundException if the host cannot be
* connected to
* @exception IllegalArgumentException if the name is malformed
*/
protected Connection openConn(String name, String scheme)
throws IOException, IllegalArgumentException, SipException {
Connection retval = null;
URLParser parser = new URLParser(scheme + ":" + name);
SipURI inputURI = null;
try {
inputURI = (SipURI)parser.parseWholeString();
} catch (ParseException exc) {
throw new IllegalArgumentException(exc.getMessage());
}
String transport = inputURI.getTransportParam();
if (transport == null) { // get default transport name
transport = SIPConstants.TRANSPORT_UDP;
} else if (!transport.equalsIgnoreCase(SIPConstants.TRANSPORT_UDP) &&
!transport.equalsIgnoreCase(SIPConstants.TRANSPORT_TCP)) {
throw new SipException(SipException.TRANSPORT_NOT_SUPPORTED);
}
int portNum = inputURI.getPort();
boolean isSecure = inputURI.isSecure();
StackConnector stackConnector =
StackConnector.getInstance(classSecurityToken);
if (inputURI.isServer()) { // server URI
String mimeType = inputURI.getTypeParam();
if (inputURI.isShared()) { // sip:*;type="application/..."
if (mimeType == null) { // no type parameter
throw new IllegalArgumentException("No type parameter "
+ "in shared URI");
}
/* Used for MIDP/CDC Push functionality */
retval = (Connection)PushUtil.getPushConnection(stackConnector,
scheme + ":" + name, mimeType);
if (retval == null) {
retval = (Connection)stackConnector.
createSharedSipConnectionNotifier(
isSecure,
transport,
mimeType);
}
} else { // dedicated sip:5060;...
/* Used for MIDP/CDC Push functionality */
retval = (Connection)PushUtil.getPushConnection(stackConnector,
scheme + ":" + name, portNum, mimeType);
if (retval == null) {
retval = (Connection)stackConnector.
createSipConnectionNotifier(
portNum,
isSecure,
transport,
mimeType);
}
}
} else { // client URI
if (portNum == -1) { // set default port
inputURI.setPort(SIPConstants.DEFAULT_NONTLS_PORT);
}
retval = (Connection) stackConnector.
createSipClientConnection(inputURI);
}
return retval;
}
}