|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.vcscore.cmdline; import java.beans.*; import java.io.*; import java.lang.reflect.*; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.text.*; import org.openide.ErrorManager; import org.openide.filesystems.FileObject; import org.openide.util.*; import org.netbeans.api.vcs.VcsManager; import org.netbeans.api.vcs.commands.Command; import org.netbeans.api.vcs.commands.CommandTask; import org.netbeans.spi.vcs.commands.CommandSupport; import org.netbeans.modules.vcscore.cmdline.exec.*; import org.netbeans.modules.vcscore.*; import org.netbeans.modules.vcscore.caching.RefreshCommandSupport; import org.netbeans.modules.vcscore.caching.StatusFormat; import org.netbeans.modules.vcscore.commands.CommandDataOutputListener; import org.netbeans.modules.vcscore.commands.CommandExecutionContext; import org.netbeans.modules.vcscore.commands.CommandOutputListener; import org.netbeans.modules.vcscore.commands.RegexOutputListener; import org.netbeans.modules.vcscore.commands.TextInput; import org.netbeans.modules.vcscore.commands.TextOutputListener; import org.netbeans.modules.vcscore.commands.VcsCommand; import org.netbeans.modules.vcscore.commands.VcsCommandExecutor; import org.netbeans.modules.vcscore.commands.VcsCommandIO; import org.netbeans.modules.vcscore.commands.VcsCommandVisualizer; import org.netbeans.modules.vcscore.commands.VcsDescribedCommand; import org.netbeans.modules.vcscore.util.*; //import org.netbeans.modules.vcscore.revision.RevisionListener; /** Execute command. * * @author Michal Fadljevic, Martin Entlicher */ //------------------------------------------- public class ExecuteCommand extends Object implements VcsCommandExecutor { public static final String DEFAULT_REGEX = "^(.*$)"; // Match the whole line by default. public static final String STATUS_USE_REG_EXP_PARSE_OUTPUT = "REG_EXP_PARSE_OUTPUT"; // Use the output of the parsing as the status private CommandExecutionContext executionContext = null; private VcsFileSystem fileSystem = null; private UserCommand cmd = null; private Hashtable vars = null; /** * The preferred execution string, that should be used instead of the * execution string defined by the command. This is usually pre-processed * command's execution string, where some values may be expanded. */ private String preferredExec = null; /** * Fully expanded preferred execution string. This is the final execution * string, that is used to run the command. */ private String preferredExecExpanded = null; /** * The preferred structured execution property, that should be used instead * of the structured execution property defined by the command. * This is usually pre-processed command's execution property, * where some values may be expanded. */ private StructuredExec preferredStructuredExec = null; /** The command associated with this executor. * @deprecated For compatibility with the old VCS "API" only. */ private VcsDescribedCommand command = null; /** The CommandTask associated with this executor. */ private CommandTask task = null; /** The underlying text input command, if any. */ private TextInput txtInputCommand = null; //private RegexListener stdoutListener = null; //private RegexListener stderrListener = null; //private NoRegexListener stdoutNoRegexListener = null; //private NoRegexListener stderrNoRegexListener = null; //private OutputContainer errorContainer = null; private ArrayList textOutputListeners = new ArrayList(); private ArrayList textErrorListeners = new ArrayList(); private ArrayList regexOutputListeners = new ArrayList(); private ArrayList regexErrorListeners = new ArrayList(); private ArrayList dataOutputListeners = new ArrayList(); // For compatibility only private ArrayList dataErrorListeners = new ArrayList(); // For compatibility only private ArrayList fileReaderListeners = new ArrayList(); private ArrayList immediateOutputListeners = new ArrayList(); private ArrayList immediateErrorListeners = new ArrayList(); private boolean doFileRefresh; // Whether this command provides updated status of processed files private boolean doPostExecutionRefresh; // Whether this command refresh status of all processed files private boolean getFileRefreshFromErrOut = false; // Whether to read the refresh info from the error data output also private ArrayList filesToRefresh; // The list of files, that were not refreshed. // Files, that were not refreshed when the command finish // will be refreshed by the LIST_FILE command (if present). private ArrayList refreshInfoElements; /** The base folder, that will be prepended to the refreshed files, so that * the result will be relative to FS root (work + relative mount point) */ private String refreshFilesBase = null; /** The folder that the refreshed files must start with. This is important * if there is a non-empty relative mount point, but the files are relative * to working dir (the files must start with the relative mount point in this * case). */ private String refreshFilesMustStartWith = null; private boolean substituteStatuses = false; private Pattern[] substituitionRegExps; private String[] substituitionStatuses; private Collection processingFilesCollection = null; protected int exitStatus = 0; //private ArrayList commandListeners = new ArrayList(); //------------------------------------------- public ExecuteCommand(CommandExecutionContext executionContext, UserCommand cmd, Hashtable vars) { this(executionContext, cmd, vars, null); } public ExecuteCommand(CommandExecutionContext executionContext, UserCommand cmd, Hashtable vars, String preferredExec) { //super("VCS-ExecuteCommand-"+cmd.getName()); // NOI18N this.executionContext = executionContext; if (executionContext instanceof VcsFileSystem) { this.fileSystem = (VcsFileSystem) executionContext; } else { this.fileSystem = null; } this.cmd = cmd; this.vars = vars; if (preferredExec == null) { preferredExec = (String) cmd.getProperty(VcsCommand.PROPERTY_EXEC); } this.preferredExec = preferredExec; this.doFileRefresh = (fileSystem != null) && VcsCommandIO.getIntegerPropertyAssumeNegative(cmd, UserCommand.PROPERTY_LIST_INDEX_FILE_NAME) >= 0; this.doPostExecutionRefresh = (fileSystem != null) && VcsCommandIO.getBooleanProperty(cmd, UserCommand.PROPERTY_REFRESH_PROCESSED_FILES); if (doFileRefresh) { refreshInfoElements = new ArrayList(); String statusSubstitutions = (String) cmd.getProperty(UserCommand.PROPERTY_REFRESH_FILE_STATUS_SUBSTITUTIONS); substituteStatuses = (statusSubstitutions != null && statusSubstitutions.length() > 0); if (substituteStatuses) { parseStatusSubstitutions(statusSubstitutions); } getFileRefreshFromErrOut = VcsCommandIO.getBooleanProperty(cmd, UserCommand.PROPERTY_REFRESH_INFO_FROM_BOTH_DATA_OUTS); } } private void parseStatusSubstitutions(String statusSubstitutions) { String[] substitutions = VcsUtilities.getQuotedStrings(statusSubstitutions); int n = substitutions.length / 2; Pattern[] regExps = new Pattern[n]; String[] statuses = new String[n]; int nn = n; for (int i = 0; i < n; i++) { try { regExps[i] = Pattern.compile(substitutions[2*i]); } catch(PatternSyntaxException e) { ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(e, NbBundle.getMessage(ExecuteCommand.class, "MSG_BadRegExpInStatusSubstitution", substitutions[2*i]))); nn--; continue; //throw new BadRegexException("Bad regexp.", e); // NOI18N } statuses[i] = substitutions[2*i + 1]; } if (n == nn) { substituitionRegExps = regExps; substituitionStatuses = statuses; } else { n = nn; substituitionRegExps = new Pattern[n]; substituitionStatuses = new String[n]; int j = 0; for (int i = 0; i < n; i++) { if (regExps[j] == null) { i--; } else { substituitionRegExps[i] = regExps[j]; substituitionStatuses[i] = statuses[j]; } j++; } } } /** * Get the command associated with this ExecuteCommand. * @deprecated Needed for the compatibility with old "API" only. */ public VcsDescribedCommand getDescribedCommand() { return command; } /** * Set the command associated with this ExecuteCommand. * @deprecated Needed for the compatibility with old "API" only. */ public void setDescribedCommand(VcsDescribedCommand command) { this.command = command; } /** * Set the CommandTask, that is associated with this executor. */ public CommandTask getTask() { return task; } /** * Get the CommandTask, that is associated with this executor. */ public void setTask(CommandTask task) { this.task = task; } /** * Add the listener to the standard output of the command. The listeners are removed * when the command finishes. */ public final synchronized void addTextOutputListener(TextOutputListener l) { if (textOutputListeners != null) textOutputListeners.add(l); } /** * Add the listener to the error output of the command. The listeners are removed * when the command finishes. */ public final synchronized void addTextErrorListener(TextOutputListener l) { if (textErrorListeners != null) textErrorListeners.add(l); } /** * Add the listener to the data output of the command. This output may contain * a parsed information from its standard output or some other data provided * by this command. The listeners are removed when the command finishes. */ public final synchronized void addRegexOutputListener(RegexOutputListener l) { if (regexOutputListeners != null) regexOutputListeners.add(l); } /** * Add the listener to the data error output of the command. This output may contain * a parsed information from its error output or some other data provided * by this command. If there are some data given to this listener, the command * is supposed to fail. The listeners are removed when the command finishes. */ public final synchronized void addRegexErrorListener(RegexOutputListener l) { if (regexErrorListeners != null) regexErrorListeners.add(l); } /** * Add the listener to the standard output of the command. The listeners should be * released by the implementing class, when the command finishes. * @deprecated Kept for compatibility reasons only. * Use {@link #addTextOutputListener} instead. */ public void addOutputListener(CommandOutputListener l) { if (textOutputListeners != null) textOutputListeners.add(l); } /** * Add the listener to the error output of the command. The listeners should be * released by the implementing class, when the command finishes. * @deprecated Kept for compatibility reasons only. * Use {@link #addTextErrorListener} instead. */ public void addErrorOutputListener(CommandOutputListener l) { if (textErrorListeners != null) textErrorListeners.add(l); } /** * Add the listener to the data output of the command. This output may contain * a parsed information from its standard output or some other data provided * by this command. The listeners should be released by the implementing class, * when the command finishes. * @deprecated Kept for compatibility reasons only. * Use {@link #addRegexOutputListener} instead. */ public void addDataOutputListener(CommandDataOutputListener l) { if (dataOutputListeners != null) dataOutputListeners.add(l); } /** * Add the listener to the data error output of the command. This output may contain * a parsed information from its error output or some other data provided * by this command. If there are some data given to this listener, the command * is supposed to fail. The listeners should be released by the implementing class, * when the command finishes. * @deprecated Kept for compatibility reasons only. * Use {@link #addRegexErrorListener} instead. */ public void addDataErrorOutputListener(CommandDataOutputListener l) { if (dataErrorListeners != null) dataErrorListeners.add(l); } public void addImmediateTextOutputListener(TextOutputListener l) { if (immediateOutputListeners != null) immediateOutputListeners.add(l); } public void addImmediateTextErrorListener(TextOutputListener l) { if (immediateErrorListeners != null) immediateErrorListeners.add(l); } public void sendInput(String input) { if (txtInputCommand != null) { txtInputCommand.sendInput(input); } } public final VcsCommand getCommand() { return cmd; } /** * Get the variables used by this command execution. */ public final Hashtable getVariables() { return vars; } //------------------------------------------- public final int getExitStatus(){ return exitStatus; } private VcsCommandVisualizer createVisualizer() { String visualizerClassName = (String) cmd.getProperty(VcsCommand.PROPERTY_DISPLAY_VISUALIZER); if (visualizerClassName != null) { Class visualizerClass = null; try { visualizerClass = Class.forName(visualizerClassName, true, VcsUtilities.getSFSClassLoader()); } catch (ClassNotFoundException e) {} if (visualizerClass == null) { try { visualizerClass = Class.forName(visualizerClassName, true, (ClassLoader) Lookup.getDefault().lookup(ClassLoader.class)); } catch (ClassNotFoundException e) {} } if (visualizerClass == null) { try { printErrorOutput("CLASS EXEC: " + g("ERR_ClassNotFound", visualizerClassName)); // NOI18N } catch(java.util.MissingResourceException mrexc) { // Likely to be called when the module is being uninstalled printErrorOutput("CLASS EXEC: Class " + visualizerClassName + " not found"); // NOI18N } } else { VcsCommandVisualizer visualizer = null; try { visualizer = (VcsCommandVisualizer) visualizerClass.newInstance(); } catch (InstantiationException e) { printErrorOutput("CLASS EXEC: "+g("ERR_CanNotInstantiate", visualizerClass)); // NOI18N } catch (IllegalAccessException e) { printErrorOutput("CLASS EXEC: "+g("ERR_IllegalAccessOnClass", visualizerClass)); // NOI18N } return visualizer; } } return null; } /** * Get the graphical visualization of the command. * The returned visualizer might need to be initialized in UserCommandTask, * that owns the CommandOutputCollector. * @return null no visualization is desired. */ public VcsCommandVisualizer getVisualizer() { return createVisualizer(); } private void commandFinished(String exec, boolean success) { textOutputListeners.clear(); textErrorListeners.clear(); regexOutputListeners.clear(); regexErrorListeners.clear(); dataOutputListeners.clear(); dataErrorListeners.clear(); immediateOutputListeners.clear(); immediateErrorListeners.clear(); if (doFileRefresh) { flushRefreshInfo(); cleanupSendRefreshInfo(); } textOutputListeners = null; textErrorListeners = null; regexOutputListeners = null; regexErrorListeners = null; dataOutputListeners = null; dataErrorListeners = null; immediateOutputListeners = null; immediateErrorListeners = null; if (success || VcsCommandIO.getIntegerPropertyAssumeNegative(cmd, VcsCommand.PROPERTY_REFRESH_ON_FAIL) == 1) { refreshRemainingFiles(); /* Moved to CommandExecutorSupport String path = (String) vars.get("DIR") + "/" + (String) vars.get("FILE"); path = path.replace(java.io.File.separatorChar, '/'); if (VcsCommandIO.getBooleanProperty(cmd, VcsCommand.PROPERTY_CHECK_FOR_MODIFICATIONS)) { //System.out.println(cmd.getName()+" finished successfully."); fileSystem.checkForModifications(path); /* org.openide.filesystems.FileObject fo = fileSystem.findResource(path); System.out.println("fo("+path+") = "+fo); if (fo != null) { System.out.println("calling refresh(true)..."); fo.refresh(true); } * } */ int whatChanged = 0; Object changedInfo = null; } fileReaderListeners.clear(); fileReaderListeners = null; } /** * This method can be used to do some preprocessing of the command which is to be run. * @param vc the command to be preprocessed. * @param vars the variables * @param exec the updated execution string. It may contain user input from variable input dialog * @return the updated exec property */ public String preprocessCommand(VcsCommand vc, Hashtable vars, String exec, StructuredExec sexec) { this.preferredExec = exec; this.preferredStructuredExec = sexec; executionContext.getVarValueAdjustment().adjustVarValues(vars); boolean createTempFile = false; if (sexec != null) { StructuredExec.Argument[] args = sexec.getArguments(); for (int i = 0; i < args.length; i++) { if (args[i].getArgument().indexOf(Variables.TEMPORARY_FILE) >= 0) { createTempFile = true; break; } } } else { createTempFile = (exec != null && exec.indexOf(Variables.TEMPORARY_FILE) >= 0); } if (createTempFile && vars.get(Variables.TEMPORARY_FILE) == null) { try { File tempFile = File.createTempFile("VCS", "tmp"); tempFile.deleteOnExit(); vars.put(Variables.TEMPORARY_FILE, tempFile.getAbsolutePath()); } catch (IOException ioex) {} } this.vars = vars; if (exec != null) { this.preferredExecExpanded = Variables.expand(vars, exec, false); } /* if (!(vc instanceof UserCommand)) return ""; UserCommand uc = (UserCommand) vc; PreCommandPerformer cmdPerf = new PreCommandPerformer(fileSystem, uc, vars); String exec = cmdPerf.process(); */ return exec; } /** * Get the updated execution string. It may contain user input now. */ public String getExec() { return preferredExecExpanded; } protected final VcsFileSystem getFileSystem() { return fileSystem; } /** * Add the data and error regular expression listeners, * if some global regex is defined, return the global data * output in the first item and global error output in the second. * @param ec the command to add the listeners to * @param globalRegexs the array, that is filled with compiled data and error * regular expressions * @return the array of length 2 with global data and error output * (either of them can be null) or null, when none of them are defined */ private StringBuffer[] addRegexListeners(final ExternalCommand ec, final Pattern[] globalRegexs) { String dataRegex = (String) cmd.getProperty(UserCommand.PROPERTY_DATA_REGEX); if (dataRegex == null) dataRegex = DEFAULT_REGEX; String errorRegex = (String) cmd.getProperty(UserCommand.PROPERTY_ERROR_REGEX); if (errorRegex == null) errorRegex = DEFAULT_REGEX; String dataRegexGlobal = (String) cmd.getProperty(UserCommand.PROPERTY_DATA_REGEX_GLOBAL); String errorRegexGlobal = (String) cmd.getProperty(UserCommand.PROPERTY_ERROR_REGEX_GLOBAL); Pattern dataRegexGlobalRE = null; Pattern errorRegexGlobalRE = null; final StringBuffer dataOutput; final StringBuffer errorOutput; if (dataRegexGlobal != null) { try { dataRegexGlobalRE = Pattern.compile(dataRegexGlobal); } catch (PatternSyntaxException exc) { ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(exc, NbBundle.getMessage(ExternalCommand.class, "MSG_BadRegexMessageInfo", dataRegexGlobal))); } if (dataRegexGlobalRE != null) { globalRegexs[0] = dataRegexGlobalRE; dataOutput = new StringBuffer(); } else { dataOutput = null; } } else { dataOutput = null; } if (errorRegexGlobal != null) { try { errorRegexGlobalRE = Pattern.compile(errorRegexGlobal); } catch (PatternSyntaxException exc) { ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(exc, NbBundle.getMessage(ExternalCommand.class, "MSG_BadRegexMessageInfo", errorRegexGlobal))); } if (errorRegexGlobalRE != null) { globalRegexs[1] = errorRegexGlobalRE; errorOutput = new StringBuffer(); } else { errorOutput = null; } } else { errorOutput = null; } try { if (dataRegexGlobalRE == null) { ec.addRegexOutputListener(new RegexOutputListener() { public void outputMatchedGroups(String[] data) { printDataOutput(data); } }, dataRegex); } else { ec.addRegexOutputListener(new RegexOutputListener() { public void outputMatchedGroups(String[] data) { if (data != null) { for (int i = 0; i < data.length; i++) { dataOutput.append(data[i]); } dataOutput.append(" "); } } }, dataRegex); } } catch (BadRegexException e) { ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(e, NbBundle.getMessage(ExternalCommand.class, "MSG_BadRegexMessageInfo", dataRegex))); } try { if (errorRegexGlobalRE == null) { ec.addRegexErrorListener(new RegexOutputListener() { public void outputMatchedGroups(String[] data) { printDataErrorOutput(data); } }, errorRegex); } else { ec.addRegexErrorListener(new RegexOutputListener() { public void outputMatchedGroups(String[] data) { if (data != null) { for (int i = 0; i < data.length; i++) { errorOutput.append(data[i]); } errorOutput.append(" "); } } }, errorRegex); } } catch (BadRegexException e) { ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(e, NbBundle.getMessage(ExternalCommand.class, "MSG_BadRegexMessageInfo", errorRegex))); } if (dataOutput != null || errorOutput != null) { return new StringBuffer[] { dataOutput, errorOutput }; } else { return null; } } private void printGlobalDataOutput(String globalDataOutput, Pattern globalDataRegex) { if (globalDataOutput.endsWith(" ")) { globalDataOutput = globalDataOutput.substring(0, globalDataOutput.length() - 1); } String[] parsed = ExternalCommand.matchToStringArray(globalDataRegex, globalDataOutput); printDataOutput(parsed); } private void printGlobalErrorDataOutput(String globalDataOutput, Pattern globalDataRegex) { if (globalDataOutput.endsWith(" ")) { globalDataOutput = globalDataOutput.substring(0, globalDataOutput.length() - 1); } String[] parsed = ExternalCommand.matchToStringArray(globalDataRegex, globalDataOutput); printDataErrorOutput(parsed); } //------------------------------------------- /** * Execute a command-line command. */ protected void runCommand(String[] execs) { //exec = Variables.expand(vars,exec, true); preferredExec = preferredExecExpanded = VcsUtilities.array2stringNl(execs); StringBuffer[] globalDataOutputWhole = null; Pattern[] globalRegexs = new Pattern[2]; for (int i = 0; i < execs.length; i++) { String exec = execs[i]; ExternalCommand ec = new ExternalCommand(exec); setupExternalCommand(ec); StringBuffer[] globalDataOutput = addRegexListeners(ec, globalRegexs); int status = ec.exec(); if (status != exitStatus) { if (exitStatus == VcsCommandExecutor.SUCCEEDED || exitStatus == VcsCommandExecutor.FAILED && status == VcsCommandExecutor.INTERRUPTED) { exitStatus = status; } } if (globalDataOutput != null) { if (globalDataOutputWhole == null) { globalDataOutputWhole = globalDataOutput; } else { if (globalDataOutputWhole[0] != null) { globalDataOutputWhole[0].append(globalDataOutput[0]); } if (globalDataOutputWhole[1] != null) { globalDataOutputWhole[1].append(globalDataOutput[1]); } } } } if (globalDataOutputWhole != null) { if (globalDataOutputWhole[0] != null) { printGlobalDataOutput(globalDataOutputWhole[0].toString(), globalRegexs[0]); } if (globalDataOutputWhole[1] != null) { printGlobalErrorDataOutput(globalDataOutputWhole[1].toString(), globalRegexs[1]); } } switch (exitStatus) { case VcsCommandExecutor.SUCCEEDED: commandFinished(preferredExecExpanded, true); break; case VcsCommandExecutor.INTERRUPTED: //commandFinished(exec, false); //break; // Do the same as when the command fails. case VcsCommandExecutor.FAILED: commandFinished(preferredExecExpanded, false); if (fileSystem != null) fileSystem.removeNumDoAutoRefresh((String) vars.get("DIR")); // NOI18N break; } } /** * Execute a command-line command. */ protected void runCommand(StructuredExec exec) { preferredExec = preferredExecExpanded = VcsUtilities.array2stringNl(ExternalCommand.parseParameters(exec)); StringBuffer[] globalDataOutputWhole = null; Pattern[] globalRegexs = new Pattern[2]; ExternalCommand ec = new ExternalCommand(exec); setupExternalCommand(ec); StringBuffer[] globalDataOutput = addRegexListeners(ec, globalRegexs); int status = ec.exec(); exitStatus = status; if (globalDataOutput != null) { if (globalDataOutput[0] != null) { printGlobalDataOutput(globalDataOutput[0].toString(), globalRegexs[0]); } if (globalDataOutput[1] != null) { printGlobalErrorDataOutput(globalDataOutput[1].toString(), globalRegexs[1]); } } switch (exitStatus) { case VcsCommandExecutor.SUCCEEDED: commandFinished(preferredExecExpanded, true); break; case VcsCommandExecutor.INTERRUPTED: //commandFinished(exec, false); //break; // Do the same as when the command fails. case VcsCommandExecutor.FAILED: commandFinished(preferredExecExpanded, false); if (fileSystem != null) fileSystem.removeNumDoAutoRefresh((String) vars.get("DIR")); // NOI18N break; } } private void setupExternalCommand(ExternalCommand ec) { this.txtInputCommand = (TextInput) ec; //ec.setTimeout(cmd.getTimeout()); ec.setInput((String) cmd.getProperty(UserCommand.PROPERTY_INPUT), VcsCommandIO.getBooleanProperty(cmd, UserCommand.PROPERTY_INPUT_REPEAT)); String dynamicEnv = (String) getVariables().get("DYNAMIC_ENVIRONMENT_VARS"); if (dynamicEnv != null && dynamicEnv.length() > 0) { ec.setEnv(getEnvironmentFromVars(getVariables())); } else { ec.setEnv(executionContext.getEnvironmentVars()); } for (Iterator it = textOutputListeners.iterator(); it.hasNext(); ) { ec.addTextOutputListener((TextOutputListener) it.next()); } for (Iterator it = textErrorListeners.iterator(); it.hasNext(); ) { ec.addTextErrorListener((TextOutputListener) it.next()); } for (Iterator it = immediateOutputListeners.iterator(); it.hasNext(); ) { ec.addImmediateTextOutputListener((TextOutputListener) it.next()); } for (Iterator it = immediateErrorListeners.iterator(); it.hasNext(); ) { ec.addImmediateTextErrorListener((TextOutputListener) it.next()); } } private static String[] getEnvironmentFromVars(Hashtable vars) { Map systemEnv = VcsUtilities.getSystemEnvVars(); Map env = VcsUtilities.addEnvVars(systemEnv, vars, VcsFileSystem.VAR_ENVIRONMENT_PREFIX, VcsFileSystem.VAR_ENVIRONMENT_REMOVE_PREFIX); return VcsUtilities.getEnvString(env); } protected void printOutput(String line) { for (Iterator it = textOutputListeners.iterator(); it.hasNext(); ) { ((TextOutputListener) it.next()).outputLine(line); } } protected void printErrorOutput(String line) { for (Iterator it = textErrorListeners.iterator(); it.hasNext(); ) { ((TextOutputListener) it.next()).outputLine(line); } } protected void printDataOutput(String[] data) { for (Iterator it = regexOutputListeners.iterator(); it.hasNext(); ) { ((RegexOutputListener) it.next()).outputMatchedGroups(data); } for (Iterator it = dataOutputListeners.iterator(); it.hasNext(); ) { ((CommandDataOutputListener) it.next()).outputData(data); } if (doFileRefresh) { collectRefreshInfo(data); } } protected void printDataErrorOutput(String[] data) { for (Iterator it = regexErrorListeners.iterator(); it.hasNext(); ) { ((RegexOutputListener) it.next()).outputMatchedGroups(data); } for (Iterator it = dataErrorListeners.iterator(); it.hasNext(); ) { ((CommandDataOutputListener) it.next()).outputData(data); } if (getFileRefreshFromErrOut) { collectRefreshInfo(data); } } /** * Loads class of given name with some arguments and execute its exec() method. * @param className the name of the class to be loaded * @param args the arguments */ protected void runClass(String exec, String className, String[] args) { boolean success = true; Class execClass = null; preferredExec = preferredExecExpanded = exec; try { execClass = Class.forName(className, true, VcsUtilities.getSFSClassLoader()); //org.openide.TopManager.getDefault().currentClassLoader()); } catch (ClassNotFoundException e) {} if (execClass == null) { try { printErrorOutput("CLASS EXEC: " + g("ERR_ClassNotFound", className)); // NOI18N } catch(java.util.MissingResourceException mrexc) { // Likely to be called when the module is being uninstalled printErrorOutput("CLASS EXEC: Class " + className + " not found"); // NOI18N } success = false; } VcsAdditionalCommand execCommand = null; if (success) { try { execCommand = (VcsAdditionalCommand) execClass.newInstance(); } catch (InstantiationException e) { printErrorOutput("CLASS EXEC: "+g("ERR_CanNotInstantiate", execClass)); // NOI18N /* fileSystem.debug ("EXEC: "+g("ERR_CanNotInstantiate", execClass)); // NOI18N if (stderrNoRegexListener != null) stderrNoRegexListener.match("EXEC: "+g("ERR_CanNotInstantiate", execClass)); // NOI18N */ success = false; } catch (IllegalAccessException e) { printErrorOutput("CLASS EXEC: "+g("ERR_IllegalAccessOnClass", execClass)); // NOI18N /* fileSystem.debug ("EXEC: "+g("ERR_IllegalAccessOnClass", execClass)); // NOI18N if (stderrNoRegexListener != null) stderrNoRegexListener.match("EXEC: "+g("ERR_IllegalAccessOnClass", execClass)); // NOI18N */ success = false; } } if (success) { ExecuteCommand.setAdditionalParams(execCommand, fileSystem, executionContext); String dataRegex = (String) cmd.getProperty(UserCommand.PROPERTY_DATA_REGEX); String errorRegex = (String) cmd.getProperty(UserCommand.PROPERTY_ERROR_REGEX); String input = (String) cmd.getProperty(UserCommand.PROPERTY_INPUT); if (dataRegex != null) vars.put("DATAREGEX", dataRegex); // NOI18N if (errorRegex != null) vars.put("ERRORREGEX", errorRegex); // NOI18N if (input != null) vars.put("INPUT", input); // NOI18N //vars.put("TIMEOUT", new Long(cmd.getTimeout())); // NOI18N //TopManager.getDefault().setStatusText(g("MSG_Command_name_running", cmd.getName())); if (execCommand instanceof TextInput) { this.txtInputCommand = (TextInput) execCommand; } try { if (execCommand instanceof VcsAdditionalCommand.ImmediateOutput) { VcsAdditionalCommand.ImmediateOutput io = (VcsAdditionalCommand.ImmediateOutput) execCommand; for (Iterator it = immediateOutputListeners.iterator(); it.hasNext(); ) { io.addImmediateTextOutputListener((TextOutputListener) it.next()); } for (Iterator it = immediateErrorListeners.iterator(); it.hasNext(); ) { io.addImmediateTextErrorListener((TextOutputListener) it.next()); } } success = execCommand.exec(vars, args, new CommandOutputListener() { public void outputLine(String line) { printOutput(line); } }, new CommandOutputListener() { public void outputLine(String line) { printErrorOutput(line); } }, new CommandDataOutputListener() { public void outputData(String[] data) { printDataOutput(data); } }, dataRegex, new CommandDataOutputListener() { public void outputData(String[] data) { printDataErrorOutput(data); } }, errorRegex ); } catch (ThreadDeath td) { throw td; // re-throw the ThreadDeath } catch (Throwable thr) { // Something bad has happened in the called class! success = false; ErrorManager.getDefault().notify( ErrorManager.getDefault().annotate(thr, NbBundle.getMessage(ExecuteCommand.class, "ERR_EXC_IN_CLASS", className))); } } if (Thread.interrupted()) { exitStatus = VcsCommandExecutor.INTERRUPTED; commandFinished(exec, false); if (fileSystem != null) fileSystem.removeNumDoAutoRefresh((String) vars.get("DIR")); // NOI18N } else { if (success) { exitStatus = VcsCommandExecutor.SUCCEEDED; commandFinished(exec, true); } else { exitStatus = VcsCommandExecutor.FAILED; commandFinished(exec, false); if (fileSystem != null) fileSystem.removeNumDoAutoRefresh((String) vars.get("DIR")); // NOI18N } } } /** * Execute the command. */ public void run() { //isRunning = true; //hasStarted = true; String exec = null; String[] execs = null; int maxCmdLength = 0; String maxCmdLengthStr = (String) vars.get(Variables.MAX_CMD_LENGTH); if (maxCmdLengthStr != null) { try { maxCmdLength = Integer.parseInt(maxCmdLengthStr); } catch (NumberFormatException nfex) {} } StructuredExec sexec = preferredStructuredExec; if (sexec == null) sexec = (StructuredExec) cmd.getProperty(VcsCommand.PROPERTY_EXEC_STRUCTURED); if (sexec != null) { sexec = sexec.getExpanded(vars, false); } else { if (preferredExec != null) exec = preferredExec; else exec = (String) cmd.getProperty(VcsCommand.PROPERTY_EXEC); //System.out.println("ExecuteCommand.run(): exec = "+exec+"\npreferredExec = "+preferredExec); if (exec == null) return ; // Silently ignore null exec String execOrig = exec; exec = Variables.expand(vars, exec, false); exec = exec.trim(); if (exec.trim().length() == 0) { preferredExec = ""; return ; // Silently ignore empty exec } //System.out.println("Exec length = "+exec.length()+", MAX is "+maxCmdLengthStr); if (maxCmdLength > 0 && exec.length() > maxCmdLength) { execs = splitExec(execOrig, maxCmdLength); } else { execs = new String[] { exec }; } } if (doPostExecutionRefresh) { filesToRefresh = new ArrayList(getFiles()); // All files should be refreshed at the end. } else if (doFileRefresh) { filesToRefresh = new ArrayList(); // Only some files (with unmatched status) should be refreshed. } // Initialize refreshFilesBase and refreshFilesMustStartWith fields: createRefreshFilesBase(); boolean checkForModification = VcsCommandIO.getBooleanProperty(cmd, VcsCommand.PROPERTY_CHECK_FOR_MODIFICATIONS) && (fileSystem != null); Collection processingFiles = null; if (checkForModification) { processingFiles = getFiles(); fileSystem.disableRefresh(); for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { fileSystem.lockFilesToBeModified((String) it.next(), true); } } try { if (checkForModification) { // It's crucial to once more save any possibly modified objects // after we have locked them. List fileObjects = new ArrayList(processingFiles.size()); for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { FileObject fo = fileSystem.findResource((String) it.next()); if (fo != null) { fileObjects.add(fo); } } VcsAction.assureFilesSaved(fileObjects); } if (sexec != null) { String exe = sexec.getExecutable(); if (exe.toLowerCase().endsWith(".class")) { String[] eargs = ExternalCommand.parseParameters(sexec); String[] args = new String[eargs.length - 1]; System.arraycopy(eargs, 1, args, 0, args.length); runClass(VcsUtilities.array2stringNl(eargs), exe.substring(0, exe.length() - ".class".length()), args); } else { runCommand(sexec); } } else { String[] allArgs = VcsUtilities.getQuotedArguments(exec); String first = allArgs[0]; if (first != null && (first.toLowerCase().endsWith(".class"))) {// NOI18N String[] args = new String[allArgs.length - 1]; System.arraycopy(allArgs, 1, args, 0, args.length); runClass(exec, first.substring(0, first.length() - ".class".length()), args); // NOI18N } else { runCommand(execs); } } } finally { if (checkForModification) { fileSystem.enableRefresh(); for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { fileSystem.unlockFilesToBeModified((String) it.next(), true); } } String tempFilePath = (String) vars.get(Variables.TEMPORARY_FILE); if (tempFilePath != null) { String postCommands; if (getExitStatus() == VcsCommandExecutor.SUCCEEDED) { postCommands = (String) cmd.getProperty(VcsCommand.PROPERTY_COMMANDS_AFTER_SUCCESS); } else { postCommands = (String) cmd.getProperty(VcsCommand.PROPERTY_COMMANDS_AFTER_FAIL); } if (postCommands != null) { postCommands = Variables.expand(vars, postCommands, false).trim(); } if (postCommands == null || postCommands.length() == 0) { new File(tempFilePath).delete(); } } } } private String[] splitExec(String exec, int maxCmdLength) { //System.out.println("splitExec("+exec+", "+maxCmdLength+")"); String[] varNames = new String[] { "FILES", "QFILES", "PATHS", "QPATHS", "MPATHS", "QMPATHS" }; int nVARS = varNames.length; int[][] fileIndexes = new int[nVARS][]; int nFiles = 0; for (int i = 0; i < nVARS; i++) { String indexesEncoded = (String) vars.get(varNames[i]+"_FILE_POS_INDEXES"); if (indexesEncoded != null) { try { fileIndexes[i] = (int[]) VcsUtilities.decodeValue(indexesEncoded); nFiles = fileIndexes[i].length; } catch (java.io.IOException ioex) {} } } if (nFiles <= 1) { // We can not shrink this anyway, Therefore we simply return the original exec return new String[] { Variables.expand(vars, exec, false) }; } String[] varValues = new String[nVARS]; for (int i = 0; i < nVARS; i++) { varValues[i] = (String) vars.get(varNames[i]); } Hashtable tempVars = new Hashtable(vars); ArrayList execs = new ArrayList(); int startFileIndex = 0; //System.out.println("nFiles = "+nFiles); do { int i = startFileIndex; int j = nFiles; String execTemp = null; int lastK = -1; while (i < j) { int k = (i + j + 1)/2; //System.out.println(" i = "+i+", j = "+j+", k = "+k); if (k == startFileIndex) k++; if (k == lastK) { // prevent an infinite loop. if (i != k) { if (i == startFileIndex) { i = k; // We need to accept a longer execution string :-( } else { k = i; // We're in the loop and the exec string was too long j = i; } } else { break; } } execTemp = getTempExec(startFileIndex, k, fileIndexes, exec, nVARS, varNames, varValues, tempVars); //System.out.print(" exec "+((execTemp.length() < maxCmdLength) ? "<" : ">=")+" MAX =>"); if (execTemp.length() < maxCmdLength) { i = k; //j = k; // For simplicity stop it here. Do not look for longer exec. } else { j = k; } lastK = k; //System.out.println(" i = "+i+", j = "+j+", k = "+k+", exec length ("+execTemp.length()+")"+((execTemp.length() < maxCmdLength) ? "<" : ">=")+maxCmdLength); } //System.out.println(" FINAL: i = "+i+", j = "+j+", k = "+lastK+", exec length ("+execTemp.length()+")"+((execTemp.length() < maxCmdLength) ? "<" : ">=")+maxCmdLength); execs.add(execTemp); startFileIndex = i; } while (startFileIndex < nFiles); /* System.out.println("return splitted:"); for (int i = 0; i < execs.size(); i++) { System.out.println(" '"+execs.get(i)+"'"); } System.out.println("========"); */ return (String[]) execs.toArray(new String[0]); } private String getTempExec(int j, int k, int[][] fileIndexes, String exec, int nVARS, String[] varNames, String[] varValues, Hashtable vars) { for (int i = 0; i < nVARS; i++) { String varTempValue; if (j < k) { if (k < fileIndexes[i].length) { varTempValue = varValues[i].substring(fileIndexes[i][j], fileIndexes[i][k] - 1); } else { varTempValue = varValues[i].substring(fileIndexes[i][j]); } } else { varTempValue = ""; } vars.put(varNames[i], varTempValue); //System.out.println(" Temp var "+varNames[i]+" = "+varTempValue); } String execTemp = Variables.expand(vars, exec, false); execTemp = execTemp.trim(); //System.out.println("tempExec("+j+", "+k+") = '"+execTemp+"'"); return execTemp; } /** * Search for optional methods and set additional parameters. */ protected static void setAdditionalParams(Object execCommand, VcsFileSystem fileSystem) { setAdditionalParams(execCommand, fileSystem, fileSystem); } /** * Search for optional methods and set additional parameters. */ protected static void setAdditionalParams(Object execCommand, VcsFileSystem fileSystem, CommandExecutionContext executionContext) { Class clazz = execCommand.getClass(); if (fileSystem != null) { Class[] paramClasses = new Class[] { VcsFileSystem.class }; Method setFileSystemMethod = null; try { setFileSystemMethod = clazz.getDeclaredMethod("setFileSystem", paramClasses); } catch (Exception exc) { setFileSystemMethod = null; } if (setFileSystemMethod != null) { Object[] args = new Object[] { fileSystem }; try { setFileSystemMethod.invoke(execCommand, args); } catch (Exception iae) { // silently ignored } } } Class[] paramClasses = new Class[] { CommandExecutionContext.class }; Method setExecutionContextMethod = null; try { setExecutionContextMethod = clazz.getDeclaredMethod("setExecutionContext", paramClasses); } catch (Exception exc) { setExecutionContextMethod = null; } if (setExecutionContextMethod != null) { Object[] args = new Object[] { executionContext }; try { setExecutionContextMethod.invoke(execCommand, args); } catch (Exception iae) { // silently ignored } } } /** * Get the set of files being processed by the command. * @return the set of files of type |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.