Hubiquitus Android  0.3
Android client for hubiquitus protocol
HClient.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) Novedia Group 2012.
00003  *
00004  *     This file is part of Hubiquitus.
00005  *
00006  *     Hubiquitus is free software: you can redistribute it and/or modify
00007  *     it under the terms of the GNU General Public License as published by
00008  *     the Free Software Foundation, either version 3 of the License, or
00009  *     (at your option) any later version.
00010  *
00011  *     Hubiquitus is distributed in the hope that it will be useful,
00012  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *     GNU General Public License for more details.
00015  *
00016  *     You should have received a copy of the GNU General Public License
00017  *     along with Hubiquitus.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 package org.hubiquitus.hapi.client;
00021 
00022 import java.util.Hashtable;
00023 import java.util.Random;
00024 
00025 import org.hubiquitus.hapi.hStructures.ConnectionError;
00026 import org.hubiquitus.hapi.hStructures.ConnectionStatus;
00027 import org.hubiquitus.hapi.hStructures.HAck;
00028 import org.hubiquitus.hapi.hStructures.HAckValue;
00029 import org.hubiquitus.hapi.hStructures.HAlert;
00030 import org.hubiquitus.hapi.hStructures.HCommand;
00031 import org.hubiquitus.hapi.hStructures.HConvState;
00032 import org.hubiquitus.hapi.hStructures.HJsonObj;
00033 import org.hubiquitus.hapi.hStructures.HMeasure;
00034 import org.hubiquitus.hapi.hStructures.HMessage;
00035 import org.hubiquitus.hapi.hStructures.HMessageOptions;
00036 import org.hubiquitus.hapi.hStructures.HOptions;
00037 import org.hubiquitus.hapi.hStructures.HResult;
00038 import org.hubiquitus.hapi.hStructures.HStatus;
00039 import org.hubiquitus.hapi.hStructures.ResultStatus;
00040 import org.hubiquitus.hapi.structures.JabberID;
00041 import org.hubiquitus.hapi.transport.HTransport;
00042 import org.hubiquitus.hapi.transport.HTransportDelegate;
00043 import org.hubiquitus.hapi.transport.HTransportOptions;
00044 import org.hubiquitus.hapi.transport.socketio.HTransportSocketio;
00045 import org.hubiquitus.hapi.transport.xmpp.HTransportXMPP;
00046 import org.hubiquitus.hapi.util.HJsonDictionnary;
00047 import org.hubiquitus.hapi.util.HUtil;
00048 import org.json.JSONObject;
00049 
00050 import exceptions.MissingAttrException;
00051 
00052 
00058 public class HClient {
00059          
00060          private ConnectionStatus connectionStatus = ConnectionStatus.DISCONNECTED; /* only connecting, connected, diconnecting, disconnected */
00061          @SuppressWarnings("unused")
00062          private HOptions options = null;
00063          private HTransportOptions transportOptions = null;
00064          private HTransport transport;
00065          
00066          private HStatusDelegate statusDelegate = null;
00067          private HMessageDelegate messageDelegate = null;
00068          private Hashtable<String, HCommandDelegate> commandsDelegates = new Hashtable<String, HCommandDelegate>();
00069          
00070          private TransportDelegate transportDelegate= new TransportDelegate();
00071          
00072          public HClient() {
00073                   transportOptions = new HTransportOptions();
00074          }
00075 
00083          public void connect(String publisher, String password, HOptions options) {
00084                   boolean shouldConnect = false;
00085                   boolean connInProgress = false;
00086                   boolean disconInProgress = false;
00087 
00088                   //synchronize connection status updates to make sure, we have one connect at a time
00089                   synchronized (this) {
00090                            if (this.connectionStatus == ConnectionStatus.DISCONNECTED) {
00091                                     shouldConnect = true;
00092                                     
00093                                     //update connection status
00094                                     connectionStatus = ConnectionStatus.CONNECTING;
00095                            } else if(this.connectionStatus == ConnectionStatus.CONNECTING) {
00096                                     connInProgress = true;
00097                            } else if(this.connectionStatus == ConnectionStatus.DISCONNECTING) {
00098                                     disconInProgress = true;
00099                            }
00100                   }
00101                   
00102                   if (shouldConnect) { //if not connected, then connect
00103                            
00104                            //notify connection
00105                            this.notifyStatus(ConnectionStatus.CONNECTING, ConnectionError.NO_ERROR, null);
00106                            
00107                            //fill HTransportOptions
00108                            try {
00109                                     this.fillHTransportOptions(publisher, password, options);
00110                            } catch (Exception e) { 
00111                                     //stop connecting if filling error
00112                                     this.notifyStatus(ConnectionStatus.DISCONNECTED, ConnectionError.JID_MALFORMAT, e.getMessage());
00113                                     return;
00114                            }
00115                            
00116                            //choose transport layer
00117                            if(options.getTransport().equals("socketio")) {
00118                                     /*if (this.transport != null) { //check if other transport mode connect
00119                                              this.transport.disconnect();
00120                                     }*/
00121                                     if (this.transport == null || (this.transport.getClass() != HTransportSocketio.class)) {
00122                                              this.transport = new HTransportSocketio();
00123                                     }
00124                                     this.transport.connect(transportDelegate, this.transportOptions);
00125                            } else {
00126                                     /*if (this.transport != null) { //check if other transport mode connect
00127                                              this.transport.disconnect();
00128                                     }*/
00129                                     this.transport = new HTransportXMPP();
00130                                     this.transport.connect(transportDelegate, this.transportOptions);
00131                            }
00132                   } else {
00133                            if (connInProgress) {
00134                                     notifyStatus(ConnectionStatus.CONNECTING, ConnectionError.CONN_PROGRESS, null);
00135                            } else if (disconInProgress) {
00136                                     //updateStatus(ConnectionStatus.DISCONNECTING, ConnectionError.ALREADY_CONNECTED, null);
00137                            } else {
00138                                     notifyStatus(ConnectionStatus.CONNECTED, ConnectionError.ALREADY_CONNECTED, null);
00139                            }        
00140                   }
00141          }
00142 
00143          public void disconnect() {
00144                   boolean shouldDisconnect = false;
00145                   boolean connectInProgress = false;
00146                   synchronized (this) {
00147                            if (this.connectionStatus == ConnectionStatus.CONNECTED) {
00148                                     shouldDisconnect = true;
00149                                     //update connection status
00150                                     connectionStatus = ConnectionStatus.DISCONNECTING;
00151                            } else if(this.connectionStatus == ConnectionStatus.CONNECTING) {
00152                                     connectInProgress = true;
00153                            }
00154                   }
00155                   
00156                   if(shouldDisconnect) {
00157                            notifyStatus(ConnectionStatus.DISCONNECTING, ConnectionError.NO_ERROR, null);
00158                            transport.disconnect();
00159                   } else if (connectInProgress) {
00160                            notifyStatus(ConnectionStatus.CONNECTING, ConnectionError.CONN_PROGRESS, "Can't disconnect while a connection is in progress");
00161                   } else {
00162                            notifyStatus(ConnectionStatus.DISCONNECTED, ConnectionError.NOT_CONNECTED, null);
00163                   }
00164                   
00165                   
00166          }
00167          
00172          public void onStatus(HStatusDelegate statusDelgate) {
00173                   this.statusDelegate = statusDelgate;
00174          }
00175          
00180          public void onMessage(HMessageDelegate messageDelegate) {
00181                   this.messageDelegate = messageDelegate;
00182          }
00183          
00188          public ConnectionStatus status() {
00189                   return this.connectionStatus;
00190          }
00191          
00198          public void command(HCommand cmd, HCommandDelegate commandDelegate) {
00199                   if(this.connectionStatus == ConnectionStatus.CONNECTED && cmd != null) {
00200                            String reqid = null;
00201                            reqid = cmd.getReqid();
00202                            if(reqid == null) {
00203                                     Random rand = new Random();
00204                                     reqid = "javaCmd:" + rand.nextInt();
00205                                     cmd.setReqid(reqid);
00206                            }
00207                            
00208                            if(cmd.getSender() == null) {
00209                                     cmd.setSender(transportOptions.getJid().getFullJID());
00210                            }
00211                            
00212                            if(cmd.getTransient() == null) {
00213                                     cmd.setTransient(true);
00214                            }
00215                            
00216                            if(cmd.getEntity() != null) {
00217                                     if (commandDelegate != null) {
00218                                              commandsDelegates.put(reqid, commandDelegate);
00219                                     }
00220                                     transport.sendObject(cmd.toJSON());
00221                            } else {
00222                                     this.notifyResultError(cmd.getReqid(), cmd.getCmd(), ResultStatus.MISSING_ATTR, "Entity not found");
00223                            }
00224                   } else if (cmd == null) {
00225                            this.notifyResultError(null, null, ResultStatus.MISSING_ATTR, "Provided cmd is null", commandDelegate);
00226                   } else {
00227                            this.notifyResultError(cmd.getReqid(), cmd.getCmd(), ResultStatus.NOT_CONNECTED, null, commandDelegate);
00228                   }
00229          }
00230          
00239          public void subscribe(String chid, HCommandDelegate commandDelegate) {
00240                   HJsonDictionnary params = new HJsonDictionnary();
00241                   params.put("chid", chid);
00242                   HCommand cmd = new HCommand(transportOptions.getHserverService(), "hsubscribe", params);
00243                   this.command(cmd, commandDelegate);
00244          }
00245          
00253          public void unsubscribe(String chid, HCommandDelegate commandDelegate) {
00254                   HJsonDictionnary params = new HJsonDictionnary();
00255                   params.put("chid", chid);
00256                   HCommand cmd = new HCommand(transportOptions.getHserverService(), "hunsubscribe", params);
00257                   this.command(cmd, commandDelegate);
00258          }
00259          
00266          public void publish(HMessage message, HCommandDelegate commandDelegate) {
00267                   //fill mandatory fields
00268                   String msgid = message.getMsgid();
00269                   if(msgid == null) {
00270                            Random rand = new Random();
00271                            msgid = "javaCmd:" + rand.nextInt();
00272                            message.setMsgid(msgid);
00273                   }
00274                   
00275                   String convid = message.getConvid();
00276                   if(convid == null) {
00277                            message.setConvid(msgid);
00278                   }
00279                                     
00280                   message.setConvid(convid);
00281                   
00282                   if(message.getPublisher() == null) {
00283                            message.setPublisher(this.transportOptions.getJid().getBareJID());
00284                   }
00285                   
00286                   HCommand cmd = new HCommand(transportOptions.getHserverService(), "hpublish", message);
00287                   this.command(cmd, commandDelegate);                            
00288          }
00302          public void getLastMessages(String chid, int nbLastMsg, HCommandDelegate commandDelegate) {
00303                   HJsonDictionnary params = new HJsonDictionnary();
00304                   params.put("chid", chid);
00305                   if(nbLastMsg > 0) {
00306                            params.put("nbLastMsg", nbLastMsg);
00307                   }
00308                   HCommand cmd = new HCommand(transportOptions.getHserverService(), "hgetlastmessages", params);
00309                   this.command(cmd, commandDelegate);
00310          }
00311          
00318          public void getLastMessages(String chid, HCommandDelegate commandDelegate) {
00319                   this.getLastMessages(chid,-1, commandDelegate);
00320          }
00321          
00329          public void getSubscriptions(HCommandDelegate commandDelegate) {
00330                   HCommand cmd = new HCommand(transportOptions.getHserverService(), "hgetsubscriptions", null);
00331                   this.command(cmd, commandDelegate);
00332          }
00333          
00342          public void getThread(String chid, String convid, HCommandDelegate commandDelegate) {
00343                   HJsonDictionnary params = new HJsonDictionnary();
00344                   String cmdName = "hgetthread";
00345                   
00346                   //check mandatory fields
00347                   if (chid == null || chid.length() <= 0) {
00348                            notifyResultError(null, cmdName, ResultStatus.MISSING_ATTR, "Chid is missing", commandDelegate);
00349                            return;
00350                   }
00351                   
00352                   if (convid == null || convid.length() <= 0) {
00353                            notifyResultError(null, cmdName, ResultStatus.MISSING_ATTR, "Convid is missing", commandDelegate);
00354                            return;
00355                   }
00356                   
00357                   params.put("chid", chid);
00358                   params.put("convid", convid);
00359                   
00360                   HCommand cmd = new HCommand(transportOptions.getHserverService(), cmdName, params);
00361                   this.command(cmd, commandDelegate);
00362          }
00363          
00372          public void getThreads(String chid, String status, HCommandDelegate commandDelegate) {
00373                   HJsonDictionnary params = new HJsonDictionnary();
00374                   String cmdName = "hgetthreads";
00375                   
00376                   //check mandatory fields
00377                   if (chid == null || chid.length() <= 0) {
00378                            notifyResultError(null, cmdName, ResultStatus.MISSING_ATTR, "Chid is missing", commandDelegate);
00379                            return;
00380                   }
00381                   
00382                   if (status == null || status.length() <= 0) {
00383                            notifyResultError(null, cmdName, ResultStatus.MISSING_ATTR, "Status is missing", commandDelegate);
00384                            return;
00385                   }
00386                   
00387                   params.put("chid", chid);
00388                   params.put("status", status);
00389                   
00390                   HCommand cmd = new HCommand(transportOptions.getHserverService(), cmdName, params);
00391                   this.command(cmd, commandDelegate);
00392          }
00393          
00394          /* Builder */
00395          
00406          public HMessage buildMessage(String chid, String type, HJsonObj payload, HMessageOptions options) throws MissingAttrException {
00407                   
00408                   //check for required attributes
00409                   if (chid == null || chid.length() <= 0) {
00410                            throw new MissingAttrException("chid");
00411                   }
00412                   
00413                   //build the message
00414                   HMessage hmessage = new HMessage();
00415 
00416                   hmessage.setChid(chid);
00417                   hmessage.setType(type);
00418                   if(options != null) {
00419                            hmessage.setConvid(options.getConvid());
00420                            hmessage.setPriority(options.getPriority());
00421                            hmessage.setRelevance(options.getRelevance());
00422                            hmessage.setTransient(options.getTransient());
00423                            hmessage.setLocation(options.getLocation());
00424                            hmessage.setAuthor(options.getAuthor());
00425                            hmessage.setHeaders(options.getHeaders());
00426                   }                                   
00427                            
00428                   if(transportOptions != null && transportOptions.getJid() != null) {
00429                            hmessage.setPublisher(transportOptions.getJid().getBareJID());
00430                   } else {
00431                            hmessage.setPublisher(null);
00432                   }                 
00433                                     
00434                   hmessage.setPayload(payload);
00435 
00436                   return hmessage;
00437          }
00438          
00448          public HMessage buildConvState(String chid, String convid, String status, HMessageOptions options) throws MissingAttrException {
00449                   
00450                   //check for required attributes
00451                   if (chid == null || chid.length() <= 0) {
00452                            throw new MissingAttrException("chid");
00453                   }
00454                   
00455                   if (convid == null || convid.length() <= 0) {
00456                            throw new MissingAttrException("convid");
00457                   }
00458                   
00459                   if (status == null || status.length() <= 0) {
00460                            throw new MissingAttrException("status");
00461                   }
00462                   
00463                   HMessage hmessage = new HMessage();
00464                   
00465                   HConvState hconvstate = new HConvState();
00466                   hconvstate.setStatus(status);
00467                   
00468                   hmessage = buildMessage(chid, "hConvState", hconvstate, options);
00469                   hmessage.setConvid(convid);
00470 
00471                   return hmessage;
00472          }
00473          
00483          public HMessage buildAck(String chid, String ackid,HAckValue ack, HMessageOptions options) throws MissingAttrException {
00484                   //check for required attributes
00485                   if (chid == null || chid.length() <= 0) {
00486                            throw new MissingAttrException("chid");
00487                   }
00488                   
00489                   //check for required attributes
00490                   if (ackid == null || ackid.length() <= 0) {
00491                            throw new MissingAttrException("ackid");
00492                   }
00493                   
00494                   //check for required attributes
00495                   if (ack == null) {
00496                            throw new MissingAttrException("ack");
00497                   }
00498                   
00499                   HMessage hmessage = new HMessage();
00500 
00501                   HAck hack = new HAck();
00502                   hack.setAckid(ackid);
00503                   hack.setAck(ack);
00504                   hmessage = buildMessage(chid, "hAck", hack, options);
00505 
00506                   return hmessage;
00507          }
00508          
00517          public HMessage buildAlert(String chid, String alert, HMessageOptions options) throws MissingAttrException {
00518                   //check for required attributes
00519                   if (chid == null || chid.length() <= 0) {
00520                            throw new MissingAttrException("chid");
00521                   }
00522                   
00523                   //check for required attributes
00524                   if (alert == null || alert.length() <= 0) {
00525                            throw new MissingAttrException("chid");
00526                   }
00527                   
00528                   HMessage hmessage = new HMessage();
00529                   
00530                   HAlert halert = new HAlert();
00531                   halert.setAlert(alert);
00532                   
00533                   hmessage = buildMessage(chid, "hAlert", halert, options);
00534          
00535                   return hmessage;
00536          }
00537          
00547          public HMessage buildMeasure(String chid, String value, String unit, HMessageOptions options) throws MissingAttrException {
00548                   //check for required attributes
00549                   if (chid == null || chid.length() <= 0) {
00550                            throw new MissingAttrException("chid");
00551                   }
00552                                     
00553                   //check for required attributes
00554                   if (value == null || value.length() <= 0) {
00555                            throw new MissingAttrException("value");
00556                   }
00557                                     
00558                   //check for required attributes
00559                   if (unit == null || unit.length() <= 0) {
00560                            throw new MissingAttrException("unit");
00561                   }
00562                   
00563                   HMessage hmessage = new HMessage();
00564                   
00565                   HMeasure hmeasure = new HMeasure();
00566                   hmeasure.setValue(value);
00567                   hmeasure.setUnit(unit);
00568                   hmessage = buildMessage(chid, "hMeasure", hmeasure, options);
00569          
00570                   return hmessage;
00571          }
00572          /* HTransportCallback functions */
00573 
00583          private void fillHTransportOptions(String publisher, String password, HOptions options) throws Exception {
00584                   JabberID jid = new JabberID(publisher);
00585                   
00586                   this.transportOptions.setJid(jid);
00587                   this.transportOptions.setPassword(password);
00588                   this.transportOptions.setHserver(options.getHserver());
00589                   
00590                   //by default we user server host rather than publish host if defined
00591                   if (options.getServerHost() != null ) {
00592                            this.transportOptions.setServerHost(options.getServerHost());
00593                   } else { 
00594                            this.transportOptions.setServerHost(jid.getDomain());
00595                   }
00596                   
00597                   this.transportOptions.setServerPort(options.getServerPort());
00598                   //for endpoints, pick one randomly and fill htransport options
00599                   if (options.getEndpoints().size() > 0) {
00600                            int endpointIndex = HUtil.pickIndex(options.getEndpoints()); 
00601                            String endpoint = options.getEndpoints().get(endpointIndex);
00602                            
00603                            this.transportOptions.setEndpointHost(HUtil.getHost(endpoint));
00604                            this.transportOptions.setEndpointPort(HUtil.getPort(endpoint));
00605                            this.transportOptions.setEndpointPath(HUtil.getPath(endpoint));
00606                   } else {
00607                            this.transportOptions.setEndpointHost(null);
00608                            this.transportOptions.setEndpointPort(0);
00609                            this.transportOptions.setEndpointPath(null);
00610                   }
00611          }
00612          
00620          private void notifyStatus(ConnectionStatus status, ConnectionError error, String errorMsg) {
00621                   try {
00622                            if (this.statusDelegate != null) {
00623                                     connectionStatus = status;
00624                                     
00625                                     //create structure 
00626                                     final HStatus hstatus = new HStatus();
00627                                     hstatus.setStatus(status);
00628                                     hstatus.setErrorCode(error);
00629                                     hstatus.setErrorMsg(errorMsg);
00630                                     
00631                                     //return status asynchronously
00632                                     (new Thread(new Runnable() {
00633                                              public void run() {
00634                                                       try {
00635                                                                statusDelegate.onStatus(hstatus);
00636                                                       } catch (Exception e) {
00637                                                                // TODO: Add a message to message logger
00638                                                                e.printStackTrace();
00639                                                       }
00640                                              }
00641                                     })).start();
00642                            }
00643                   } catch (Exception e) {
00644                            e.printStackTrace();
00645                            // TODO: Add a message to message logger
00646                   }
00647          }
00648          
00653          private void notifyMessage(final HMessage message) {
00654                   try {
00655                            if (this.messageDelegate != null) {
00656                                     
00657                                     //return message asynchronously
00658                                     (new Thread(new Runnable() {
00659                                              public void run() {
00660                                                       try {
00661                                                                messageDelegate.onMessage(message);
00662                                                       } catch (Exception e) {
00663                                                                // TODO: Add a message to message logger
00664                                                                e.printStackTrace();
00665                                                       }
00666                                              }
00667                                     })).start();
00668                            }
00669                   } catch (Exception e) {
00670                            e.printStackTrace();
00671                            // TODO: Add a message to message logger
00672                   }
00673          }
00674          
00679          private void notifyResult(final HResult result, final HCommandDelegate commandDelegate) {
00680                   try {
00681                            if (commandDelegate != null) {
00682                                     
00683                                     //return result asynchronously
00684                                     (new Thread(new Runnable() {
00685                                              public void run() {
00686                                                       try {
00687                                                                commandDelegate.onResult(result);
00688                                                       } catch (Exception e) {
00689                                                                // TODO: Add a message to message logger
00690                                                                e.printStackTrace();
00691                                                       }
00692                                              }
00693                                     })).start();
00694                            } else {
00695                                     // TODO: add a message to logger in debug mode to know which results are dropped
00696                            }
00697                   } catch (Exception e) {
00698                            e.printStackTrace();
00699                            // TODO: Add a message to message logger
00700                   }
00701          }
00702          
00709          private void notifyResult(final HResult result) {
00710                   HCommandDelegate commandDelegate = commandsDelegates.get(result.getReqid());
00711                   notifyResult(result, commandDelegate);
00712          }
00713          
00719          private void notifyResultError(String reqid, String cmd, ResultStatus resultstatus, String errorMsg) {
00720                   HJsonDictionnary obj = new HJsonDictionnary(); 
00721                   obj.put("errorMsg", errorMsg);
00722                   HResult hresult = new HResult();
00723                   hresult.setResult(obj);
00724                   hresult.setStatus(resultstatus);
00725                   
00726                   hresult.setReqid(reqid);
00727                   hresult.setCmd(cmd);
00728                   
00729                   this.notifyResult(hresult);
00730          }
00731          
00737          private void notifyResultError(String reqid, String cmd, ResultStatus resultstatus, String errorMsg, HCommandDelegate commandDelegate) {
00738                   HJsonDictionnary obj = new HJsonDictionnary(); 
00739                   obj.put("errorMsg", errorMsg);
00740                   HResult hresult = new HResult();
00741                   hresult.setResult(obj);
00742                   hresult.setStatus(resultstatus);
00743                   
00744                   hresult.setReqid(reqid);
00745                   hresult.setCmd(cmd);
00746                   
00747                   this.notifyResult(hresult, commandDelegate);
00748          }
00749          
00750 
00755          private class TransportDelegate implements HTransportDelegate {
00756 
00761                   public void onStatus(ConnectionStatus status, ConnectionError error, String errorMsg) {
00762                            notifyStatus(status, error, errorMsg);
00763                   }
00764 
00769                   public void onData(String type, JSONObject jsonData) {
00770                            try {
00771                                     if(type.equalsIgnoreCase("hresult")) {
00772                                              notifyResult(new HResult(jsonData));
00773                                     } else if (type.equalsIgnoreCase("hmessage")) {
00774                                              notifyMessage(new HMessage(jsonData));
00775                                     }
00776                            } catch (Exception e) {
00777                                     System.out.println("erreur datacallBack");
00778                            }
00779                   }
00780          }
00781 
00782          
00783 }
 All Classes Namespaces Files Functions Variables