@Override
    public void channelRead0(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) {
      final CmdlineRemoteProto.Message.Type type = message.getType();
      final Channel channel = context.channel();

      if (type == CmdlineRemoteProto.Message.Type.CONTROLLER_MESSAGE) {
        final CmdlineRemoteProto.Message.ControllerMessage controllerMessage = message.getControllerMessage();
        switch (controllerMessage.getType()) {

          case BUILD_PARAMETERS: {
            if (mySession == null) {
              final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null;
              final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta, ourPreloadedData);
              mySession = session;
              SharedThreadPool.getInstance().execute(() -> {
                //noinspection finally
                try {
                  try {
                    session.run();
                  }
                  finally {
                    channel.close();
                  }
                }
                finally {
                  System.exit(0);
                }
              });
            }
            else {
              LOG.info("Cannot start another build session because one is already running");
            }
            return;
          }

          case FS_EVENT: {
            final BuildSession session = mySession;
            if (session != null) {
              session.processFSEvent(controllerMessage.getFsEvent());
            }
            return;
          }
          case CONSTANT_SEARCH_RESULT: {
            // ignored, functionality deprecated
            return;
          }

          case CANCEL_BUILD_COMMAND: {
            final BuildSession session = mySession;
            if (session != null) {
              session.cancel();
            }
            else {
              LOG.info("Build canceled, but no build session is running. Exiting.");
              try {
                final CmdlineRemoteProto.Message.BuilderMessage canceledEvent = CmdlineProtoUtil
                  .createBuildCompletedEvent("build completed", CmdlineRemoteProto.Message.BuilderMessage.BuildEvent.Status.CANCELED);
                channel.writeAndFlush(CmdlineProtoUtil.toMessage(mySessionId, canceledEvent)).await();
                channel.close();
              }
              catch (Throwable e) {
                LOG.info(e);
              }
              Thread.interrupted(); // to clear the 'interrupted' flag
              final PreloadedData preloaded = ourPreloadedData;
              final ProjectDescriptor pd = preloaded != null? preloaded.getProjectDescriptor() : null;
              if (pd != null) {
                pd.release();
              }

              JpsServiceManager.getInstance().getExtensions(PreloadedDataExtension.class).forEach(ext-> ext.discardPreloadedData(preloaded));

              System.exit(0);
            }
            return;
          }
        }
      }

      channel.writeAndFlush(
        CmdlineProtoUtil.toMessage(mySessionId,
                                   CmdlineProtoUtil.createFailure(JpsBuildBundle.message("build.message.unsupported.message.type.0", type.name()), null)));
    }
@Override
    public void channelRead0(final ChannelHandlerContext context, CmdlineRemoteProto.Message message)