001: package com.tc.test.server.appserver.was6x;
002:
003: import org.apache.commons.io.IOUtils;
004:
005: import com.tc.logging.TCLogger;
006: import com.tc.logging.TCLogging;
007: import com.tc.process.Exec;
008: import com.tc.process.Exec.Result;
009: import com.tc.test.TestConfigObject;
010: import com.tc.test.server.Server;
011: import com.tc.test.server.ServerParameters;
012: import com.tc.test.server.ServerResult;
013: import com.tc.test.server.appserver.AbstractAppServer;
014: import com.tc.test.server.appserver.AppServerParameters;
015: import com.tc.test.server.appserver.AppServerResult;
016: import com.tc.test.server.util.AppServerUtil;
017: import com.tc.util.PortChooser;
018: import com.tc.util.runtime.Os;
019:
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.FileNotFoundException;
023: import java.io.FileOutputStream;
024: import java.io.IOException;
025: import java.text.MessageFormat;
026: import java.util.ArrayList;
027: import java.util.Arrays;
028: import java.util.HashSet;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Set;
032:
033: public class Was6xAppServer extends AbstractAppServer {
034:
035: private static final TCLogger logger = TCLogging
036: .getLogger(Server.class);
037:
038: private static final String TERRACOTTA_PY = "terracotta.py";
039: private static final String DEPLOY_APPS_PY = "deployApps.py";
040: private static final String ENABLE_DSO_PY = "enable-dso.py";
041: private static final String DSO_JVMARGS = "__DSO_JVMARGS__";
042: private static final String PORTS_DEF = "ports.def";
043: private static final int START_STOP_TIMEOUT_SECONDS = 5 * 60;
044:
045: private String[] scripts = new String[] { DEPLOY_APPS_PY,
046: TERRACOTTA_PY, ENABLE_DSO_PY };
047:
048: private String policy = "grant codeBase \"file:FILENAME\" {"
049: + IOUtils.LINE_SEPARATOR
050: + " permission java.security.AllPermission;"
051: + IOUtils.LINE_SEPARATOR + "};" + IOUtils.LINE_SEPARATOR;
052: private String instanceName;
053: private String dsoJvmArgs;
054: private int webspherePort;
055: private File sandbox;
056: private File instanceDir;
057: private File pyScriptsDir;
058: private File dataDir;
059: private File warDir;
060: private File portDefFile;
061: private File serverInstallDir;
062: private File extraScript;
063:
064: private Thread serverThread;
065:
066: public Was6xAppServer(Was6xAppServerInstallation installation) {
067: super (installation);
068: }
069:
070: public ServerResult start(ServerParameters parameters)
071: throws Exception {
072: init(parameters);
073: createPortFile();
074: copyPythonScripts();
075: patchTerracottaPy();
076: deleteProfileIfExists();
077: createProfile();
078: verifyProfile();
079: deployWarFile();
080: addTerracottaToServerPolicy();
081: enableDSO();
082: if (extraScript != null) {
083: executeJythonScript(extraScript);
084: }
085: serverThread = new Thread() {
086: public void run() {
087: try {
088: startWebsphere();
089: } catch (Exception e) {
090: e.printStackTrace();
091: }
092: }
093: };
094: serverThread.setDaemon(true);
095: serverThread.start();
096: AppServerUtil.waitForPort(webspherePort,
097: START_STOP_TIMEOUT_SECONDS * 1000);
098: logger.info("Websphere instance " + instanceName
099: + " started on port " + webspherePort);
100: return new AppServerResult(webspherePort, this );
101: }
102:
103: public void stop() throws Exception {
104: try {
105: stopWebsphere();
106: } catch (Exception e) {
107: // ignored
108: } finally {
109: try {
110: deleteProfile();
111: } catch (Exception e2) {
112: // ignored
113: }
114: }
115: }
116:
117: private void createPortFile() throws Exception {
118: PortChooser portChooser = new PortChooser();
119: webspherePort = portChooser.chooseRandomPort();
120:
121: List lines = IOUtils.readLines(getClass().getResourceAsStream(
122: PORTS_DEF));
123: lines.set(0, (String) lines.get(0) + webspherePort);
124:
125: for (int i = 1; i < lines.size(); i++) {
126: String line = (String) lines.get(i);
127: lines.set(i, line + portChooser.chooseRandomPort());
128: }
129: if (logger.isDebugEnabled()) {
130: logger.debug("createPortFile() using ports: " + lines);
131: }
132:
133: writeLines(lines, portDefFile, false);
134: }
135:
136: private void copyPythonScripts() throws Exception {
137: for (int i = 0; i < scripts.length; i++) {
138: logger.debug("copyPythonScripts(): copying file["
139: + scripts[i] + "] to directory [" + pyScriptsDir
140: + "]");
141: copyResourceTo(scripts[i], new File(pyScriptsDir,
142: scripts[i]));
143: }
144: }
145:
146: private void patchTerracottaPy() throws FileNotFoundException,
147: IOException, Exception {
148: File terracotta_py = new File(pyScriptsDir, TERRACOTTA_PY);
149: FileInputStream fin = new FileInputStream(terracotta_py);
150: List lines = IOUtils.readLines(fin);
151: fin.close();
152:
153: // replace __DSO_JVMARGS__
154: for (int i = 0; i < lines.size(); i++) {
155: String line = (String) lines.get(i);
156: if (line.indexOf(DSO_JVMARGS) >= 0) {
157: if (logger.isDebugEnabled()) {
158: logger.debug("patchTerracottaPy(): patching line: "
159: + line);
160: }
161: line = line.replaceFirst(DSO_JVMARGS, dsoJvmArgs);
162: if (logger.isDebugEnabled()) {
163: logger
164: .debug("patchTerracottaPy(): after patching line: "
165: + line);
166: }
167: lines.set(i, line);
168: }
169: }
170:
171: writeLines(lines, terracotta_py, false);
172: }
173:
174: private void enableDSO() throws Exception {
175: String[] args = new String[] { "-lang", "jython", "-connType",
176: "NONE", "-profileName", instanceName, "-f",
177: new File(pyScriptsDir, ENABLE_DSO_PY).getAbsolutePath() };
178: executeCommand(serverInstallDir, "wsadmin", args, pyScriptsDir,
179: "Error in enabling DSO for " + instanceName);
180: }
181:
182: private void executeJythonScript(File script) throws Exception {
183: String[] args = new String[] { "-lang", "jython", "-connType",
184: "NONE", "-profileName", instanceName, "-f",
185: script.getAbsolutePath() };
186: executeCommand(serverInstallDir, "wsadmin", args, pyScriptsDir,
187: "Error executing " + script);
188: }
189:
190: private void deleteProfile() throws Exception {
191: String[] args = new String[] { "-delete", "-profileName",
192: instanceName };
193: executeCommand(serverInstallDir, "manageprofiles", args,
194: serverInstallDir, "Error in deleting profile for "
195: + instanceName);
196: }
197:
198: private void createProfile() throws Exception {
199: String defaultTemplate = new File(serverInstallDir
200: .getAbsolutePath(), "profileTemplates/default")
201: .getAbsolutePath();
202: String[] args = new String[] { "-create", "-templatePath",
203: defaultTemplate, "-profileName", instanceName,
204: "-profilePath", instanceDir.getAbsolutePath(),
205: "-portsFile", portDefFile.getAbsolutePath(),
206: "-enableAdminSecurity", "false", "-isDeveloperServer" };
207: logger.info("Creating profile for instance " + instanceName
208: + "...");
209: long start = System.currentTimeMillis();
210: executeCommand(serverInstallDir, "manageprofiles", args,
211: serverInstallDir, "Error in creating profile for "
212: + instanceName);
213: long elapsedMillis = System.currentTimeMillis() - start;
214: long elapsedSeconds = elapsedMillis / 1000;
215: Long elapsedMinutes = new Long(elapsedSeconds / 60);
216: logger.info("Profile creation time: "
217: + MessageFormat.format("{0,number,##}:{1}.{2}",
218: new Object[] { elapsedMinutes,
219: new Long(elapsedSeconds % 60),
220: new Long(elapsedMillis % 1000) }));
221: }
222:
223: private void verifyProfile() throws Exception {
224: if (!(instanceDir.exists() && instanceDir.isDirectory())) {
225: Exception e = new Exception(
226: "Unable to verify profile for instance '"
227: + instanceName + "'");
228: logger.error("WebSphere profile '" + instanceName
229: + "' does not exist at "
230: + instanceDir.getAbsolutePath(), e);
231: throw e;
232: }
233: logger.info("WebSphere profile '" + instanceName
234: + "' is verified at " + instanceDir.getAbsolutePath());
235: }
236:
237: private void deleteProfileIfExists() throws Exception {
238: // call "manageprofiles.sh -validateAndUpdateRegistry" to clean out corrupted profiles
239: String[] args = new String[] { "-validateAndUpdateRegistry" };
240: executeCommand(serverInstallDir, "manageprofiles", args,
241: serverInstallDir, "");
242: args = new String[] { "-listProfiles" };
243: String output = executeCommand(serverInstallDir,
244: "manageprofiles", args, serverInstallDir, "");
245: if (output.indexOf(instanceName) >= 0) {
246: args = new String[] { "-delete", "-profileName",
247: instanceName };
248: executeCommand(serverInstallDir, "manageprofiles", args,
249: serverInstallDir,
250: "Trying to clean up existing profile");
251: }
252: }
253:
254: private void addTerracottaToServerPolicy() throws Exception {
255: String classpath = System.getProperty("java.class.path");
256: Set set = new HashSet();
257: String[] entries = classpath.split(File.pathSeparator);
258: for (int i = 0; i < entries.length; i++) {
259: File filename = new File(entries[i]);
260: if (filename.isDirectory()) {
261: set.add(filename);
262: } else {
263: set.add(filename.getParentFile());
264: }
265: }
266:
267: List lines = new ArrayList(set.size() + 1);
268: for (Iterator it = set.iterator(); it.hasNext();) {
269: lines.add(getPolicyFor((File) it.next()));
270: }
271: lines.add(getPolicyFor(new File(TestConfigObject.getInstance()
272: .normalBootJar())));
273:
274: writeLines(lines, new File(new File(instanceDir, "properties"),
275: "server.policy"), true);
276: }
277:
278: private String getPolicyFor(File filename) {
279: String entry = filename.getAbsolutePath().replace('\\', '/');
280:
281: if (filename.isDirectory()) {
282: return policy.replaceFirst("FILENAME", entry + "/-");
283: } else {
284: return policy.replaceFirst("FILENAME", entry);
285: }
286: }
287:
288: private void copyResourceTo(String filename, File dest)
289: throws Exception {
290: FileOutputStream fos = null;
291: try {
292: fos = new FileOutputStream(dest);
293: IOUtils.copy(getClass().getResourceAsStream(filename), fos);
294: } finally {
295: IOUtils.closeQuietly(fos);
296: }
297: }
298:
299: private void deployWarFile() throws Exception {
300: String[] args = new String[] {
301: "-lang",
302: "jython",
303: "-connType",
304: "NONE",
305: "-profileName",
306: instanceName,
307: "-f",
308: new File(pyScriptsDir, DEPLOY_APPS_PY)
309: .getAbsolutePath(),
310: warDir.getAbsolutePath().replace('\\', '/') };
311: logger.info("Deploying war file in: " + warDir);
312: executeCommand(serverInstallDir, "wsadmin", args, pyScriptsDir,
313: "Error in deploying warfile for " + instanceName);
314: logger.info("Done deploying war file in: " + warDir);
315: }
316:
317: private void startWebsphere() throws Exception {
318: String[] args = new String[] { "server1", "-profileName",
319: instanceName, "-trace", "-timeout",
320: String.valueOf(START_STOP_TIMEOUT_SECONDS) };
321: executeCommand(serverInstallDir, "startServer", args,
322: instanceDir, "Error in starting " + instanceName);
323: }
324:
325: private void stopWebsphere() throws Exception {
326: String[] args = new String[] { "server1", "-profileName",
327: instanceName };
328: executeCommand(serverInstallDir, "stopServer", args,
329: instanceDir, "Error in stopping " + instanceName);
330: if (serverThread != null) {
331: serverThread.join(START_STOP_TIMEOUT_SECONDS * 1000);
332: }
333: }
334:
335: private void init(ServerParameters parameters) {
336: AppServerParameters params = (AppServerParameters) parameters;
337: sandbox = sandboxDirectory();
338: instanceName = params.instanceName();
339: instanceDir = new File(sandbox, instanceName);
340: dataDir = new File(sandbox, "data");
341: warDir = new File(sandbox, "war");
342: pyScriptsDir = new File(dataDir, instanceName);
343: pyScriptsDir.mkdirs();
344: portDefFile = new File(pyScriptsDir, PORTS_DEF);
345: serverInstallDir = serverInstallDirectory();
346:
347: String[] jvm_args = params.jvmArgs().replaceAll("'", "")
348: .replace('\\', '/').split("\\s+");
349: StringBuffer sb = new StringBuffer();
350: for (int i = 0; i < jvm_args.length; i++) {
351: sb.append("\"" + jvm_args[i] + "\"");
352: if (i < jvm_args.length - 1) {
353: sb.append(", ");
354: }
355: }
356: dsoJvmArgs = sb.toString();
357:
358: if (logger.isDebugEnabled()) {
359: logger.debug("init{sandbox} ==> "
360: + sandbox.getAbsolutePath());
361: logger.debug("init{instanceName} ==> " + instanceName);
362: logger.debug("init{instanceDir} ==> "
363: + instanceDir.getAbsolutePath());
364: logger.debug("init{webappDir} ==> "
365: + dataDir.getAbsolutePath());
366: logger.debug("init{pyScriptsDir} ==> "
367: + pyScriptsDir.getAbsolutePath());
368: logger.debug("init{portDefFile} ==> "
369: + portDefFile.getAbsolutePath());
370: logger.debug("init{serverInstallDir} ==> "
371: + serverInstallDir.getAbsolutePath());
372: logger.debug("init{dsoJvmArgs} ==> " + dsoJvmArgs);
373: }
374: }
375:
376: private String getScriptPath(File root, String scriptName) {
377: File bindir = new File(root, "bin");
378: return new File(bindir, (Os.isWindows() ? scriptName + ".bat"
379: : scriptName + ".sh")).getAbsolutePath();
380: }
381:
382: private String executeCommand(File rootDir, String scriptName,
383: String[] args, File workingDir, String errorMessage)
384: throws Exception {
385: String script = getScriptPath(rootDir, scriptName);
386: String[] cmd = new String[args.length + 1];
387: cmd[0] = script;
388: System.arraycopy(args, 0, cmd, 1, args.length);
389: logger.info("Executing cmd: " + Arrays.asList(cmd));
390: Result result = Exec.execute(cmd, null, null,
391: workingDir == null ? instanceDir : workingDir);
392: final StringBuffer stdout = new StringBuffer(result.getStdout());
393: final StringBuffer stderr = new StringBuffer(result.getStderr());
394: if (logger.isDebugEnabled()) {
395: logger.debug("STDOUT for[" + Arrays.asList(cmd) + "]:\n"
396: + stdout);
397: logger.debug("STDERR for[" + Arrays.asList(cmd) + "]:\n"
398: + stderr);
399: }
400: if (result.getExitCode() != 0) {
401: logger.warn("Command did not return 0; message is: "
402: + errorMessage);
403: }
404: return stdout.append(IOUtils.LINE_SEPARATOR).append(stderr)
405: .toString();
406: }
407:
408: private void writeLines(List lines, File filename, boolean append)
409: throws Exception {
410: FileOutputStream fos = null;
411: try {
412: fos = new FileOutputStream(filename, append);
413: IOUtils.writeLines(lines, IOUtils.LINE_SEPARATOR, fos);
414: } finally {
415: IOUtils.closeQuietly(fos);
416: }
417: }
418:
419: public void setExtraScript(File extraScript) {
420: this.extraScript = extraScript;
421: }
422: }
|