@Override
 public IFile createFile(String path) {
   File file = new File(context.absPath(path));
   String name = file.getName();
   String parentPath = file.getParent();
   try {
     VfsUtil.createDirectories(parentPath);
   } catch (IOException e) {
     Flog.error("Create directories error %s", e);
     context.errorMessage("The Floobits plugin was unable to create directories for file.");
     return null;
   }
   VirtualFile parent = LocalFileSystem.getInstance().findFileByPath(parentPath);
   if (parent == null) {
     Flog.error("Virtual file is null? %s", parentPath);
     return null;
   }
   VirtualFile newFile;
   try {
     newFile = parent.findOrCreateChildData(context, name);
   } catch (Throwable e) {
     Flog.error("Create file error %s", e);
     context.errorMessage(
         String.format("The Floobits plugin was unable to create a file: %s.", path));
     return null;
   }
   return new FileImpl(newFile);
 }
 public void write(Serializable obj) {
   // TODO: threading issue. lock channel
   if (channel == null) {
     Flog.error("not writing because no channel");
     return;
   }
   String data = new Gson().toJson(obj);
   if (channel == null) {
     Flog.error("Lost connection? Not writing because no channel. Also, race condition!");
     return;
   }
   channel.writeAndFlush(data + "\n");
 }
 public void shutdown() {
   retries = -1;
   if (channel != null) {
     try {
       channel.disconnect();
       channel.close();
     } catch (Throwable e) {
       Flog.error(e);
     }
     channel = null;
   }
 }
  protected void connect() {
    if (retries <= 0) {
      Flog.error("I give up connecting.");
      return;
    }
    retries -= 1;
    FlooUrl flooUrl = handler.getUrl();
    final String host;
    final int port;

    if (flooUrl.host.equals(Constants.floobitsDomain) && retries % 4 == 0) {
      host = Constants.OUTBOUND_FILTER_PROXY_HOST;
      port = Constants.OUTBOUND_FILTER_PROXY_PORT;
    } else {
      host = flooUrl.host;
      port = flooUrl.port;
    }

    if (channel == null) {
      _connect(host, port);
      return;
    }
    try {
      channel
          .close()
          .addListener(
              new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                  channel = null;
                  _connect(host, port);
                }
              });
    } catch (Throwable e) {
      Flog.error(e);
      reconnect();
    }
  }
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   if (retries < 0) {
     return;
   }
   if (cause instanceof ConnectException) {
     Flog.error("Failed to connect: " + cause.getMessage());
     return;
   }
   if (cause instanceof IOException) {
     Flog.error(cause);
     return;
   }
   if (cause instanceof TooLongFrameException) {
     Flog.error(String.format("Took too long: %s", cause.getMessage()));
     return;
   }
   //        if (cause instanceof SSLHandshakeException) {
   //            Flog.error(String.format("SSL Handshake failed: %s", cause.getMessage()));
   //            return;
   //        }
   API.uploadCrash(handler, context, cause);
 }
  @Override
  public IFile createDirectories(String path) {
    VirtualFile directory = null;
    try {
      directory = VfsUtil.createDirectories(path);
    } catch (IOException e) {
      Flog.error(e);
    }

    if (directory == null) {
      Flog.warn("Failed to create directories %s %s", path);
      return null;
    }
    return new FileImpl(directory);
  }
 @Override
 public IDoc getDocument(IFile virtualFile) {
   if (virtualFile == null) {
     return null;
   }
   Document document;
   try {
     document =
         FileDocumentManager.getInstance().getDocument(((FileImpl) virtualFile).virtualFile);
   } catch (RuntimeException e) {
     // We've seen an java.io.EOFException here before.
     Flog.error(e);
     return null;
   }
   if (document == null) {
     return null;
   }
   return new DocImpl(context, document);
 }
  protected void _connect(String host, int port) {
    Bootstrap b = new Bootstrap();

    if (!context.addGroup(b)) {
      Flog.warn("no loopgroup, will not reconnect");
      return;
    }
    b.channel(NioSocketChannel.class);
    b.option(ChannelOption.SO_KEEPALIVE, true);
    b.option(ChannelOption.TCP_NODELAY, true);
    b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15 * 1000);
    b.handler(new FlooChannelInitializer(this));

    try {
      ChannelFuture connect = b.connect(host, port);
      channel = connect.channel();
    } catch (RejectedExecutionException e) {
      context.errorMessage("Can not connect to floobits!");
      context.shutdown();
    } catch (Throwable e) {
      Flog.error(e);
      reconnect();
    }
  }
 @Override
 public void on_connect() {
   Flog.error("Connected.");
   conn.setRetries(-1);
   conn.write(new NewAccount());
 }