ServerHandler.java :  » Mobile » jimm-fork-van » protocol » msn » Java Open Source

Java Open Source » Mobile » jimm fork van 
jimm fork van » protocol » msn » ServerHandler.java
/* JIMMY - Instant Mobile Messenger
   Copyright (C) 2006  JIMMY Project
 
 This program 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.
 
 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 for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **********************************************************************
 File: jimmy/ServerHandler.java
 
 Author(s): Zoran Mesec, Matevz Jekovec
 */
// #sijapp cond.if protocols_MSN is "true" #
package protocol.msn;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;

import javax.microedition.io.Connector;
import javax.microedition.io.SocketConnection;
import jimm.comm.StringConvertor;

/**
 * This class is used to connect to a remote server using SocketConnection class.
 * This is the way how all the communication between the mobile phone and IM servers should be done.
 * The class always creates read/write type of the connection automatically.
 *
 * Usage:
 * 1) Class should be created passing the server URL without the "protocol://" prefix and a port which to connect to.
 *    ServerHandler sh_ = new ServerHandler("messenger.hotmail.com","1863");
 * 2) sh_.setTimeout(10000); //set timeout to 10 seconds - we have a really bad connection :)
 * 2) sh_.connect();
 * 3) sendRequest("VER 1 MSNP8 CVR0\r\n")
 * 4) String myReply = getReply();
 *
 * @author Zoran Mesec
 * @author Matevz Jekovec
 */
public class ServerHandler {
    private String url_;  //server URL without the leading "protocol://"
    private int outPort_;  //output port we connect to
    private int inPort_;  //input port the connection is made to
    private SocketConnection sc_;  //main connection
    private DataOutputStream os_;  //output stream linked with sc_
    private DataInputStream is_;  //input stream linked with sc_
    private final int SLEEPTIME_ = 50;  //sleep time per iteration in miliseconds
    private int timeout_ = 5000;  //timeout of getting the reply
    private boolean connected_ = false;  //connection status
    private boolean isNokia_ = false;   //if app runs on a Nokia phone
    
    /**
     * The constructor method.
     *
     * @param url URL of the server without the leading "protocol://" - No protocol type specified here! eg. messenger.hotmail.com
     * @param port Server port which to connect to. eg. 1863 for MSN.
     */
    public ServerHandler(String url, int port) {
        url_ = url;
        outPort_ = port;
        connected_ = false;
        if(System.getProperty("microedition.platform").toLowerCase().indexOf("nokia")!=-1) this.isNokia_=true;
    }
    
    /**
     * The constructor method. If no port is used (ie. use the default port - 80 http), use this constructor method.
     *
     * @param URL URL of the server.
     */
    public ServerHandler(String url) {
        this(url,0);
    }
    
    /**
     * Set the timeout before stop checking the read buffer.
     *
     * @param timeout Timeout value in miliseconds
     */
    public void setTimeout(int timeout) {
        this.timeout_ = timeout;
    }
    
    /**
     * Open the connection to the specified URL and port passed in the constructor using the SocketConnection class.
     *
     * @param useSSL Connect using Secure Socket Layer connection
     */
    public void connect(boolean useSSL) {
        try {
            this.sc_ = (SocketConnection)Connector.open( (useSSL?"ssl://":"socket://") + url_ +
                    ((outPort_ == 0) ? "" : (":" + String.valueOf(outPort_))) );
//          this.sc_ = (SocketConnection)Connector.open("socket://" + this.url_ + ":" + String.valueOf(this.outPort_));
            this.inPort_ = this.sc_.getLocalPort();
            this.os_ = this.sc_.openDataOutputStream();
            this.is_ = this.sc_.openDataInputStream();
            this.connected_ = true;
        }catch(SecurityException e){
            //in case NO is pressed on overair question
        }catch (IOException e){
            e.printStackTrace();
            this.connected_ = false;
        }
    }
    /**
     * This method is provided for convenience.
     * It triggers connect(false).
     */
    public void connect() {
        connect(false);
    }
    
