| /* |
| * Copyright 2000-2011 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.intellij.execution.junit; |
| |
| import com.intellij.ExtensionPoints; |
| import com.intellij.execution.*; |
| import com.intellij.execution.configurations.*; |
| import com.intellij.execution.junit2.TestProxy; |
| import com.intellij.execution.junit2.segments.DeferredActionsQueue; |
| import com.intellij.execution.junit2.segments.DeferredActionsQueueImpl; |
| import com.intellij.execution.junit2.segments.DispatchListener; |
| import com.intellij.execution.junit2.segments.Extractor; |
| import com.intellij.execution.junit2.ui.JUnitTreeConsoleView; |
| import com.intellij.execution.junit2.ui.TestsPacketsReceiver; |
| import com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction; |
| import com.intellij.execution.junit2.ui.model.CompletionEvent; |
| import com.intellij.execution.junit2.ui.model.JUnitRunningModel; |
| import com.intellij.execution.junit2.ui.model.RootTestInfo; |
| import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties; |
| import com.intellij.execution.process.ProcessAdapter; |
| import com.intellij.execution.process.ProcessEvent; |
| import com.intellij.execution.runners.ExecutionEnvironment; |
| import com.intellij.execution.runners.ProgramRunner; |
| import com.intellij.execution.testframework.*; |
| import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil; |
| import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties; |
| import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView; |
| import com.intellij.execution.ui.ConsoleView; |
| import com.intellij.execution.ui.ConsoleViewContentType; |
| import com.intellij.execution.util.JavaParametersUtil; |
| import com.intellij.execution.util.ProgramParametersUtil; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.extensions.Extensions; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleUtilCore; |
| import com.intellij.openapi.projectRoots.JavaSdkType; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.projectRoots.ex.JavaSdkUtil; |
| import com.intellij.openapi.roots.ModuleRootManager; |
| import com.intellij.openapi.roots.ProjectRootManager; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.Getter; |
| import com.intellij.openapi.util.Key; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.util.registry.Registry; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.CharsetToolkit; |
| import com.intellij.psi.*; |
| import com.intellij.refactoring.listeners.RefactoringElementListener; |
| import com.intellij.rt.execution.junit.IDEAJUnitListener; |
| import com.intellij.rt.execution.junit.JUnitStarter; |
| import com.intellij.util.Function; |
| import com.intellij.util.PathUtil; |
| import com.intellij.util.ui.UIUtil; |
| import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.jps.model.serialization.PathMacroUtil; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.util.*; |
| |
| public abstract class TestObject implements JavaCommandLine { |
| protected static final Logger LOG = Logger.getInstance(TestObject.class); |
| |
| private static final String MESSAGE = ExecutionBundle.message("configuration.not.speficied.message"); |
| @NonNls private static final String JUNIT_TEST_FRAMEWORK_NAME = "JUnit"; |
| |
| protected JavaParameters myJavaParameters; |
| protected final JUnitConfiguration myConfiguration; |
| protected final ExecutionEnvironment myEnvironment; |
| protected File myTempFile = null; |
| protected File myWorkingDirsFile = null; |
| public File myListenersFile; |
| |
| public static TestObject fromString(final String id, |
| final JUnitConfiguration configuration, |
| @NotNull ExecutionEnvironment environment) { |
| if (JUnitConfiguration.TEST_METHOD.equals(id)) { |
| return new TestMethod(configuration, environment); |
| } |
| if (JUnitConfiguration.TEST_CLASS.equals(id)) { |
| return new TestClass(configuration, environment); |
| } |
| if (JUnitConfiguration.TEST_PACKAGE.equals(id)){ |
| return new TestPackage(configuration, environment); |
| } |
| if (JUnitConfiguration.TEST_DIRECTORY.equals(id)) { |
| return new TestDirectory(configuration, environment); |
| } |
| if (JUnitConfiguration.TEST_CATEGORY.equals(id)) { |
| return new TestCategory(configuration, environment); |
| } |
| if (JUnitConfiguration.TEST_PATTERN.equals(id)) { |
| return new TestsPattern(configuration, environment); |
| } |
| return NOT_CONFIGURED; |
| } |
| |
| public Module[] getModulesToCompile() { |
| final SourceScope sourceScope = getSourceScope(); |
| return sourceScope != null ? sourceScope.getModulesToCompile() : Module.EMPTY_ARRAY; |
| } |
| |
| protected TestObject(JUnitConfiguration configuration, ExecutionEnvironment environment) { |
| myConfiguration = configuration; |
| myEnvironment = environment; |
| } |
| |
| public abstract String suggestActionName(); |
| |
| public RunnerSettings getRunnerSettings() { |
| return myEnvironment.getRunnerSettings(); |
| } |
| |
| public abstract RefactoringElementListener getListener(PsiElement element, JUnitConfiguration configuration); |
| |
| public abstract boolean isConfiguredByElement(JUnitConfiguration configuration, |
| PsiClass testClass, |
| PsiMethod testMethod, |
| PsiPackage testPackage, |
| PsiDirectory testDir); |
| |
| protected void configureModule(final JavaParameters parameters, final RunConfigurationModule configurationModule, final String mainClassName) |
| throws CantRunException { |
| int classPathType = JavaParametersUtil.getClasspathType(configurationModule, mainClassName, true); |
| JavaParametersUtil.configureModule(configurationModule, parameters, classPathType, |
| myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null); |
| } |
| |
| private static final TestObject NOT_CONFIGURED = new TestObject(null, null) { |
| @Override |
| public RefactoringElementListener getListener(final PsiElement element, final JUnitConfiguration configuration) { |
| return null; |
| } |
| |
| @Override |
| public String suggestActionName() { |
| throw new RuntimeException(String.valueOf(myConfiguration)); |
| } |
| |
| @Override |
| public boolean isConfiguredByElement(final JUnitConfiguration configuration, |
| PsiClass testClass, |
| PsiMethod testMethod, |
| PsiPackage testPackage, |
| PsiDirectory testDir) { |
| return false; |
| } |
| |
| @Override |
| public void checkConfiguration() throws RuntimeConfigurationException { |
| throw new RuntimeConfigurationError(MESSAGE); |
| } |
| |
| @Override |
| public JavaParameters getJavaParameters() throws ExecutionException { |
| throw new ExecutionException(MESSAGE); |
| } |
| |
| @Override |
| protected void initialize() throws ExecutionException { |
| throw new ExecutionException(MESSAGE); |
| } |
| }; |
| |
| public void checkConfiguration() throws RuntimeConfigurationException{ |
| JavaParametersUtil.checkAlternativeJRE(myConfiguration); |
| ProgramParametersUtil.checkWorkingDirectoryExist(myConfiguration, myConfiguration.getProject(), myConfiguration.getConfigurationModule().getModule()); |
| } |
| |
| public SourceScope getSourceScope() { |
| return SourceScope.modulesWithDependencies(myConfiguration.getModules()); |
| } |
| |
| protected void initialize() throws ExecutionException { |
| String parameters = myConfiguration.getProgramParameters(); |
| myConfiguration.getPersistentData().setProgramParameters(null); |
| try { |
| JavaParametersUtil.configureConfiguration(myJavaParameters, myConfiguration); |
| } |
| finally { |
| myConfiguration.getPersistentData().setProgramParameters(parameters); |
| } |
| myJavaParameters.setMainClass(JUnitConfiguration.JUNIT_START_CLASS); |
| final Module module = myConfiguration.getConfigurationModule().getModule(); |
| if (myJavaParameters.getJdk() == null){ |
| myJavaParameters.setJdk(module != null |
| ? ModuleRootManager.getInstance(module).getSdk() |
| : ProjectRootManager.getInstance(myEnvironment.getProject()).getProjectSdk()); |
| } |
| |
| configureAdditionalClasspath(myJavaParameters); |
| myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION); |
| if (!StringUtil.isEmptyOrSpaces(parameters)) { |
| myJavaParameters.getProgramParametersList().add("@name" + parameters); |
| } |
| for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) { |
| ext.updateJavaParameters(myConfiguration, myJavaParameters, getRunnerSettings()); |
| } |
| |
| final Object[] listeners = Extensions.getExtensions(IDEAJUnitListener.EP_NAME); |
| final StringBuilder buf = new StringBuilder(); |
| for (final Object listener : listeners) { |
| boolean enabled = true; |
| for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) { |
| if (ext.isListenerDisabled(myConfiguration, listener, getRunnerSettings())) { |
| enabled = false; |
| break; |
| } |
| } |
| if (enabled) { |
| final Class classListener = listener.getClass(); |
| buf.append(classListener.getName()).append("\n"); |
| myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(classListener)); |
| } |
| } |
| if (buf.length() > 0) { |
| try { |
| myListenersFile = FileUtil.createTempFile("junit_listeners_", ""); |
| myListenersFile.deleteOnExit(); |
| myJavaParameters.getProgramParametersList().add("@@" + myListenersFile.getPath()); |
| FileUtil.writeToFile(myListenersFile, buf.toString().getBytes(CharsetToolkit.UTF8_CHARSET)); |
| } |
| catch (IOException e) { |
| LOG.error(e); |
| } |
| } |
| } |
| |
| private void configureAdditionalClasspath(JavaParameters javaParameters) { |
| javaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath()); |
| javaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class)); |
| if (Registry.is("junit_sm_runner")) { |
| javaParameters.getClassPath().add(PathUtil.getJarPathForClass(ServiceMessageTypes.class)); |
| } |
| } |
| |
| @Override |
| public JavaParameters getJavaParameters() throws ExecutionException { |
| if (myJavaParameters == null) { |
| myJavaParameters = new JavaParameters(); |
| initialize(); |
| final Module module = myConfiguration.getConfigurationModule().getModule(); |
| final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER); |
| for (Object patcher : patchers) { |
| ((JUnitPatcher)patcher).patchJavaParameters(module, myJavaParameters); |
| } |
| } |
| return myJavaParameters; |
| } |
| |
| @Override |
| public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException { |
| final boolean smRunner = Registry.is("junit_sm_runner"); |
| if (smRunner) { |
| myJavaParameters.getVMParametersList().add("-Didea.junit.sm_runner"); |
| } |
| final JUnitProcessHandler handler = createHandler(executor); |
| final RunnerSettings runnerSettings = getRunnerSettings(); |
| JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings); |
| if (smRunner) { |
| return useSmRunner(executor, handler); |
| } |
| final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo()); |
| final JUnitConsoleProperties consoleProperties = new JUnitConsoleProperties(myConfiguration, executor); |
| final JUnitTreeConsoleView consoleView = new JUnitTreeConsoleView(consoleProperties, myEnvironment, unboundOutputRoot); |
| consoleView.initUI(); |
| consoleView.attachToProcess(handler); |
| unboundOutputRoot.setPrinter(consoleView.getPrinter()); |
| Disposer.register(consoleView, unboundOutputRoot); |
| final TestsPacketsReceiver packetsReceiver = new TestsPacketsReceiver(consoleView, unboundOutputRoot) { |
| @Override |
| public synchronized void notifyStart(TestProxy root) { |
| if (!isRunning()) return; |
| super.notifyStart(root); |
| unboundOutputRoot.addChild(root); |
| if (myConfiguration.isSaveOutputToFile()) { |
| unboundOutputRoot.setOutputFilePath(myConfiguration.getOutputFilePath()); |
| } |
| final JUnitRunningModel model = getModel(); |
| if (model != null) { |
| handler.getOut().setDispatchListener(model.getNotifier()); |
| Disposer.register(model, new Disposable() { |
| @Override |
| public void dispose() { |
| handler.getOut().setDispatchListener(DispatchListener.DEAF); |
| } |
| }); |
| consoleView.attachToModel(model); |
| } |
| } |
| }; |
| Disposer.register(consoleView, packetsReceiver); |
| |
| final DeferredActionsQueue queue = new DeferredActionsQueueImpl(); |
| handler.getOut().setPacketDispatcher(packetsReceiver, queue); |
| handler.getErr().setPacketDispatcher(packetsReceiver, queue); |
| |
| handler.addProcessListener(new ProcessAdapter() { |
| private boolean myStarted = false; |
| @Override |
| public void startNotified(ProcessEvent event) { |
| myStarted = true; |
| } |
| |
| @Override |
| public void processTerminated(ProcessEvent event) { |
| handler.removeProcessListener(this); |
| if (myTempFile != null) { |
| FileUtil.delete(myTempFile); |
| } |
| if (myListenersFile != null) { |
| FileUtil.delete(myListenersFile); |
| } |
| final Runnable runnable = new Runnable() { |
| @Override |
| public void run() { |
| unboundOutputRoot.flush(); |
| packetsReceiver.checkTerminated(); |
| final JUnitRunningModel model = packetsReceiver.getModel(); |
| notifyByBalloon(model, myStarted, consoleProperties); |
| } |
| }; |
| handler.getOut().addRequest(runnable, queue); |
| } |
| |
| @Override |
| public void onTextAvailable(final ProcessEvent event, final Key outputType) { |
| final String text = event.getText(); |
| final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType); |
| final Printable printable = new Printable() { |
| @Override |
| public void printOn(final Printer printer) { |
| printer.print(text, consoleViewType); |
| } |
| }; |
| final Extractor extractor; |
| if (consoleViewType == ConsoleViewContentType.ERROR_OUTPUT || |
| consoleViewType == ConsoleViewContentType.SYSTEM_OUTPUT) { |
| extractor = handler.getErr(); |
| } |
| else { |
| extractor = handler.getOut(); |
| } |
| extractor.getEventsDispatcher().processOutput(printable); |
| } |
| }); |
| |
| final RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView, consoleProperties); |
| rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() { |
| @Override |
| public TestFrameworkRunningModel get() { |
| return packetsReceiver.getModel(); |
| } |
| }); |
| |
| final DefaultExecutionResult result = new DefaultExecutionResult(consoleView, handler); |
| result.setRestartActions(rerunFailedTestsAction); |
| return result; |
| } |
| |
| private ExecutionResult useSmRunner(Executor executor, JUnitProcessHandler handler) { |
| TestConsoleProperties testConsoleProperties = new SMTRunnerConsoleProperties(myConfiguration, JUNIT_TEST_FRAMEWORK_NAME, executor); |
| testConsoleProperties.setIfUndefined(TestConsoleProperties.HIDE_PASSED_TESTS, false); |
| |
| final ConsoleView consoleView = SMTestRunnerConnectionUtil.createConsoleWithCustomLocator( |
| JUNIT_TEST_FRAMEWORK_NAME, |
| testConsoleProperties, |
| myEnvironment, null); |
| consoleView.attachToProcess(handler); |
| |
| RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView, testConsoleProperties); |
| rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() { |
| @Override |
| public TestFrameworkRunningModel get() { |
| return ((SMTRunnerConsoleView)consoleView).getResultsViewer(); |
| } |
| }); |
| |
| final DefaultExecutionResult result = new DefaultExecutionResult(consoleView, handler); |
| result.setRestartActions(rerunFailedTestsAction); |
| return result; |
| } |
| |
| protected void notifyByBalloon(JUnitRunningModel model, boolean started, JUnitConsoleProperties consoleProperties) { |
| String comment; |
| if (model != null) { |
| final CompletionEvent done = model.getProgress().getDone(); |
| comment = done != null ? done.getComment() : null; |
| } |
| else { |
| comment = null; |
| } |
| TestsUIUtil.notifyByBalloon(myEnvironment.getProject(), started, model != null ? model.getRoot() : null, consoleProperties, comment); |
| } |
| |
| protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException { |
| appendForkInfo(executor); |
| return JUnitProcessHandler.runCommandLine(CommandLineBuilder.createFromJavaParameters(myJavaParameters, myEnvironment.getProject(), true)); |
| } |
| |
| private boolean forkPerModule() { |
| final String workingDirectory = myConfiguration.getWorkingDirectory(); |
| return JUnitConfiguration.TEST_PACKAGE.equals(myConfiguration.getPersistentData().TEST_OBJECT) && |
| myConfiguration.getPersistentData().getScope() != TestSearchScope.SINGLE_MODULE && |
| ("$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$").equals(workingDirectory); |
| } |
| |
| private void appendForkInfo(Executor executor) throws ExecutionException { |
| final String forkMode = myConfiguration.getForkMode(); |
| if (Comparing.strEqual(forkMode, "none")) { |
| if (forkPerModule()) { |
| if (getRunnerSettings() != null) { |
| final String actionName = UIUtil.removeMnemonic(executor.getStartActionText()); |
| throw new CantRunException("'" + actionName + "' is disabled when per-module working directory is configured.<br/>" + |
| "Please specify single working directory, or change test scope to single module."); |
| } |
| } else { |
| return; |
| } |
| } else if (getRunnerSettings() != null) { |
| final String actionName = executor.getActionName(); |
| throw new CantRunException(actionName + " is disabled in fork mode.<br/>Please change fork mode to <none> to " + actionName.toLowerCase(Locale.ENGLISH) + "."); |
| } |
| |
| final JavaParameters javaParameters = getJavaParameters(); |
| final Sdk jdk = javaParameters.getJdk(); |
| if (jdk == null) { |
| throw new ExecutionException(ExecutionBundle.message("run.configuration.error.no.jdk.specified")); |
| } |
| |
| try { |
| final File tempFile = FileUtil.createTempFile("command.line", "", true); |
| final PrintWriter writer = new PrintWriter(tempFile, CharsetToolkit.UTF8); |
| try { |
| writer.println(((JavaSdkType)jdk.getSdkType()).getVMExecutablePath(jdk)); |
| for (String vmParameter : javaParameters.getVMParametersList().getList()) { |
| writer.println(vmParameter); |
| } |
| writer.println("-classpath"); |
| writer.println(javaParameters.getClassPath().getPathsString()); |
| } |
| finally { |
| writer.close(); |
| } |
| |
| myJavaParameters.getProgramParametersList().add("@@@" + forkMode + ',' + tempFile.getAbsolutePath()); |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| } |
| |
| protected <T> void addClassesListToJavaParameters(Collection<? extends T> elements, Function<T, String> nameFunction, String packageName, |
| boolean createTempFile, |
| boolean junit4) throws CantRunException { |
| try { |
| if (createTempFile) { |
| createTempFiles(); |
| } |
| |
| final Map<Module, List<String>> perModule = forkPerModule() ? new TreeMap<Module, List<String>>(new Comparator<Module>() { |
| @Override |
| public int compare(Module o1, Module o2) { |
| return StringUtil.compare(o1.getName(), o2.getName(), true); |
| } |
| }) : null; |
| |
| final List<String> testNames = new ArrayList<String>(); |
| |
| for (final T element : elements) { |
| final String name = nameFunction.fun(element); |
| if (name == null) { |
| LOG.error("invalid element " + element); |
| return; |
| } |
| |
| if (perModule != null && element instanceof PsiElement) { |
| final Module module = ModuleUtilCore.findModuleForPsiElement((PsiElement)element); |
| if (module != null) { |
| List<String> list = perModule.get(module); |
| if (list == null) { |
| list = new ArrayList<String>(); |
| perModule.put(module, list); |
| } |
| list.add(name); |
| } |
| } |
| else { |
| testNames.add(name); |
| } |
| } |
| if (perModule != null) { |
| for (List<String> perModuleClasses : perModule.values()) { |
| Collections.sort(perModuleClasses); |
| testNames.addAll(perModuleClasses); |
| } |
| } |
| else { |
| Collections.sort(testNames); //sort tests in FQN order |
| } |
| |
| final JUnitConfiguration.Data data = myConfiguration.getPersistentData(); |
| final String category = data.TEST_OBJECT == JUnitConfiguration.TEST_CATEGORY ? data.getCategory() : ""; |
| JUnitStarter.printClassesList(testNames, packageName, category, myTempFile); |
| |
| if (perModule != null && perModule.size() > 1) { |
| final PrintWriter wWriter = new PrintWriter(myWorkingDirsFile, CharsetToolkit.UTF8); |
| try { |
| wWriter.println(packageName); |
| for (Module module : perModule.keySet()) { |
| final String moduleDir = PathMacroUtil.getModuleDir(module.getModuleFilePath()); |
| wWriter.println(moduleDir); |
| |
| final JavaParameters parameters = new JavaParameters(); |
| JavaParametersUtil.configureModule(module, parameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS, |
| myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null); |
| configureAdditionalClasspath(parameters); |
| wWriter.println(parameters.getClassPath().getPathsString()); |
| final List<String> classNames = perModule.get(module); |
| wWriter.println(classNames.size()); |
| for (String className : classNames) { |
| wWriter.println(className); |
| } |
| } |
| } finally { |
| wWriter.close(); |
| } |
| } |
| } |
| catch (IOException e) { |
| LOG.error(e); |
| } |
| } |
| |
| protected void createTempFiles() throws IOException { |
| myTempFile = FileUtil.createTempFile("idea_junit", ".tmp"); |
| myTempFile.deleteOnExit(); |
| myJavaParameters.getProgramParametersList().add("@" + myTempFile.getAbsolutePath()); |
| myWorkingDirsFile = FileUtil.createTempFile("idea_working_dirs_junit", ".tmp"); |
| myWorkingDirsFile.deleteOnExit(); |
| myJavaParameters.getProgramParametersList().add("@w@" + myWorkingDirsFile.getAbsolutePath()); |
| } |
| |
| public void clear() { |
| myJavaParameters = null; |
| } |
| } |