/**
   * Creates a task that will execute the given command.
   *
   * @param cmd command to schedule
   * @param globalOptions options to use when running the command
   * @param mgr listener for command events
   * @return RequestProcessor.Task a task ready to execute the command
   * @throws IllegalCommandException if the command is not valid, e.g. it contains files that cannot
   *     be processed by a single command (they do not have a common filesystem root OR their CVS
   *     Roots differ)
   */
  public RequestProcessor.Task createTask(
      Command cmd, GlobalOptions globalOptions, final ExecutorSupport mgr)
      throws IllegalCommandException {

    File[] files = getCommandFiles(cmd);
    if ((cmd instanceof CheckoutCommand) == false && !(cmd instanceof RlogCommand)) { // XXX
      ensureValidCommand(files);
    }

    if (globalOptions.getCVSRoot() == null) {
      globalOptions = (GlobalOptions) globalOptions.clone();
      globalOptions.setCVSRoot(cvsRoot);
    }

    Client client = createClient();
    if ((cmd instanceof RlogCommand)) { // XXX
    } else if ((cmd instanceof CheckoutCommand)) { // XXX
      BasicCommand bc = (BasicCommand) cmd;
      if (bc.getFiles() != null) {
        String path = bc.getFiles()[0].getAbsolutePath();
        client.setLocalPath(path);
      } else {
        // #67315: use some default working dir
        client.setLocalPath(System.getProperty("user.dir")); // NOI18N
      }
    } else if (cmd instanceof ImportCommand) {
      client.setLocalPath(((ImportCommand) cmd).getImportDirectory());
    } else {
      setLocalDirectory(client, files);
    }

    client.getEventManager().addCVSListener(mgr);
    final CommandRunnable cr = new CommandRunnable(client, globalOptions, cmd, mgr);
    mgr.commandEnqueued(cr);
    RequestProcessor.Task task = requestProcessor.create(cr);
    task.addTaskListener(
        new TaskListener() {
          public void taskFinished(Task task) {
            try {
              // There are times when 'commandTerminated()' is not the last method called, therefore
              // I introduced
              // this event that really marks the very end of a command (thread end)
              mgr.commandTerminated(new TerminationEvent(new Result(cr)));
            } catch (Throwable e) {
              ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
            } finally {
              flushLog();
            }
          }
        });
    return task;
  }
  /**
   * Sets up connection to a given CVS root including any proxies on route.
   *
   * @param cvsRoot root to connect to
   * @return Connection object ready to connect to the given CVS root
   * @throws IllegalArgumentException if the 'method' part of the supplied CVS Root is not
   *     recognized
   */
  public static Connection setupConnection(CVSRoot cvsRoot) throws IllegalArgumentException {

    // for testing porposes allow to use dynamically generated port numbers
    String t9yRoot = System.getProperty("netbeans.t9y.cvs.connection.CVSROOT"); // NOI18N
    CVSRoot patchedCvsRoot = cvsRoot;
    if (t9yRoot != null && t9yRoot.length() > 0) {
      int idx = t9yRoot.indexOf(',');
      if (idx != -1) {
        System.setProperty(
            "netbeans.t9y.cvs.connection.CVSROOT", t9yRoot.substring(idx + 1)); // NOI18N
        t9yRoot = t9yRoot.substring(0, idx);
      }
      try {
        patchedCvsRoot = CVSRoot.parse(t9yRoot);
        assert patchedCvsRoot.getRepository().equals(cvsRoot.getRepository());
        assert patchedCvsRoot.getHostName() == cvsRoot.getHostName()
            || patchedCvsRoot.getHostName().equals(cvsRoot.getHostName());
        ErrorManager.getDefault()
            .log(
                ErrorManager.INFORMATIONAL,
                "CVS.ClientRuntime: using patched CVSROOT " + t9yRoot); // NOI18N
      } catch (IllegalArgumentException ex) {
        ErrorManager.getDefault().annotate(ex, "While parsing: " + t9yRoot); // NOI18N
        ErrorManager.getDefault().notify(ex);
      }
    }

    if (cvsRoot.isLocal()) {
      LocalConnection con = new LocalConnection();
      con.setRepository(cvsRoot.getRepository());
      return con;
    }

    ProxySocketFactory factory = ProxySocketFactory.getDefault();

    String method = cvsRoot.getMethod();
    if (CVSRoot.METHOD_PSERVER.equals(method)) {
      PServerConnection con = new PServerConnection(patchedCvsRoot, factory);
      char[] passwordChars =
          KeyringSupport.read(CvsModuleConfig.PREFIX_KEYRING_KEY, cvsRoot.toString());
      String password;
      if (passwordChars != null) {
        password = new String(passwordChars);
      } else {
        password = PasswordsFile.findPassword(cvsRoot.toString());
        if (password != null) {
          KeyringSupport.save(
              CvsModuleConfig.PREFIX_KEYRING_KEY, cvsRoot.toString(), password.toCharArray(), null);
        }
      }
      con.setEncodedPassword(password);
      return con;
    } else if (CVSRoot.METHOD_EXT.equals(method)) {
      CvsModuleConfig.ExtSettings extSettings =
          CvsModuleConfig.getDefault().getExtSettingsFor(cvsRoot);
      String userName = cvsRoot.getUserName();
      String host = cvsRoot.getHostName();
      if (extSettings.extUseInternalSsh) {
        int port = patchedCvsRoot.getPort();
        port = port == 0 ? 22 : port; // default port
        String password = new String(extSettings.extPassword);
        if (password == null) {
          password = "******"; // NOI18N    user will be asked later on
        }
        SSHConnection sshConnection = new SSHConnection(factory, host, port, userName, password);
        sshConnection.setRepository(cvsRoot.getRepository());
        return sshConnection;
      } else {
        // What do we want to achieve here?
        // It's possible to mimics ordinary cvs or cvsnt behaviour:
        // Ordinary cvs style (CVS_RSH):
        //   command += " $hostname [-l$username] $CVS_SERVER"
        // cvsnt style (CVS_EXT and CVS_RSH):
        //   command += " cvs server"
        // I prefer the cvs style, see issue #62683 for details.

        String command = extSettings.extCommand;
        String cvs_server = System.getenv("CVS_SERVER");
        cvs_server = cvs_server != null ? cvs_server + " server" : "cvs server"; // NOI18N
        String userOption = ""; // NOI18N
        if (userName != null) {
          userOption = " -l " + userName; // NOI18N
        }
        command += " " + host + userOption + " " + cvs_server; // NOI18N
        ExtConnection connection = new ExtConnection(command);
        connection.setRepository(cvsRoot.getRepository());
        return connection;
      }
    }

    throw new IllegalArgumentException("Unrecognized CVS Root: " + cvsRoot); // NOI18N
  }