    /**
     * Disconnect the SocketConnection and IO streams.
     */
    public void disconnect() {
        try {
            is_.close();
            os_.flush();  //flush the output stream before closing it!
            os_.close();
            sc_.close();
            connected_ = false;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * Send a message to the remote server using the OutputStream.
     *
     * @param message Message to be sent using the OutputStream to the remote server using SocketConnection.
     */
    public void sendRequest(String message) {
        sendRequest(StringConvertor.stringToByteArrayUtf8(message));
    }
    public void sendRequest(String message, byte[] body) {
        // #sijapp cond.if modules_DEBUGLOG is "true" #
        jimm.modules.DebugLog.println("MSN out: " + message + StringConvertor.utf8beByteArrayToString(body, 0, body.length));
        // #sijapp cond.end #
        try {
            os_.write(StringConvertor.stringToByteArrayUtf8(message));
            os_.write(body);
            os_.flush();
            
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * Send a message to the remote server using the OutputStream.
     *
     * @param message Message to be sent using the OutputStream to the remote server using SocketConnection.
     */
    public void sendRequest(byte[] message) {
        // #sijapp cond.if modules_DEBUGLOG is "true" #
        jimm.modules.DebugLog.println("MSN out: " + StringConvertor.utf8beByteArrayToString(message, 0, message.length));
        // #sijapp cond.end #
//      System.out.println("[DEBUG] OUT:\n" + Utils.byteArrayToHexString(message));
        
        try {
            os_.write(message);
            os_.flush();
            
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * Read a message from the remote server reading the waiting buffer. If waiting buffer is empty, wait until it gets filled or if timeout occurs.
     * This method reads and empties the WHOLE buffer (ie. doesn't stop at new line)!
     *
     * @return Message from the remote server as a String in UTF-8 encoding, null if timeout has occured.
     */
    public String getReply() {
        return getReply(null);
    }
    
    /**
     * Read a message from the remote server reading the waiting buffer. If waiting buffer is empty, wait until it gets filled or if timeout occurs.
     * This method reads and empties the WHOLE buffer (ie. doesn't stop at new line)!
     *
     * @param enc Return String in the given encoding. See http://java.sun.com/j2se/1.5.0/docs/api/java/nio/charset/Charset.html for additional information on String encodings.
     * @return Message from the remote server as a String in UTF-8 encoding, null if timeout has occured.
     */
    public String getReply(String enc) {
        if (enc == null) enc = "UTF-8";
        byte[] buffer = getReplyLine();
        if ((null != buffer) && (0 != buffer.length)) {
            // #sijapp cond.if modules_DEBUGLOG is "true" #
            jimm.modules.DebugLog.println("MSN in: " + StringConvertor.utf8beByteArrayToString(buffer, 0, buffer.length));
            // #sijapp cond.end #
            return StringConvertor.utf8beByteArrayToString(buffer, 0, buffer.length);
        }
        return null;
    }
    public boolean available() {
        try {
            return 0 < is_.available();
        } catch (IOException ex) {
            connected_ = false;
            return false;
        }
    }
    public byte[] getReplyBytes(int count) {
        byte[] data = new byte[count];
        try {
            int readed = 0;
            while (true) {
                int read = is_.read(data, readed, count - readed);
                if (read < 0) break;
                readed += read;
                if (readed == count) break;
                if (!available()) {
                    try {
                        Thread.sleep(50);
                    } catch (Exception e) {
                    }
                }
            }
            // #sijapp cond.if modules_DEBUGLOG is "true" #
            jimm.modules.DebugLog.println("___ in: " + StringConvertor.utf8beByteArrayToString(data, 0, data.length));
            // #sijapp cond.end #
        } catch (Exception ex) {
            connected_ = false;
            ex.printStackTrace();
            return null;
        }
        return data;
    }
    /**
     * Read a message from the remote server reading the waiting buffer. If waiting buffer is empty, wait until it gets filled or if timeout occurs.
     * This method reads and empties the WHOLE buffer (ie. doesn't stop at new line)!
     *
     * @return Message from the remote server as a byte[]. null if timeout has occured
     */
    public byte[] getReplyLine() {
        try {
            ByteArrayOutputStream result = new ByteArrayOutputStream();
            while (0 == is_.available()) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                }
            }
            while (true) {
                int read = is_.available();
                while (0 < read--) {
                    int ch = is_.read();
                    if (read < 0) return null;
                    if ('\r' == ch) continue;
                    if ('\n' == ch) {
                        return (0 == result.size()) ? null : result.toByteArray();
                    }
                    result.write(ch);
                }
                try {
                    Thread.sleep(50);
                } catch (Exception e) {
                }
            }
        }catch (InterruptedIOException ex){
//            ex.printStackTrace();
            connected_ = false;
            return null;
        }catch (IOException ex){
            connected_ = false;
            ex.printStackTrace();
            
        }
        return null;
    }
    
    /**
     * Returns the created input (local) port when an outgoing connection was established.
     *
     * @return Incoming port
     */
    public int getInputPort() {return inPort_;}
    
    /**
     * Returns the connection outgoing port passed in the constructor.
     *
     * @return Outgoing port
     */
    public int getOutputPort() {return outPort_;}
    
    /**
     * Returns true if the connection is established, false otherwise.
     */
    public boolean isConnected() {return connected_;}
    
    /**
     * Sets a new url to connect to
     * @param u the url String
     */
    public void setURL(String u) {this.url_ = u;}
    
    /**
     * Sets tne new port to connect to
     * @param p the port int number
     */
    public void setPort(int p) {this.outPort_ = p;}
}

// #sijapp cond.end #
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.