public void connect(String token) {
   if (!Preconditions.checkNotNull(token, "Null token").equals(currentToken)) {
     log.log(Level.INFO, "Connecting with token ", token);
     currentToken = token;
     connectNative(token);
   } else {
     log.log(Level.DEBUG, "Already using same token, ignoring ", token);
   }
 }
 @SuppressWarnings("unused") // called by native code
 private void onMessage(String data) {
   log.log(Level.DEBUG, "onMessage data=", data);
   if (data == null) {
     log.log(Level.WARNING, "Null data on channel");
     return;
   }
   try {
     JsoView jso = JsUtil.eval(data);
     if (!jso.containsKey("id") || !jso.containsKey("m")) {
       throw new MessageException("Missing fields");
     }
     String id = jso.getString("id");
     JsoView m = jso.getJsoView("m");
     GaeChannel channel = channels.get(id);
     if (channel == null) {
       log.log(Level.WARNING, "No channel registered for object with id ", id);
       return;
     }
     channel.onMessage(m);
   } catch (MessageException e) {
     log.log(Level.WARNING, "Bad data on channel ", data, " ", e);
   }
 }
 @SuppressWarnings("unused") // called by native code
 private void onClose() {
   log.log(Level.DEBUG, "onClose ");
 }
 @SuppressWarnings("unused") // called by native code
 private void onError(int httpCode, String description) {
   log.log(Level.WARNING, "onError code=", httpCode, " description=", description);
 }