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: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.modules.profiler.attach.providers.scripted;
042:
043: import org.netbeans.lib.profiler.common.AttachSettings;
044: import org.netbeans.lib.profiler.common.integration.IntegrationUtils;
045: import org.openide.util.RequestProcessor;
046: import java.io.BufferedReader;
047: import java.io.File;
048: import java.io.FileInputStream;
049: import java.io.FileOutputStream;
050: import java.io.IOException;
051: import java.io.InputStreamReader;
052: import java.io.OutputStreamWriter;
053: import java.io.Writer;
054: import java.util.ArrayList;
055: import java.util.Collection;
056: import java.util.Iterator;
057: import org.netbeans.modules.profiler.attach.providers.AbstractIntegrationProvider;
058: import org.netbeans.modules.profiler.attach.providers.IntegrationCategorizer;
059: import org.netbeans.modules.profiler.attach.providers.ValidationResult;
060: import org.netbeans.modules.profiler.attach.spi.ModificationException;
061: import org.netbeans.modules.profiler.attach.spi.RunException;
062: import org.netbeans.modules.profiler.attach.wizard.steps.NullWizardStep;
063:
064: /**
065: *
066: * @author Jaroslav Bachorik
067: */
068: public abstract class AbstractScriptIntegrationProvider extends
069: AbstractIntegrationProvider {
070: //~ Instance fields ----------------------------------------------------------------------------------------------------------
071:
072: private String installationPath = ""; // NOI18N
073:
074: //~ Constructors -------------------------------------------------------------------------------------------------------------
075:
076: public AbstractScriptIntegrationProvider() {
077: super ();
078: this .attachedWizard = new NullWizardStep();
079: }
080:
081: //~ Methods ------------------------------------------------------------------------------------------------------------------
082:
083: public void setInstallationPath(String path) {
084: this .installationPath = path;
085: }
086:
087: public String getInstallationPath() {
088: return this .installationPath;
089: }
090:
091: public void categorize(IntegrationCategorizer categorizer) {
092: categorizer.addAppserver(this , getAttachWizardPriority());
093: }
094:
095: public void modify(AttachSettings attachSettings)
096: throws ModificationException {
097: try {
098: modifyScriptForAttach(attachSettings);
099: } catch (ScriptModificationException e) {
100: throw new ModificationException(e);
101: }
102: }
103:
104: public void run(AttachSettings attachSettings) throws RunException {
105: if (attachSettings.isRemote()) {
106: // System.err.println(MessageFormat.format(getStartTargetUnsupportedMessage(), new Object[] {attachSettings.debug()}));
107: return;
108: }
109:
110: final boolean isDirectAttach = attachSettings.isDirect();
111:
112: String targetOS = attachSettings.getHostOS();
113:
114: Collection commandsArray = prepareCommands(targetOS); // prepares the appserver independent part of the startup script
115:
116: final String[] commands = (String[]) commandsArray
117: .toArray(new String[] {});
118:
119: RequestProcessor.getDefault().post(new Runnable() {
120: public void run() {
121: try {
122: BufferedReader input = new BufferedReader(
123: new InputStreamReader(Runtime.getRuntime()
124: .exec(commands).getInputStream()));
125:
126: while (input.readLine() != null) {
127: ;
128: }
129:
130: input.close();
131: } catch (Exception ex) {
132: ex.printStackTrace();
133:
134: // System.err.println(MessageFormat.format(getStartingErrorMessage(), new Object[] {ex}));
135: }
136: }
137: });
138: }
139:
140: public abstract ValidationResult validateInstallation(
141: final String targetOS, final String path);
142:
143: protected abstract boolean isBackupRequired();
144:
145: protected abstract ScriptHeaderModifier getHeaderModifier(
146: final String targetOS);
147:
148: protected abstract String getModifiedScriptPath(
149: final String targetOS, final boolean quoted);
150:
151: protected abstract String getScriptPath(final String targetOS,
152: final boolean quoted);
153:
154: protected abstract String getWinConsoleString();
155:
156: protected abstract void generateCommands(String targetOS,
157: Collection commandsArray);
158:
159: protected abstract void modifyScriptFileForDirectAttach(
160: final String hostOS, final int port,
161: final boolean isReplaceFile, final StringBuffer buffer);
162:
163: protected abstract void modifyScriptFileForDynamicAttach(
164: final String hostOS, final int port,
165: final boolean isReplaceFile, final StringBuffer buffer);
166:
167: protected String getDefaultScriptEncoding() {
168: return null;
169: }
170:
171: protected final void modifyScript(final String originalScriptName,
172: final String modifiedScriptName,
173: final ProfilerScriptModifier modifier,
174: final AttachSettings attachSettings)
175: throws ScriptModificationException {
176: modifyScript(originalScriptName, modifiedScriptName, modifier,
177: attachSettings, null);
178: }
179:
180: protected final void modifyScript(final String originalScriptName,
181: final String modifiedScriptName,
182: final ProfilerScriptModifier modifier,
183: final AttachSettings attachSettings, String encoding)
184: throws ScriptModificationException {
185: String targetOS = attachSettings.getHostOS();
186: String lineBreak = IntegrationUtils.getLineBreak(targetOS);
187: BufferedReader br = null;
188:
189: File scriptFile = null;
190: File modifiedScriptFile = null;
191:
192: try {
193: scriptFile = new File(originalScriptName);
194: modifiedScriptFile = new File(modifiedScriptName);
195:
196: // /******* !!!! Provide meaningful exceptions !!!! ***********/
197: //
198: // if (IntegrationUtils.isFileModifiedForProfiler(scriptFile)) {
199: //// lastErrorMessage = MessageFormat.format(FILE_MODIFIED_MSG, new Object[] {catalinaScriptFilePath, getCatalinaScriptName(targetOS, targetJVM, supportedTarget)});
200: //// return false;
201: // return;
202: // }
203: //
204: // if (!IntegrationUtils.copyFile(scriptFile, modifiedScriptFile)) {
205: //// lastErrorMessage = MessageFormat.format(ERROR_COPY_FILE_MSG, new Object[] {catalinaScriptFilePath, modifiedScriptFilePath});
206: //// return false;
207: // return;
208: // }
209: //
210: // /***********************************************/
211: String line;
212:
213: InputStreamReader fr = null;
214:
215: if (encoding == null) {
216: fr = new InputStreamReader(new FileInputStream(
217: scriptFile));
218: } else {
219: fr = new InputStreamReader(new FileInputStream(
220: scriptFile), encoding);
221: }
222:
223: if (encoding == null) {
224: encoding = fr.getEncoding();
225: }
226:
227: br = new BufferedReader(fr);
228:
229: StringBuffer buffer = new StringBuffer();
230:
231: StringBuffer lineBuffer = new StringBuffer();
232:
233: // copy config file from disk into memory buffer
234: while ((line = br.readLine()) != null) {
235: lineBuffer.append(line);
236: modifier.lineRead(lineBuffer); // give a chance to the custom script modifier to modify the line on-the-fly
237: buffer.append(lineBuffer);
238: buffer.append(lineBreak);
239: lineBuffer.delete(0, lineBuffer.length());
240: }
241:
242: modifier.readDone();
243: br.close();
244:
245: if (modifier.needsModification() && isBackupRequired()) {
246: if (!IntegrationUtils.backupFile(scriptFile)) {
247: throw new ScriptModificationException(
248: "Can't backup script"); // NOI18N
249: }
250: }
251:
252: modifier.modifyScript(attachSettings, lineBreak, buffer); // let the custom script modifier modify the script in batch mode
253:
254: // flush modified config file from memory buffer to disk
255: Writer fw = new OutputStreamWriter(new FileOutputStream(
256: modifiedScriptFile), "UTF-8"); // NOI18N
257: fw.write(buffer.toString());
258: fw.flush();
259: fw.close();
260:
261: if (!IntegrationUtils.isWindowsPlatform(targetOS)) {
262: Runtime.getRuntime().exec("chmod a+x " // NOI18N
263: + modifiedScriptFile.getAbsolutePath()); //NOI18N
264: }
265: } catch (IOException e) {
266: if (isBackupRequired()) {
267: if (!IntegrationUtils.restoreFile(scriptFile)) {
268: throw new ScriptModificationException(
269: "Restore corrupted"); // NOI18N
270: }
271: }
272:
273: throw new ScriptModificationException(e);
274: } catch (ScriptModificationException e) {
275: if (isBackupRequired()) {
276: if (!IntegrationUtils.restoreFile(scriptFile)) {
277: throw new ScriptModificationException(
278: "Restore corrupted", e); // NOI18N
279: }
280: }
281:
282: throw e; // rethrow
283: } finally {
284: try {
285: br.close();
286: } catch (Exception e) {
287: }
288: }
289: }
290:
291: protected final void modifyScript(final String originalScriptName,
292: final ProfilerScriptModifier modifier,
293: final AttachSettings attachSettings)
294: throws ScriptModificationException {
295: modifyScript(originalScriptName, originalScriptName, modifier,
296: attachSettings);
297: }
298:
299: private void generateCompleteCommands(String targetOS,
300: Collection commandsArray) {
301: if (IntegrationUtils.isWindowsPlatform(targetOS)) {
302: commandsArray.add("cmd.exe"); // NOI18N
303: commandsArray.add("/K"); // NOI18N
304: commandsArray.add("start"); // NOI18N
305: commandsArray.add("\"" + getWinConsoleString() + "\""); // NOI18N
306: } else if (IntegrationUtils.PLATFORM_MAC_OS.equals(targetOS)) {
307: Collection startCommand = new ArrayList();
308: StringBuffer startCommandBuffer = new StringBuffer(256);
309: Iterator commandIt = startCommand.iterator();
310:
311: generateCommands(targetOS, startCommand);
312: commandIt = startCommand.iterator();
313:
314: while (commandIt.hasNext()) {
315: String args = (String) commandIt.next();
316:
317: startCommandBuffer.append(args);
318: startCommandBuffer.append(" "); // NOI18N
319: }
320:
321: commandsArray.add("/usr/bin/osascript"); // NOI18N
322: commandsArray.add("-e"); // NOI18N
323: commandsArray.add("tell Application \"Terminal\""); // NOI18N
324: commandsArray.add("-e"); // NOI18N
325:
326: commandsArray.add("do script \"" + startCommandBuffer
327: + "\""); // NOI18N
328: commandsArray.add("-e"); // NOI18N
329: commandsArray.add("end tell"); // NOI18N
330:
331: return;
332: } else {
333: commandsArray.add("xterm"); // NOI18N
334: commandsArray.add("-sb"); // NOI18N
335: commandsArray.add("-sl"); // NOI18N
336: commandsArray.add("1000"); // NOI18N
337: commandsArray.add("-e"); // NOI18N
338: }
339:
340: generateCommands(targetOS, commandsArray);
341: }
342:
343: private void modifyScriptForAttach(
344: final AttachSettings attachSettings)
345: throws ScriptModificationException {
346: final String targetOS = attachSettings.getHostOS();
347:
348: if (attachSettings.isDirect()) {
349: modifyScript(getScriptPath(targetOS, false),
350: getModifiedScriptPath(targetOS, false),
351: new ProfilerScriptModifier(
352: getHeaderModifier(targetOS)) {
353: public void onModification(
354: final AttachSettings attachSettings,
355: final String lineBreak,
356: StringBuffer scriptBuffer)
357: throws ScriptModificationException {
358: modifyScriptFileForDirectAttach(targetOS,
359: attachSettings.getPort(), false,
360: scriptBuffer);
361: }
362:
363: public void onLineRead(final StringBuffer line) {
364: }
365: }, attachSettings, getDefaultScriptEncoding());
366: } else {
367: modifyScript(getScriptPath(targetOS, false),
368: getModifiedScriptPath(targetOS, false),
369: new ProfilerScriptModifier(
370: getHeaderModifier(targetOS)) {
371: public void onModification(
372: final AttachSettings attachSettings,
373: final String lineBreak,
374: StringBuffer scriptBuffer)
375: throws ScriptModificationException {
376: modifyScriptFileForDynamicAttach(targetOS,
377: attachSettings.getPort(), false,
378: scriptBuffer);
379: }
380:
381: public void onLineRead(final StringBuffer line) {
382: }
383: }, attachSettings, getDefaultScriptEncoding());
384: }
385: }
386:
387: private Collection prepareCommands(String targetOS) {
388: Collection commandsArray = new ArrayList(15);
389: generateCompleteCommands(targetOS, commandsArray);
390:
391: return commandsArray;
392: }
393: }
|