PageRenderTime 25ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/netbeans-7.3/php.project/src/org/netbeans/modules/php/project/ui/actions/support/FileRunner.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 346 lines | 255 code | 38 blank | 53 comment | 22 complexity | f767ca2941c4837540f6a6ef01d2dd49 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * If you wish your version of this file to be governed by only the CDDL
  28. * or only the GPL Version 2, indicate your decision by adding
  29. * "[Contributor] elects to include this software in this distribution
  30. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  31. * single choice of license, a recipient has the option to distribute
  32. * your version of this file under either the CDDL, the GPL Version 2 or
  33. * to extend the choice of license to its licensees as provided above.
  34. * However, if you add GPL Version 2 code and therefore, elected the GPL
  35. * Version 2 license, then the option applies only if the new code is
  36. * made subject to such option by the copyright holder.
  37. *
  38. * Contributor(s):
  39. *
  40. * Portions Copyrighted 2012 Sun Microsystems, Inc.
  41. */
  42. package org.netbeans.modules.php.project.ui.actions.support;
  43. import java.awt.EventQueue;
  44. import java.io.File;
  45. import java.io.IOException;
  46. import java.net.MalformedURLException;
  47. import java.nio.charset.Charset;
  48. import java.util.ArrayList;
  49. import java.util.Arrays;
  50. import java.util.Collections;
  51. import java.util.List;
  52. import java.util.concurrent.Callable;
  53. import java.util.concurrent.Future;
  54. import java.util.logging.Level;
  55. import java.util.logging.Logger;
  56. import java.util.regex.Pattern;
  57. import org.netbeans.api.extexecution.ExecutionDescriptor;
  58. import org.netbeans.api.extexecution.print.LineConvertor;
  59. import org.netbeans.api.extexecution.print.LineConvertors;
  60. import org.netbeans.api.project.Project;
  61. import org.netbeans.api.queries.FileEncodingQuery;
  62. import org.netbeans.modules.php.api.executable.PhpExecutable;
  63. import org.netbeans.modules.php.api.executable.PhpInterpreter;
  64. import org.netbeans.modules.php.api.util.Pair;
  65. import org.netbeans.modules.php.api.util.StringUtils;
  66. import org.netbeans.modules.php.api.util.UiUtils;
  67. import org.netbeans.modules.php.project.PhpProject;
  68. import org.netbeans.modules.php.project.ProjectPropertiesSupport;
  69. import org.netbeans.modules.php.project.spi.XDebugStarter;
  70. import org.netbeans.modules.php.project.ui.options.PhpOptions;
  71. import org.netbeans.modules.php.project.util.PhpProjectUtils;
  72. import org.openide.awt.HtmlBrowser;
  73. import org.openide.filesystems.FileObject;
  74. import org.openide.filesystems.FileUtil;
  75. import org.openide.util.Cancellable;
  76. import org.openide.util.Lookup;
  77. import org.openide.util.NbBundle;
  78. import org.openide.util.RequestProcessor;
  79. import org.openide.util.Utilities;
  80. import org.openide.windows.InputOutput;
  81. /**
  82. * Run or debug a file.
  83. * <p>
  84. * This class is thread safe.
  85. */
  86. public final class FileRunner {
  87. static final Logger LOGGER = Logger.getLogger(FileRunner.class.getName());
  88. private static final RequestProcessor RP = new RequestProcessor(FileRunner.class);
  89. private static final ExecutionDescriptor.LineConvertorFactory PHP_LINE_CONVERTOR_FACTORY = new PhpLineConvertorFactory();
  90. // for debugger, let's treat all the files withour project under one dbg session
  91. private static final Project DUMMY_PROJECT = new DummyProject();
  92. final File file;
  93. // @GuardedBy("this")
  94. PhpProject project;
  95. volatile String command;
  96. volatile String phpArgs;
  97. volatile String fileArgs;
  98. volatile String workDir;
  99. volatile boolean debug = false;
  100. public FileRunner(File file) {
  101. this.file = file;
  102. }
  103. public synchronized FileRunner project(PhpProject project) {
  104. this.project = project;
  105. return this;
  106. }
  107. public FileRunner command(String command) {
  108. this.command = command;
  109. return this;
  110. }
  111. public FileRunner phpArgs(String phpArgs) {
  112. this.phpArgs = phpArgs;
  113. return this;
  114. }
  115. public FileRunner fileArgs(String fileArgs) {
  116. this.fileArgs = fileArgs;
  117. return this;
  118. }
  119. public FileRunner workDir(String workDir) {
  120. this.workDir = workDir;
  121. return this;
  122. }
  123. @NbBundle.Messages({
  124. "# {0} - project or file name",
  125. "FileRunner.run.displayName={0} (run)"
  126. })
  127. public void run() {
  128. RP.post(new Runnable() {
  129. @Override
  130. public void run() {
  131. try {
  132. getRunCallable(Bundle.FileRunner_run_displayName(getDisplayName()), false).call();
  133. } catch (Exception ex) {
  134. LOGGER.log(Level.WARNING, null, ex);
  135. }
  136. }
  137. });
  138. }
  139. public void debug() {
  140. RP.post(new Runnable() {
  141. @Override
  142. public void run() {
  143. try {
  144. debugInternal();
  145. } catch (Exception ex) {
  146. LOGGER.log(Level.WARNING, null, ex);
  147. }
  148. }
  149. });
  150. }
  151. Callable<Cancellable> getRunCallable(final String displayName, final boolean debug) {
  152. return new Callable<Cancellable>() {
  153. @Override
  154. public Cancellable call() {
  155. assert !EventQueue.isDispatchThread();
  156. PhpExecutable executable = new PhpExecutable(command);
  157. if (StringUtils.hasText(workDir)) {
  158. executable.workDir(new File(workDir));
  159. } else {
  160. executable.workDir(file.getParentFile());
  161. }
  162. // open in browser or editor?
  163. Runnable postExecution = null;
  164. if (getRedirectToFile()) {
  165. File tmpFile = createTempFile();
  166. if (tmpFile != null) {
  167. executable.fileOutput(tmpFile, false);
  168. postExecution = new PostExecution(tmpFile);
  169. }
  170. }
  171. executable
  172. .displayName(displayName)
  173. .viaAutodetection(false)
  174. .viaPhpInterpreter(false)
  175. .additionalParameters(getParams());
  176. if (debug) {
  177. executable
  178. .environmentVariables(Collections.singletonMap("XDEBUG_CONFIG", "idekey=" + PhpOptions.getInstance().getDebuggerSessionId())); // NOI18N
  179. }
  180. // run!
  181. final Future<Integer> result = executable
  182. .run(getDescriptor(postExecution, !debug));
  183. return new Cancellable() {
  184. @Override
  185. public boolean cancel() {
  186. return result.cancel(true);
  187. }
  188. };
  189. }
  190. };
  191. }
  192. @NbBundle.Messages({
  193. "# {0} - project or file name",
  194. "FileRunner.debug.displayName={0} (debug)"
  195. })
  196. private void debugInternal() {
  197. XDebugStarter dbgStarter = XDebugStarterFactory.getInstance();
  198. assert dbgStarter != null;
  199. if (dbgStarter.isAlreadyRunning()) {
  200. if (CommandUtils.warnNoMoreDebugSession()) {
  201. dbgStarter.stop();
  202. debugInternal();
  203. }
  204. } else {
  205. Callable<Cancellable> callable = getRunCallable(Bundle.FileRunner_debug_displayName(getDisplayName()), true);
  206. XDebugStarter.Properties props = XDebugStarter.Properties.create(
  207. FileUtil.toFileObject(file),
  208. true,
  209. // #209682 - "run as script" always from project files
  210. Collections.<Pair<String, String>>emptyList(),
  211. null, // no debug proxy for files (valid only for server urls)
  212. getEncoding());
  213. dbgStarter.start(project != null ? project : DUMMY_PROJECT, callable, props);
  214. }
  215. }
  216. synchronized String getDisplayName() {
  217. return project != null ? project.getName() : file.getName();
  218. }
  219. private List<String> getParams() {
  220. List<String> params = new ArrayList<String>();
  221. if (StringUtils.hasText(phpArgs)) {
  222. params.addAll(Arrays.asList(Utilities.parseParameters(phpArgs)));
  223. }
  224. params.add(file.getAbsolutePath());
  225. if (StringUtils.hasText(fileArgs)) {
  226. params.addAll(Arrays.asList(Utilities.parseParameters(fileArgs)));
  227. }
  228. return params;
  229. }
  230. ExecutionDescriptor getDescriptor(Runnable postExecution, boolean controllable) {
  231. ExecutionDescriptor descriptor = PhpExecutable.DEFAULT_EXECUTION_DESCRIPTOR
  232. .charset(Charset.forName(getEncoding()))
  233. .controllable(controllable)
  234. .optionsPath(UiUtils.OPTIONS_PATH)
  235. .outConvertorFactory(PHP_LINE_CONVERTOR_FACTORY);
  236. if (!getPhpOptions().isOpenResultInOutputWindow()) {
  237. descriptor = descriptor.inputOutput(InputOutput.NULL)
  238. .frontWindow(false)
  239. .frontWindowOnError(false);
  240. }
  241. if (postExecution != null) {
  242. descriptor = descriptor.postExecution(postExecution);
  243. }
  244. return descriptor;
  245. }
  246. private String getEncoding() {
  247. return project != null ? ProjectPropertiesSupport.getEncoding(project) : FileEncodingQuery.getDefaultEncoding().name();
  248. }
  249. boolean getRedirectToFile() {
  250. return getPhpOptions().isOpenResultInBrowser() || getPhpOptions().isOpenResultInEditor();
  251. }
  252. File createTempFile() {
  253. try {
  254. File tmpFile = File.createTempFile(file.getName(), ".html"); // NOI18N
  255. tmpFile.deleteOnExit();
  256. return tmpFile;
  257. } catch (IOException ex) {
  258. LOGGER.log(Level.WARNING, null, ex);
  259. }
  260. return null;
  261. }
  262. private PhpOptions getPhpOptions() {
  263. return PhpOptions.getInstance();
  264. }
  265. //~ Inner classes
  266. private static final class PhpLineConvertorFactory implements ExecutionDescriptor.LineConvertorFactory {
  267. @Override
  268. public LineConvertor newLineConvertor() {
  269. LineConvertor[] lineConvertors = new LineConvertor[PhpInterpreter.LINE_PATTERNS.length];
  270. int i = 0;
  271. for (Pattern linePattern : PhpInterpreter.LINE_PATTERNS) {
  272. lineConvertors[i++] = LineConvertors.filePattern(null, linePattern, null, 1, 2);
  273. }
  274. return LineConvertors.proxy(lineConvertors);
  275. }
  276. }
  277. private static final class PostExecution implements Runnable {
  278. private final File tmpFile;
  279. public PostExecution(File tmpFile) {
  280. this.tmpFile = tmpFile;
  281. }
  282. @Override
  283. public void run() {
  284. PhpOptions options = PhpOptions.getInstance();
  285. try {
  286. if (options.isOpenResultInBrowser()) {
  287. HtmlBrowser.URLDisplayer.getDefault().showURL(Utilities.toURI(tmpFile).toURL());
  288. }
  289. } catch (MalformedURLException ex) {
  290. LOGGER.log(Level.WARNING, null, ex);
  291. }
  292. if (options.isOpenResultInEditor()) {
  293. PhpProjectUtils.openFile(tmpFile);
  294. }
  295. }
  296. }
  297. // needed for php debugger, used as a key in session map
  298. private static final class DummyProject implements Project {
  299. @Override
  300. public FileObject getProjectDirectory() {
  301. throw new UnsupportedOperationException("Not supported yet.");
  302. }
  303. @Override
  304. public Lookup getLookup() {
  305. return Lookup.EMPTY;
  306. }
  307. }
  308. }