code: package com.github.sulir.runtimesearch.plugin;
  
  import com.github.sulir.runtimesearch.plugin.breakpoint.RuntimeBreakpointType;
  import com.github.sulir.runtimesearch.plugin.config.RuntimeSearchSettings;
  import com.github.sulir.runtimesearch.shared.SearchOptions;
  import com.intellij.execution.Executor;
  import com.intellij.execution.ProgramRunnerUtil;
  import com.intellij.execution.RunManager;
  import com.intellij.execution.RunnerAndConfigurationSettings;
  import com.intellij.execution.configurations.RunConfigurationBase;
  import com.intellij.execution.configurations.RunProfile;
  import com.intellij.execution.executors.DefaultDebugExecutor;
  import com.intellij.execution.impl.EditConfigurationsDialog;
  import com.intellij.notification.Notification;
  import com.intellij.notification.NotificationType;
  import com.intellij.notification.Notifications;
  import com.intellij.openapi.actionSystem.AnAction;
  import com.intellij.openapi.actionSystem.AnActionEvent;
  import com.intellij.openapi.project.Project;
  import com.intellij.xdebugger.XDebugSession;
  import com.intellij.xdebugger.XDebuggerManager;
  import com.intellij.xdebugger.XDebuggerUtil;
  import com.intellij.xdebugger.breakpoints.XBreakpoint;
  import com.intellij.xdebugger.breakpoints.XBreakpointManager;
  import org.jetbrains.annotations.NotNull;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ObjectOutputStream;
  import java.net.InetAddress;
  import java.net.Socket;
  
  public class RuntimeFindManager {
      private static final String NOTIFICATION_GROUP = "RuntimeSearch";
  
      private final Project project;
      private RuntimeFindForm form;
      private final SearchOptions options = new SearchOptions();
  
      public static RuntimeFindManager getInstance(Project project) {
          return project.getService(RuntimeFindManager.class);
      }
  
      public RuntimeFindManager(Project project) {
          this.project = project;
      }
  
      public void showForm() {
          if (form == null)
              form = new RuntimeFindForm(project);
  
          form.show();
      }
  
      public void findNext() {
          if (options.getText().isEmpty()) {
              showForm();
          } else {
              enableBreakpoint();
              XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
  
              if (session == null) {
                  startDebugging();
              } else {
                  sendSearchText(session);
                  if (session.isPaused())
                      session.resume();
              }
          }
      }
  
      public SearchOptions getOptions() {
          return options;
      }
  
      public void startDebugging() {
          RunnerAndConfigurationSettings selected = RunManager.getInstance(project).getSelectedConfiguration();
          if (selected == null || !(selected.getConfiguration() instanceof RunConfigurationBase)) {
              Notifications.Bus.notify(new Notification(NOTIFICATION_GROUP, Messages.get("error.no.config.title"),
                      Messages.get("error.no.config.content"), NotificationType.ERROR));
              return;
          }
  
          RunConfigurationBase<?> configuration = (RunConfigurationBase<?>) selected.getConfiguration();
          RuntimeSearchSettings settings = RuntimeSearchSettings.getOrCreate(configuration);
          if (!settings.isEnabled()) {
              offerToEnablePlugin();
              return;
          }
  
          Executor debugExecutor = DefaultDebugExecutor.getDebugExecutorInstance();
          ProgramRunnerUtil.executeConfiguration(selected, debugExecutor);
      }
  
      public void sendSearchText(XDebugSession session) {
          RunProfile runProfile = session.getRunProfile();
          if (!(runProfile instanceof RunConfigurationBase)) {
              offerToEnablePlugin();
              return;
          }
          int port = RuntimeSearchSettings.getOrCreate((RunConfigurationBase<?>) runProfile).getPort();
  
          try (
                  Socket client = new Socket(InetAddress.getLoopbackAddress(), port);
                  ObjectOutputStream output = new ObjectOutputStream(client.getOutputStream());
                  InputStream input = client.getInputStream()
          ) {
              output.writeObject(options);
              @SuppressWarnings("unused") int confirmation = input.read();
          } catch (IOException e) {
              offerToEnablePlugin();
          }
      }
  
      private void enableBreakpoint() {
          RuntimeBreakpointType type = XDebuggerUtil.getInstance().findBreakpointType(RuntimeBreakpointType.class);
          XBreakpointManager manager = XDebuggerManager.getInstance(project).getBreakpointManager();
          XBreakpoint<?> breakpoint = manager.getDefaultBreakpoints(type).iterator().next();
          breakpoint.setEnabled(true);
      }
  
      private void offerToEnablePlugin() {
          Notification notification = new Notification(NOTIFICATION_GROUP, Messages.get("error.disabled.title"),
                  Messages.get("error.disabled.content"), NotificationType.WARNING);
  
          notification.addAction(new AnAction(Messages.get("error.disabled.action")) {
              @Override
              public void actionPerformed(@NotNull AnActionEvent e) {
                  if (form != null)
                      form.hide();
                  new EditConfigurationsDialog(project).show();
                  notification.expire();
              }
          });
  
          notification.notify(project);
      }
  }
  