/** * 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 }
/** * 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; }