Beispiel #3
0
  /**
   * Process all the requests. The connection must have been opened and set first.
   *
   * @param requests the requets to process
   */
  public void processRequests(List requests)
      throws IOException, UnconfiguredRequestException, ResponseException, CommandAbortedException {

    if (requests == null || requests.size() == 0) {
      throw new IllegalArgumentException(
          "[processRequests] requests "
              + // NOI18N
              "was either null or empty."); // NOI18N
    }

    if (abort) {
      throw new CommandAbortedException(
          "Aborted during request processing", // NOI18N
          CommandException.getLocalMessage("Client.commandAborted", null)); // NOI18N
    }

    loggedDataInputStream = null;
    loggedDataOutputStream = null;

    // send the initialisation requests if we are handling the first
    // command
    boolean filterRootRequest = true;
    if (isFirstCommand()) {
      setIsFirstCommand(false);
      int pos = 0;
      if (!initialRequestsSent) {
        pos = fillInitialRequests(requests);
        initialRequestsSent = true;
        filterRootRequest = false;
      }
      if (globalOptions != null) {
        // sends the global options that are to be sent to server (-q, -Q, -t, -n, l)
        for (Iterator it = globalOptions.createRequestList().iterator(); it.hasNext(); ) {
          Request request = (Request) it.next();
          requests.add(pos++, request);
        }

        if (globalOptions.isUseGzip() && globalOptions.getCompressionLevel() != 0) {
          requests.add(pos++, new GzipFileContentsRequest(globalOptions.getCompressionLevel()));
        }
      }
    } else if (printConnectionReuseWarning) {
      if (System.getProperty("javacvs.multiple_commands_warning") == null) { // NOI18N
        System.err.println("WARNING TO DEVELOPERS:"); // NOI18N
        System.err.println(
            "Please be warned that attempting to reuse one open connection for more commands is not supported by cvs servers very well."); // NOI18N
        System.err.println("You are advised to open a new Connection each time."); // NOI18N
        System.err.println(
            "If you still want to proceed, please do: System.setProperty(\"javacvs.multiple_commands_warning\", \"false\")"); // NOI18N
        System.err.println("That will disable this message."); // NOI18N
      }
    }

    if (!ALLOWED_CONNECTION_REUSE_REQUESTS.contains(requests.get(requests.size() - 1).getClass())) {
      printConnectionReuseWarning = true;
    }

    final boolean fireEnhancedEvents = getEventManager().isFireEnhancedEventSet();
    int fileDetailRequestCount = 0;

    if (fireEnhancedEvents) {
      for (Iterator it = requests.iterator(); it.hasNext(); ) {
        Request request = (Request) it.next();

        FileDetails fileDetails = request.getFileForTransmission();
        if (fileDetails != null && fileDetails.getFile().exists()) {
          fileDetailRequestCount++;
        }
      }
      CVSEvent event =
          new EnhancedMessageEvent(
              this, EnhancedMessageEvent.REQUESTS_COUNT, new Integer(fileDetailRequestCount));
      getEventManager().fireCVSEvent(event);
    }

    LoggedDataOutputStream dos = connection.getOutputStream();
    loggedDataOutputStream = dos;

    // this list stores stream modification requests, each to be called
    // to modify the input stream the next time we need to process a
    // response
    List streamModifierRequests = new LinkedList();

    // sending files does not seem to allow compression
    transmitFileHandler = getUncompressedFileHandler();

    for (Iterator it = requests.iterator(); it.hasNext(); ) {
      if (abort) {
        throw new CommandAbortedException(
            "Aborted during request processing", // NOI18N
            CommandException.getLocalMessage("Client.commandAborted", null)); // NOI18N
      }

      final Request request = (Request) it.next();

      if (request instanceof GzipFileContentsRequest) {
        if (dontUseGzipFileHandler) {
          stderr.println(
              "Warning: The server is not supporting gzip-file-contents request, no compression is used.");
          continue;
        }
      }

      // skip the root request if already sent
      if (request instanceof RootRequest) {
        if (filterRootRequest) {
          continue;
        } else { // Even if we should not filter the RootRequest now, we must filter all successive
                 // RootRequests
          filterRootRequest = true;
        }
      }
      // send request to server
      String requestString = request.getRequestString();
      dos.writeBytes(requestString);

      // we must modify the outputstream now, but defer modification
      // of the inputstream until we are about to read a response.
      // This is because some modifiers (e.g. gzip) read the header
      // on construction, and obviously no header is present when
      // no response has been sent
      request.modifyOutputStream(connection);
      if (request.modifiesInputStream()) {
        streamModifierRequests.add(request);
      }
      dos = connection.getOutputStream();

      FileDetails fileDetails = request.getFileForTransmission();
      if (fileDetails != null) {
        final File file = fileDetails.getFile();
        // only transmit the file if it exists! When committing
        // a remove request you cannot transmit the file
        if (file.exists()) {
          Logger.logOutput(
              new String(
                      "<Sending file: "
                          + // NOI18N
                          file.getAbsolutePath()
                          + ">\n")
                  .getBytes("utf8")); // NOI18N

          if (fireEnhancedEvents) {
            CVSEvent event =
                new EnhancedMessageEvent(this, EnhancedMessageEvent.FILE_SENDING, file);
            getEventManager().fireCVSEvent(event);

            fileDetailRequestCount--;
          }

          if (fileDetails.isBinary()) {
            transmitFileHandler.transmitBinaryFile(file, dos);
          } else {
            transmitFileHandler.transmitTextFile(file, dos);
          }

          if (fireEnhancedEvents && fileDetailRequestCount == 0) {
            CVSEvent event =
                new EnhancedMessageEvent(this, EnhancedMessageEvent.REQUESTS_SENT, "Ok"); // NOI18N
            getEventManager().fireCVSEvent(event);
          }
        }
      }
      if (request.isResponseExpected()) {
        dos.flush();

        // now perform the deferred modification of the input stream
        Iterator modifiers = streamModifierRequests.iterator();
        while (modifiers.hasNext()) {
          System.err.println("Modifying the inputstream..."); // NOI18N
          final Request smRequest = (Request) modifiers.next();
          System.err.println(
              "Request is a: "
                  + // NOI18N
                  smRequest.getClass().getName());
          smRequest.modifyInputStream(connection);
        }
        streamModifierRequests.clear();

        handleResponse();
      }
    }
    dos.flush();

    transmitFileHandler = null;
  }