001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * Portions Copyrighted 2007 Sun Microsystems, Inc.
027: */
028: package org.netbeans.modules.php.project;
029:
030: import java.io.BufferedReader;
031: import java.io.File;
032: import java.io.FileInputStream;
033: import java.io.FileWriter;
034: import java.io.IOException;
035: import java.io.InputStreamReader;
036: import java.net.MalformedURLException;
037: import java.net.URL;
038: import java.util.ArrayList;
039: import java.util.List;
040: import java.util.logging.Level;
041: import java.util.logging.Logger;
042: import org.netbeans.api.progress.ProgressHandle;
043: import org.netbeans.api.progress.ProgressHandleFactory;
044: import org.netbeans.api.project.Project;
045: import org.netbeans.api.project.ProjectManager;
046: import org.netbeans.modules.php.project.options.CommandLinePreferences;
047: import org.netbeans.modules.php.project.options.ProjectActionsPreferences;
048: import org.netbeans.modules.php.project.ui.actions.SystemPackageFinder;
049: import org.netbeans.modules.php.rt.utils.PhpCommandUtils;
050: import org.openide.awt.HtmlBrowser;
051: import org.openide.filesystems.FileObject;
052: import org.openide.filesystems.FileUtil;
053: import org.openide.util.Cancellable;
054: import org.openide.util.Mutex;
055: import org.openide.util.NbBundle;
056: import org.openide.windows.IOProvider;
057: import org.openide.windows.InputOutput;
058: import org.openide.windows.OutputWriter;
059:
060: /**
061: *
062: * @author avk
063: */
064: public class RunLocalCommand extends AbstractCommand implements
065: Cancellable {
066:
067: // bundle keys
068: private static final String LBL_MALFORMED_URL = "LBL_MalformedUrl"; // NOI18N
069: private static final String LBL_SCRIPT_NOT_SAVED_WARN = "LBL_ScriptNotSavedWarn"; // NOI18N
070: private static final String LBL_EXEC_CANCELLED_MSG = "LBL_ScriptExecCancelledMsg"; // NOI18N
071: private static final String LBL_EXEC_ERROR_MSG = "LBL_ScriptExecErrorMsg"; // NOI18N
072: private static final String LBL_EXEC_EXIT_VALUE_MSG = "LBL_ScriptExecExitValueMsg"; // NOI18N
073: private static final String LBL_PHP_INTERPRETER_MSG = "LBL_PhpInterpreterMsg"; // NOI18N
074: private static final String LBL_CAN_NOT_FIND_INTERPRETER = "LBL_CantFindInterpreter"; // NOI18N
075: private static final String LBL_NO_INDEX_FILE = "LBL_NoIndexFile"; // NOI18N
076: private static final String LBL_OUT_TAB_TITLE = "LBL_RunLocalOutputTabTitle"; // NOI18N
077:
078: private static final String LF = "\n"; // NOI18N
079: //
080: static final int RUNTIME_EXIT_NORMAL = 0;
081:
082: static final String PROPERTY_SYSTEM_OS_NAME = "os.name"; // NOI18N
083:
084: static final String PROPERTY_SYSTEM_TMP_DIR = "java.io.tmpdir"; // NOI18N
085:
086: public static final String LBL_INTERPRETED_PHP_EXT = "LBL_InterpretedPhpExt"; // NOI18N
087:
088: public static final String RUN_LOCAL_ACTION = "run.local"; // NOI18N
089:
090: private static final String RUN_LOCAL_LABEL = PhpActionProvider.LBL_RUN_LOCAL;
091:
092: private static final String DEFAULT_INDEX_NAME = "index"; // NOI18N
093:
094: private static final String DEFAULT_INDEX_EXT = "php"; // NOI18N
095:
096: private static final String DEFAULT_INDEX = DEFAULT_INDEX_NAME
097: + "." + DEFAULT_INDEX_EXT; // NOI18N
098:
099: private static Logger LOGGER = Logger
100: .getLogger(RunLocalCommand.class.getName());
101:
102: public RunLocalCommand(Project project) {
103: super (project);
104: }
105:
106: public String getId() {
107: return RUN_LOCAL_ACTION;
108: }
109:
110: public String getLabel() {
111: return NbBundle.getMessage(RunLocalCommand.class,
112: RUN_LOCAL_LABEL);
113: }
114:
115: @Override
116: public boolean isEnabled() {
117: return myIsEnabled;
118: }
119:
120: public boolean cancel() {
121: isCancelled = true;
122: if (myProcess != null) {
123: myProcess.destroy();
124: }
125: notifyMsg(LBL_EXEC_CANCELLED_MSG, this .getClass(), getLabel());
126: return true;
127: }
128:
129: public void run() {
130: refresh();
131: ProgressHandle progress = ProgressHandleFactory.createHandle(
132: getLabel(), this );
133: progress.start();
134: try {
135: saveProject();
136: String php = getPhpInterpreter();
137: //saveScripts();
138: String[] scripts = getScriptsToRun();
139: if (scripts.length == 0) {
140: notifyMsg(LBL_NO_INDEX_FILE, DEFAULT_INDEX);
141: return;
142: }
143:
144: if (php != null) {
145: for (String script : scripts) {
146: if (!isCancelled) {
147:
148: String title = NbBundle.getMessage(
149: RunLocalCommand.class,
150: LBL_OUT_TAB_TITLE, getLabel(), script);
151: setOutputTabTitle(title);
152:
153: File outFile = runScript(php, script);
154: if (outFile != null) {
155: openInOutput(outFile);
156: openFileInBrowser(outFile);
157: }
158: }
159: }
160: } else {
161: notifyMsg(LBL_CAN_NOT_FIND_INTERPRETER, this .getClass());
162: }
163: } finally {
164: progress.finish();
165: }
166: }
167:
168: @Override
169: protected void refresh() {
170: super .refresh();
171: isCancelled = false;
172: setOutputTabTitle(super .getOutputTabTitle());
173: }
174:
175: @Override
176: protected String getOutputTabTitle() {
177: return myOutputTabTitle;
178: }
179:
180: protected void setOutputTabTitle(String title) {
181: myOutputTabTitle = title;
182: }
183:
184: protected boolean openFileInBrowser(File file) {
185: if (!isOpenInBrowser()) {
186: return true;
187: }
188: if (isCancelled) {
189: return false;
190: }
191:
192: URL url;
193: try {
194: url = file.toURL();
195: } catch (MalformedURLException e) {
196: notifyMsg(LBL_MALFORMED_URL, file.getPath());
197: return false;
198: }
199: if (isCancelled) {
200: return false;
201: }
202: HtmlBrowser.URLDisplayer.getDefault().showURL(url);
203: return true;
204: }
205:
206: protected boolean openInOutput(File file) {
207: boolean success = true;
208: if (isCancelled) {
209: return false;
210: }
211: if (!isPrintToOutput()) {
212: return success;
213: }
214:
215: BufferedReader reader = null;
216: OutputWriter outputWriter = null;
217:
218: try {
219: outputWriter = getOutputWriter();
220: reader = new BufferedReader(new InputStreamReader(
221: new FileInputStream(file)));
222:
223: String line;
224: while ((line = reader.readLine()) != null) {
225: outputWriter.println(line);
226: outputWriter.flush();
227: }
228: } catch (IOException ex) {
229: outputWriter.println(ex.getMessage());
230: outputWriter.flush();
231: success = false;
232: } finally {
233: if (outputWriter != null) {
234: outputWriter.close();
235: }
236: if (reader != null) {
237: try {
238: reader.close();
239: } catch (IOException ex) {
240: // do nothing
241: }
242: }
243: }
244:
245: return success;
246: }
247:
248: /**
249: * returns file with result output.
250: * can be null in case of any errors during script execution.
251: */
252: private File runScript(String php, String script) {
253: boolean success = true;
254:
255: notifyMsg(LBL_PHP_INTERPRETER_MSG, this .getClass(), php);
256:
257: File tmpFile = null;
258: FileWriter tmpOutput = null;
259: BufferedReader reader = null;
260: BufferedReader errReader = null;
261: if (isCancelled) {
262: return null;
263: }
264: try {
265: String[] command = new String[] { php, script };
266: Runtime runtime = Runtime.getRuntime();
267: myProcess = runtime.exec(command); // NOI18N
268:
269: tmpFile = getTmpFile(script);
270: tmpOutput = new FileWriter(tmpFile);
271:
272: reader = new BufferedReader(new InputStreamReader(myProcess
273: .getInputStream()));
274: errReader = new BufferedReader(new InputStreamReader(
275: myProcess.getErrorStream()));
276:
277: String line;
278: while ((line = reader.readLine()) != null) {
279: tmpOutput.write(line + LF);
280: }
281:
282: while ((line = errReader.readLine()) != null) {
283: notifyMsg(LBL_EXEC_ERROR_MSG, line);
284: }
285: try {
286: if (myProcess.waitFor() != 0) {
287: notifyMsg(LBL_EXEC_EXIT_VALUE_MSG, myProcess
288: .exitValue());
289: }
290: } catch (InterruptedException e) {
291: notifyMsg(LBL_EXEC_ERROR_MSG, e.getMessage());
292: }
293:
294: } catch (IOException ex) {
295: notifyMsg(LBL_EXEC_ERROR_MSG, ex.getMessage());
296: success = false;
297: } finally {
298: if (tmpOutput != null) {
299: try {
300: tmpOutput.close();
301: } catch (IOException ex) {
302: notifyMsg(LBL_EXEC_ERROR_MSG, ex.getMessage());
303: success = false;
304: }
305: }
306: if (reader != null) {
307: try {
308: reader.close();
309: } catch (IOException ex) {
310: success = false;
311: }
312: }
313: if (errReader != null) {
314: try {
315: errReader.close();
316: } catch (IOException ex) {
317: LOGGER.log(Level.WARNING, null, ex);
318: }
319: }
320: }
321:
322: if (success && !isCancelled) {
323: return tmpFile;
324: } else {
325: return null;
326: }
327: }
328:
329: private OutputWriter getOutputWriter() {
330: InputOutput io = IOProvider.getDefault().getIO(
331: getOutputTabTitle(), false);
332: io.select();
333: OutputWriter writer = io.getOut();
334: return writer;
335: }
336:
337: private String getPhpInterpreter() {
338: String path = ProjectManager.mutex().readAccess(
339: new Mutex.Action<String>() {
340:
341: public String run() {
342: String commandPath = getAntProjectHelper()
343: .getStandardPropertyEvaluator()
344: .getProperty(PhpProject.COMMAND_PATH);
345: return commandPath;
346: }
347: });
348: if (path == null) {
349: path = CommandLinePreferences.getInstance()
350: .getPhpInterpreter();
351: }
352: if (path != null) {
353: path = path.trim();
354: }
355: if (path != null && path.length() == 0) {
356: path = null;
357: }
358: return path;
359: }
360:
361: private void saveProject() {
362: PhpCommandUtils.saveAll();
363: }
364:
365: private void saveScripts() {
366: if (getFileObjects() != null) {
367: for (FileObject fileObject : getFileObjects()) {
368: saveFile(fileObject);
369: }
370: }
371: }
372:
373: private String[] getScriptsToRun() {
374: List<String> scripts = new ArrayList<String>();
375: if (getFileObjects() != null) {
376: for (FileObject fileObject : getFileObjects()) {
377:
378: String path = getScriptFromFO(fileObject);
379: if (path != null) {
380: scripts.add(path);
381: }
382: }
383: }
384: return scripts.toArray(new String[] {});
385: }
386:
387: private String getScriptFromFO(FileObject fileObject) {
388: File file = fileObject.isFolder() ? getDefaultIndex(fileObject)
389: : FileUtil.toFile(fileObject);
390:
391: if (file != null) {
392: return file.getAbsolutePath();
393: }
394: return null;
395: }
396:
397: private void saveFile(FileObject fromObject) {
398: try {
399: PhpCommandUtils.saveFile(fromObject);
400: } catch (IOException ex) {
401: notifyMsg(LBL_SCRIPT_NOT_SAVED_WARN,
402: getRelativeSrcPath(fromObject));
403: }
404: }
405:
406: private File getDefaultIndex(FileObject sourceRoot) {
407: FileObject[] children = sourceRoot.getChildren();
408: for (FileObject fo : children) {
409: if (fo.getName().equalsIgnoreCase(DEFAULT_INDEX_NAME)
410: && fo.getExt().equalsIgnoreCase(DEFAULT_INDEX_EXT)) {
411: return FileUtil.toFile(fo);
412: }
413: }
414: return null;
415: }
416:
417: private boolean isPrintToOutput() {
418: return ProjectActionsPreferences.getInstance()
419: .getCommandLineRunPrintToOutput();
420: }
421:
422: private boolean isOpenInBrowser() {
423: return ProjectActionsPreferences.getInstance()
424: .getCommandLineRunOpenInBrowser();
425: }
426:
427: private File getTmpFile(String script) throws IOException {
428:
429: File scriptFile = new File(script);
430: String ext = loadFormattedMsg(LBL_INTERPRETED_PHP_EXT, this
431: .getClass());
432: File tmpFile = File.createTempFile(scriptFile.getName(), ext);
433: tmpFile.deleteOnExit();
434:
435: return tmpFile;
436: }
437:
438: private static boolean myIsEnabled = SystemPackageFinder
439: .isSupportedOs();
440: private Process myProcess;
441: private boolean isCancelled = false;
442: private String myOutputTabTitle;
443:
444: }
|