public synchronized String getJSValue(String expression) {
   // Don't try to evaluate js code again if the binding has already been destroyed
   if (!destroyed) {
     // see if this is an expression or a statement block
     // Match ; followed by 0 or even quotes
     Pattern pattern = Pattern.compile(";(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
     Matcher matcher = pattern.matcher(expression);
     if (matcher.find()) {
       String lastStmt = expression.substring(matcher.end(matcher.groupCount() - 1));
       String stmtBlock = expression.substring(0, matcher.end(matcher.groupCount() - 1));
       expression = stmtBlock + " return " + lastStmt;
     } else {
       expression = " return " + expression;
     }
     String code =
         "_TiReturn.setValue((function(){try{"
             + expression
             + "+\"\";}catch(ti_eval_err){return '';}})());";
     Log.d(TAG, "getJSValue:" + code, Log.DEBUG_MODE);
     returnSemaphore.drainPermits();
     synchronized (codeSnippets) {
       codeSnippets.push(code);
     }
     try {
       if (!returnSemaphore.tryAcquire(3500, TimeUnit.MILLISECONDS)) {
         synchronized (codeSnippets) {
           codeSnippets.removeElement(code);
         }
         Log.w(TAG, "Timeout waiting to evaluate JS");
       }
       return returnValue;
     } catch (InterruptedException e) {
       Log.e(TAG, "Interrupted", e);
     }
   }
   return null;
 }
 public synchronized void free(Connection connection) {
   busyConnections.removeElement(connection);
   availableConnections.addElement(connection);
   // Wake up threads that are waiting for a connection
   notifyAll();
 }