KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > websphere6 > optional > WSStartServer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.j2ee.websphere6.optional;
20
21 import java.io.*;
22 import java.net.*;
23 import java.util.*;
24
25 import javax.enterprise.deploy.shared.*;
26 import javax.enterprise.deploy.spi.*;
27 import javax.enterprise.deploy.spi.exceptions.*;
28 import javax.enterprise.deploy.spi.status.*;
29
30 import org.openide.*;
31 import org.openide.util.*;
32 import org.netbeans.modules.j2ee.deployment.plugins.api.*;
33
34 import org.netbeans.modules.j2ee.websphere6.*;
35 import org.netbeans.modules.j2ee.websphere6.ui.nodes.actions.ShowServerLogAction;
36 import org.netbeans.modules.j2ee.websphere6.util.*;
37
38 /**
39  * This class provides functionality used to start and stop a particular server
40  * instance. It also supports starting the server in debug mode, so that
41  * NetBeans can connect to it using its built-in JPDA debugger.
42  *
43  * @author Kirill Sorokin
44  */

45 public class WSStartServer extends StartServer {
46     
47     /**
48      * The server's deployment manager, to be exact the plugin's wrapper for it
49      */

50     private WSDeploymentManager dm;
51     
52     /**
53      * Current server's state. Can be either started, starting, stopping or
54      * stopped
55      */

56     private int state;
57     
58     /**
59      * Map containing markers that describe whether the server is started in debug mode
60      */

61     private static Map isDebugModeMap = Collections.synchronizedMap((Map)new HashMap(2,1));
62     
63     /**
64      * Creates a new instance of WSStartServer
65      *
66      * @param the server's deployment manager
67      */

68     public WSStartServer(DeploymentManager dm) {
69         // cast the deployment manager to the plugin's wrapper class and save
70
this.dm = (WSDeploymentManager) dm;
71         
72         // get current server state
73
this.state = isRunning() ? STATE_STARTED : STATE_STOPPED;
74     }
75     
76     // overrides default StartServer method
77
public boolean supportsStartDebugging(Target target) {
78         return true;
79     }
80     
81     /**
82      * Starts the server (or even a particular target supplied by admin server)
83      * in debug mode. We do not support this completely thus always start the
84      * server instance defined in the deployment maanger supplied during
85      * WSStartServer construction.
86      *
87      * @param target target thst should be started
88      *
89      * @return a progress object that describes the startup process
90      */

91     public ProgressObject startDebugging(Target target) {
92         if (WSDebug.isEnabled()) // debug output
93
WSDebug.notify("starting server in debug mode"); // NOI18N
94

95         // create a new progress object
96
WSServerProgress serverProgress = new WSServerProgress(this);
97         
98         // send a message denoting that the startup process has begun
99
serverProgress.notifyStart(StateType.RUNNING, ""); // NOI18N
100

101         // if the server is stopping
102
if (state == STATE_STOPPING) {
103             // wait till the startup completes or times out
104
for (int i = 0; i < WSStopRunnable.TIMEOUT; i += WSStopRunnable.DELAY) {
105                 if (state == STATE_STOPPING) {
106                     try {
107                         Thread.sleep(WSStopRunnable.DELAY);
108                     } catch (InterruptedException JavaDoc e) {
109                         // do nothing just skip the sleeping phase
110
}
111                 }
112                 
113                 if (state == STATE_STOPPED) {
114                     break;
115                 }
116             }
117         }
118         
119         // if the server is started or starting
120
if (state == STATE_STARTING || state == STATE_STARTED) {
121             // notify the progress object that the process is already
122
// completed and return
123
serverProgress.notifyStart(StateType.COMPLETED, "");
124             return serverProgress;
125         }
126         
127         // run the startup process in a separate thread
128
RequestProcessor.getDefault().post(new WSStartDebugRunnable(
129                 serverProgress), 0, Thread.NORM_PRIORITY);
130         
131         // set the debuggable marker
132
// isDebuggable = true;
133
isDebugModeMap.put(dm.getHost() + dm.getPort() + dm.getDomainRoot(), new Object JavaDoc());
134         
135         // set the state to starting
136
state = STATE_STARTING;
137         
138         // return the progress object
139
return serverProgress;
140     }
141     
142     
143     
144     /**
145      * Specifies whether the server instance is started in debug mode. The
146      * detalization can go as deep as an individual target, but we do not
147      * support this
148      *
149      * @param target target to be checked
150      *
151      * @return whether the instance is started in debug mode
152      */

153     public boolean isDebuggable(Target target) {
154         
155         if(!isDebugModeMap.containsKey(dm.getHost() + dm.getPort() + dm.getDomainRoot())){
156             return false;
157         }
158         
159         if(!isRunning()){
160             isDebugModeMap.remove(dm.getHost() + dm.getPort() + dm.getDomainRoot());
161             return false;
162         }
163         return true;
164     }
165     
166     
167     
168     /**
169      * Tells whether the target is also the target server
170      *
171      * @return true
172      */

173     public boolean isAlsoTargetServer(Target target) {
174         return true;
175     }
176     
177     /**
178      * Returns the information for attaching the JPDA debugger to the server
179      * (host and port). The detalization can be down to a specific target, but
180      * we do not support this
181      *
182      * @param target target for which the information is requested
183      *
184      * @return the debug information
185      */

186     public ServerDebugInfo getDebugInfo(Target target) {
187         return new ServerDebugInfo(dm.getHost(), new Integer JavaDoc(
188                 dm.getInstanceProperties().getProperty(
189                 WSDeploymentFactory.DEBUGGER_PORT_ATTR)).intValue());
190     }
191     
192     /**
193      * Tells whether the normal startup of the server is supported.
194      *
195      * @return if the server is local, its true, false otherwise
196      */

197     public boolean supportsStartDeploymentManager() {
198         // if the server is local we can start it
199
if (dm.getInstanceProperties().getProperty(
200                 WSDeploymentFactory.IS_LOCAL_ATTR).equals("true")) { // NOI18N
201
return true;
202         } else {
203             return false;
204         }
205     }
206     
207     /**
208      * Stops the server instance identified by the deployment manager.
209      *
210      * @return the progress object describing the shutdown process
211      */

212     public ProgressObject stopDeploymentManager() {
213         if (WSDebug.isEnabled()) // debug output
214
WSDebug.notify("stopping server"); // NOI18N
215

216         // create a new progress object
217
WSServerProgress serverProgress = new WSServerProgress(this);
218         
219         // send a message denoting that the shutdown process has begun
220
serverProgress.notifyStop(StateType.RUNNING, ""); // NOI18N
221

222         // if the server is starting
223
if (state == STATE_STARTING) {
224             // wait till the startup completes or times out
225
for (int i = 0; i < WSStartRunnable.TIMEOUT; i += WSStartRunnable.DELAY) {
226                 if (state == STATE_STARTING) {
227                     try {
228                         Thread.sleep(WSStartRunnable.DELAY);
229                     } catch (InterruptedException JavaDoc e) {
230                         // do nothing just skip the sleeping phase
231
}
232                 }
233                 
234                 if (state == STATE_STARTED) {
235                     break;
236                 }
237             }
238         }
239         
240         // if the server is stopped or stopping
241
if (state == STATE_STOPPING || state == STATE_STOPPED) {
242             // notify the progress object that the process is already
243
// completed and return
244
serverProgress.notifyStop(StateType.COMPLETED, "");
245             return serverProgress;
246         }
247         
248         // run the shutdown process in a separate thread
249
RequestProcessor.getDefault().post(new WSStopRunnable(serverProgress),
250                 0, Thread.NORM_PRIORITY);
251         
252         // set the debugguable marker to false as the server is stopped
253
// isDebuggable = false;
254
isDebugModeMap.remove(dm.getHost() + dm.getPort() + dm.getDomainRoot());
255         
256         // set the state to stopping
257
state = STATE_STOPPING;
258         
259         // return the progress object
260
return serverProgress;
261     }
262     
263     /**
264      * Starts a server instance identified by the deployment manager.
265      *
266      * @return a progress object describing the server startup process
267      */

268     public ProgressObject startDeploymentManager() {
269         if (WSDebug.isEnabled()) // debug output
270
WSDebug.notify("starting server"); // NOI18N
271

272         // create a new progress object
273
WSServerProgress serverProgress = new WSServerProgress(this);
274         
275         // send a message denoting that the startup process has begun
276
serverProgress.notifyStart(StateType.RUNNING, ""); // NOI18N
277

278         // if the server is stopping
279
if (state == STATE_STOPPING) {
280             // wait till the startup completes or times out
281
for (int i = 0; i < WSStopRunnable.TIMEOUT; i += WSStopRunnable.DELAY) {
282                 if (state == STATE_STOPPING) {
283                     try {
284                         Thread.sleep(WSStopRunnable.DELAY);
285                     } catch (InterruptedException JavaDoc e) {
286                         // do nothing just skip the sleeping phase
287
}
288                 }
289                 
290                 if (state == STATE_STOPPED) {
291                     break;
292                 }
293             }
294         }
295         
296         // if the server is started or starting
297
if (state == STATE_STARTING || state == STATE_STARTED) {
298             // notify the progress object that the process is already
299
// completed and return
300
serverProgress.notifyStart(StateType.COMPLETED, "");
301             return serverProgress;
302         }
303         
304         // run the startup process in a separate thread
305
RequestProcessor.getDefault().post(new WSStartRunnable(serverProgress),
306                 0, Thread.NORM_PRIORITY);
307         
308         // set the debuggble marker to false as we do not start the server in
309
// debug mode
310
// isDebuggable = false;
311
isDebugModeMap.remove(dm.getHost() + dm.getPort() + dm.getDomainRoot());
312         
313         // set the state to starting
314
state = STATE_STARTING;
315         
316         // return the progress object
317
return serverProgress;
318     }
319     
320     /**
321      * Tells whether we need to start the server instance in order to get a
322      * list of deployment targets.
323      *
324      * @return true
325      */

326     public boolean needsStartForTargetList() {
327         return true;
328     }
329     
330     /**
331      * Tells whether we need to start the server instance in order to configure
332      * an application
333      *
334      * @return false
335      */

336     public boolean needsStartForConfigure() {
337         return false;// modified. was true
338
}
339     
340     /**
341      * Tells whether we need to start the server instance in order to configure
342      * the admin server
343      *
344      * @return true
345      */

346     public boolean needsStartForAdminConfig() {
347         return true;
348     }
349     
350     /**
351      * Tells whether the server instance identified by the deployment manager is
352      * currently started
353      *
354      * @return true is the server is running, false otherwise
355      */

356     public boolean isRunning() {
357         // try to get an open socket to the target host/port
358
try {
359             new Socket(dm.getHost(), new Integer JavaDoc(dm.getPort()).intValue());
360             
361             // if we are successful, return true
362
return true;
363         } catch (UnknownHostException e) {
364             ErrorManager.getDefault().notify(ErrorManager.ERROR, e);
365         } catch (IOException e) {
366             // do nothing this exception means that the server is
367
// not started
368
}
369         
370         // we failed to create a socket thus the server is not started
371
return false;
372     }
373     
374     /**
375      * An utility method that transforms a Properties object to an array of
376      * Strings each containing a property in the form of
377      * <i>'&lt;name&gt;=&lt;value&gt;'</i>
378      *
379      * @param properties properties to be converted
380      *
381      * @return an array of strings with the converted properties
382      */

383     private static String JavaDoc[] properties2StringArray(Properties properties) {
384         // initiate the list that will be converted to array for returning
385
List list = new ArrayList();
386         
387         // get the properties keys
388
Enumeration keys = properties.keys();
389         
390         // iterate over the enumeration
391
while (keys.hasMoreElements()) {
392             // get the property key
393
String JavaDoc key = (String JavaDoc) keys.nextElement();
394             
395             // get the value associated with this key and store them in the list
396
list.add(key + "=" + properties.getProperty(key)); // NOI18N
397
}
398         
399         // convert the list into an array and return
400
return (String JavaDoc[]) list.toArray(new String JavaDoc[list.size()]);
401     }
402     
403     /**
404      * Turns on/off the debugging mode of the server.
405      *
406      * @param degubEnabled whether the server should be started in debug mode
407      * @param debuggerPort which port the debugger should listen to
408      */

409     private void setDebugMode(boolean debugEnabled, int debuggerPort) {
410         // get the config file path from the instance properties
411
File configXmlFile = new File(dm.getInstanceProperties().getProperty(
412                 WSDeploymentFactory.CONFIG_XML_PATH));
413         
414         // get the current file's contents
415
String JavaDoc contents = WSUtil.readFile(configXmlFile);
416         
417         // replace the attributes that relate to debugging mode of the server
418
if (debugEnabled) {
419             contents = contents.replaceAll("debugMode=\"false\"", "debugMode=\"true\"");
420             contents = contents.replaceFirst("suspend=n,address=[0-9]+\" genericJvmArguments", "suspend=n,address=" + debuggerPort + "\" genericJvmArguments");
421             if (WSDebug.isEnabled()) {
422                 WSDebug.notify("setting the address string to: " + "suspend=n,address=" + debuggerPort);
423             }
424         } else {
425             contents = contents.replaceAll("debugMode=\"true\"", "debugMode=\"false\"");
426         }
427         
428         // write the replaced contents back to the file
429
WSUtil.writeFile(configXmlFile, contents);
430     }
431     
432     /**
433      * Runnable that starts the server in normal mode. It is used to start the
434      * server in a separate thread, so that the IDE does not hang up during the
435      * startup process.
436      *
437      * @author Kirill Sorokin
438      */

439     private class WSStartRunnable implements Runnable JavaDoc {
440         
441         /**
442          * Root directory for the selected profile
443          */

444         private String JavaDoc domainHome;
445         
446         /**
447          * Name of the selected server instance, it will be used as the
448          * parameter for the startup script
449          */

450         private String JavaDoc serverName;
451         
452         /**
453          * Progress object that describes the startup process. It will be
454          * notified of the progress and the success/failure of the process
455          */

456         private WSServerProgress serverProgress;
457         
458         /**
459          * Creates a new instance of WSStartRunnable.
460          *
461          * @param serverProgress the prgress object that the thread should
462          * notify of anything that happens with the startup process
463          */

464         public WSStartRunnable(WSServerProgress serverProgress) {
465             // save the progress object
466
this.serverProgress = serverProgress;
467             
468             // get the profile root directory and the instance name from the
469
// deployment manager
470
domainHome = dm.getInstanceProperties().getProperty(
471                     WSDeploymentFactory.DOMAIN_ROOT_ATTR);
472             serverName = dm.getInstanceProperties().getProperty(
473                     WSDeploymentFactory.SERVER_NAME_ATTR);
474         }
475         
476         /**
477          * Implementation of the run() method from the Runnable interface
478          */

479         public void run() {
480             try {
481                 // save the current time so that we can deduct that the startup
482
// failed due to timeout
483
long start = System.currentTimeMillis();
484                 
485                 // set the server's debug mode to false
486
setDebugMode(false, 0);
487                 
488                 // create the startup process
489
Process JavaDoc serverProcess = Runtime.getRuntime().
490                         exec(new String JavaDoc[]{domainHome + "/bin/" + // NOI18N
491
(Utilities.isWindows() ? STARTUP_BAT : STARTUP_SH),
492                         serverName});
493                 
494                 // create a tailer to the server's output stream so that a user
495
// can observe the progress
496
new WSTailer(serverProcess.getInputStream(), NbBundle.
497                         getMessage(WSStartServer.class,
498                         "TXT_ioWindowTitle",dm.getServerTitleMessage())).start(); // NOI18N
499

500                 // show the server's log
501

502                 new WSTailer(new File(dm.getLogFilePath()),
503                         NbBundle.getMessage(ShowServerLogAction.class,
504                         "LBL_LogWindowTitle", dm.getServerTitleMessage())).start();
505                 
506                 // wait till the timeout happens, or if the server starts before
507
// send the completed event to j2eeserver
508
while (System.currentTimeMillis() - start < TIMEOUT) {
509                     // is the server is not yet running send the 'progressing'
510
// event, else send trhe 'completed' event and return
511
if (!isRunning()) {
512                         serverProgress.notifyStart(StateType.RUNNING,
513                                 ""); // NOI18N
514
} else {
515                         serverProgress.notifyStart(StateType.COMPLETED,
516                                 ""); // NOI18N
517

518                         // set the state to started
519
state = STATE_STARTED;
520                         
521                         return;
522                     }
523                     
524                     // sleep for a little so that we do not make our checks too
525
// often
526
try {
527                         Thread.sleep(DELAY);
528                     } catch (InterruptedException JavaDoc e) {}
529                 }
530                 
531                 // if the server did not start in the designated time limits
532
// we consider the startup as failed and kill the process
533
serverProgress.notifyStart(StateType.FAILED, ""); // NOI18N
534
serverProcess.destroy();
535                 
536                 // set the state to stopped
537
state = STATE_STOPPED;
538             } catch (IOException e) {
539                 ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
540             }
541         }
542         
543         /**
544          * The amount of time in milliseconds during which the server should
545          * start
546          */

547         private static final int TIMEOUT = 120000;
548         
549         /**
550          * The amount of time in milliseconds that we should wait between checks
551          */

552         private static final int DELAY = 5000;
553         
554         /**
555          * Name of the startup script for windows
556          */

557         private static final String JavaDoc STARTUP_SH = "startServer.sh"; // NOI18N
558

559         /**
560          * Name of the startup script for Unices
561          */

562         private static final String JavaDoc STARTUP_BAT = "startServer.bat"; // NOI18N
563
}
564     
565     /**
566      * Runnable that starts the server in debug mode. It is used to start the
567      * server in a separate thread, so that the IDE does not hang up during the
568      * startup process.
569      *
570      * @author Kirill Sorokin
571      */

572     private class WSStartDebugRunnable implements Runnable JavaDoc {
573         
574         /**
575          * Root directory for the selected profile
576          */

577         private String JavaDoc domainHome;
578         
579         /**
580          * Name of the selected server instance, it will be used as the
581          * parameter for the startup script
582          */

583         private String JavaDoc serverName;
584         
585         /**
586          * The debugger port that the JPDA debugger should connect to, basically
587          * this integer will be added to the server's startup command line, to
588          * make the JVM listen for debugger connection on this port
589          */

590         private String JavaDoc debuggerPort;
591         
592         /**
593          * Progress object that describes the startup process. It will be
594          * notified of the progress and the success/failure of the process
595          */

596         private WSServerProgress serverProgress;
597         
598         /**
599          * Creates a new instance of WSStartDebugRunnable.
600          *
601          * @param serverProgress the prgress object that the thread should
602          * notify of anything that happens with the startup process
603          */

604         public WSStartDebugRunnable(WSServerProgress serverProgress) {
605             // save the progress object
606
this.serverProgress = serverProgress;
607             
608             // get the profile root directory, the debugger port and the
609
// instance name from the deployment manager
610
domainHome = dm.getInstanceProperties().getProperty(
611                     WSDeploymentFactory.DOMAIN_ROOT_ATTR);
612             debuggerPort = dm.getInstanceProperties().getProperty(
613                     WSDeploymentFactory.DEBUGGER_PORT_ATTR);
614             serverName = dm.getInstanceProperties().getProperty(
615                     WSDeploymentFactory.SERVER_NAME_ATTR);
616         }
617         
618         /**
619          * Implementation of the run() method from the Runnable interface
620          */

621         public void run() {
622             try {
623                 // save the current time so that we can deduct that the startup
624
// failed due to timeout
625
long start = System.currentTimeMillis();
626                 
627                 // set the server's debug mode to true
628
setDebugMode(true, new Integer JavaDoc(debuggerPort).intValue());
629                 
630                 // create the startup process
631
Process JavaDoc serverProcess = Runtime.getRuntime().
632                         exec(new String JavaDoc[]{domainHome + "/bin/" + // NOI18N
633
(Utilities.isWindows() ? STARTUP_BAT : STARTUP_SH),
634                         serverName});
635                 
636                 // create a tailer to the server's output stream so that a user
637
// can observe the progress
638

639                 new WSTailer(serverProcess.getInputStream(),
640                         NbBundle.getMessage(WSStartServer.class,
641                         "TXT_ioWindowTitle",dm.getServerTitleMessage())).start(); // NOI18N
642

643                 // show the server's log
644
new WSTailer(new File(dm.getLogFilePath()),
645                         NbBundle.getMessage(ShowServerLogAction.class,
646                         "LBL_LogWindowTitle", dm.getServerTitleMessage())).
647                         start();
648                 
649                 // wait till the timeout happens, or if the server starts before
650
// send the completed event to j2eeserver
651
while (System.currentTimeMillis() - start < TIMEOUT) {
652                     // is the server is not yet running send the 'progressing'
653
// event, else send trhe 'completed' event and return
654
if (!isRunning()) {
655                         serverProgress.notifyStart(StateType.RUNNING,
656                                 ""); // NOI18N
657
} else {
658                         serverProgress.notifyStart(StateType.COMPLETED,
659                                 ""); // NOI18N
660

661                         // set the state to started
662
state = STATE_STARTED;
663                         
664                         return;
665                     }
666                     
667                     // sleep for a little so that we do not make our checks too
668
// often
669
try {
670                         Thread.sleep(DELAY);
671                     } catch (InterruptedException JavaDoc e) {}
672                 }
673                 
674                 // if the server did not start in the designated time limits
675
// we consider the startup as failed and kill the process
676
serverProgress.notifyStart(StateType.FAILED, ""); // NOI18N
677
serverProcess.destroy();
678                 
679                 // set the state to stopped
680
state = STATE_STOPPED;
681             } catch (IOException e) {
682                 ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
683             }
684         }
685         
686         /**
687          * The amount of time in milliseconds during which the server should
688          * start
689          */

690         private static final int TIMEOUT = 120000;
691         
692         /**
693          * The amount of time in milliseconds that we should wait between checks
694          */

695         private static final int DELAY = 5000;
696         
697         /**
698          * Name of the startup script for windows
699          */

700         private static final String JavaDoc STARTUP_SH = "startServer.sh"; // NOI18N
701

702         /**
703          * Name of the startup script for Unices
704          */

705         private static final String JavaDoc STARTUP_BAT = "startServer.bat"; // NOI18N
706
}
707     
708     /**
709      * Runnable that stops the server. It is used to stop the server in a
710      * separate thread, so that the IDE does not hang up during the stop
711      * process.
712      *
713      * @author Kirill Sorokin
714      */

715     private class WSStopRunnable implements Runnable JavaDoc {
716         
717         /**
718          * Root directory for the selected profile
719          */

720         private String JavaDoc domainHome;
721         
722         /**
723          * Name of the selected server instance, it will be used as the
724          * parameter for the stop script
725          */

726         private String JavaDoc serverName;
727         
728         /**
729          * Progress object that describes the stop process. It will be
730          * notified of the progress and the success/failure of the process
731          */

732         private WSServerProgress serverProgress;
733         
734         /**
735          * Creates a new instance of WSStopRunnable.
736          *
737          * @param serverProgress the prgress object that the thread should
738          * notify of anything that happens with the stop process
739          */

740         public WSStopRunnable(WSServerProgress serverProgress) {
741             // save the progress pbject
742
this.serverProgress = serverProgress;
743             
744             // get the profile home directory and the instance name from the
745
// deployment manager
746
domainHome = dm.getInstanceProperties().getProperty(
747                     WSDeploymentFactory.DOMAIN_ROOT_ATTR);
748             serverName = dm.getInstanceProperties().getProperty(
749                     WSDeploymentFactory.SERVER_NAME_ATTR);
750         }
751         
752         /**
753          * Implementation of the run() method from the Runnable interface
754          */

755         public void run() {
756             try {
757                 // save the current time so that we can deduct that the startup
758
// failed due to timeout
759
long start = System.currentTimeMillis();
760                 
761                 // create the stop process
762
Process JavaDoc serverProcess = Runtime.getRuntime().exec(
763                         new String JavaDoc[]{domainHome + "/bin/" + // NOI18N
764
(Utilities.isWindows() ? SHUTDOWN_BAT : SHUTDOWN_SH),
765                         serverName});
766                 
767                 // create a tailer to the server's output stream so that a user
768
// can observe the progress
769

770                 new WSTailer(serverProcess.getInputStream(),
771                         NbBundle.getMessage(WSStartServer.class,
772                         "TXT_ioWindowTitle", dm.getServerTitleMessage())).start(); // NOI18N
773

774                 // show the server's log
775
new WSTailer(new File(dm.getLogFilePath()),
776                         NbBundle.getMessage(ShowServerLogAction.class,
777                         "LBL_LogWindowTitle", dm.getServerTitleMessage())).start();
778                 
779                 // wait till the timeout happens, or if the server starts before
780
// send the completed event to j2eeserver
781
while (System.currentTimeMillis() - start < TIMEOUT) {
782                     if (isRunning()) {
783                         serverProgress.notifyStop(StateType.RUNNING, ""); // NOI18N
784
} else {
785                         serverProgress.notifyStop(StateType.COMPLETED, ""); // NOI18N
786

787                         // set the state to stopped
788
state = STATE_STOPPED;
789                         
790                         return;
791                     }
792                     
793                     // sleep for a little so that we do not make our checks too
794
// often
795
try {
796                         Thread.sleep(DELAY);
797                     } catch (InterruptedException JavaDoc e) {}
798                 }
799                 
800                 // if the server did not stop in the designated time limits
801
// we consider the stop process as failed and kill the process
802
serverProgress.notifyStop(StateType.FAILED, ""); // NOI18N
803
serverProcess.destroy();
804                 
805                 // set the state to started
806
state = STATE_STARTED;
807             } catch (IOException e) {
808                 ErrorManager.getDefault().notify(ErrorManager.EXCEPTION, e);
809             }
810         }
811         
812         /**
813          * The amount of time in milliseconds during which the server should
814          * stop
815          */

816         private static final int TIMEOUT = 120000;
817         
818         /**
819          * The amount of time in milliseconds that we should wait between checks
820          */

821         private static final int DELAY = 5000;
822         
823         /**
824          * Name of the shutdown script for windows
825          */

826         private static final String JavaDoc SHUTDOWN_SH = "stopServer.sh"; // NOI18N
827

828         /**
829          * Name of the shutdown script for unices
830          */

831         private static final String JavaDoc SHUTDOWN_BAT = "stopServer.bat"; // NOI18N
832
}
833     
834     /**
835      * An implementation of the ProgressObject interface targeted at tracking
836      * the server instance's startup/shutdown progress
837      *
838      * @author Kirill Sorokin
839      */

840     private static class WSServerProgress implements ProgressObject {
841         
842         /**
843          * Listeners vector
844          */

845         private Vector listeners = new Vector();
846         
847         /**
848          * Current startus of the startup/shutdown process
849          */

850         private DeploymentStatus deploymentStatus;
851         
852         /**
853          * Progress events source
854          */

855         private Object JavaDoc source;
856         
857         /**
858          * Creates a new instance of WSServerProgress. The source supplied will
859          * be used as the source for all the events. Ususally it is the parent
860          * WSStartServerObject
861          *
862          * @param source the events' source
863          */

864         public WSServerProgress(Object JavaDoc source) {
865             this.source = source;
866         }
867         
868         /**
869          * Sends a startup event to the listeners.
870          *
871          * @param state the new state of the startup process
872          * @param message the attached string message
873          */

874         public void notifyStart(StateType state, String JavaDoc message) {
875             // call the general notify method with the specific startup event
876
// parameters set
877
notify(new WSDeploymentStatus(ActionType.EXECUTE, CommandType.START, state, message));
878         }
879         
880         /**
881          * Sends a shutdown event to the listeners.
882          *
883          * @param state the new state of the shutdown process
884          * @param message the attached string message
885          */

886         public void notifyStop(StateType state, String JavaDoc message) {
887             // call the general notify method with the specific shutdown event
888
// parameters set
889
notify(new WSDeploymentStatus(ActionType.EXECUTE, CommandType.STOP, state, message));
890         }
891         
892         /**
893          * Notifies the listeners of the new process status
894          *
895          * @param deploymentStatus the new status of the startup/shutdown
896          * process
897          */

898         public void notify(DeploymentStatus deploymentStatus) {
899             // construct a new progress event from the source and the supplied
900
// new process status
901
ProgressEvent evt = new ProgressEvent(source, null, deploymentStatus);
902             
903             // update the saved process status
904
this.deploymentStatus = deploymentStatus;
905             
906             // get a copy of the listeners vector so that we do not get any
907
// conflicts when multithreading
908
java.util.Vector JavaDoc targets = null;
909             synchronized (this) {
910                 if (listeners != null) {
911                     targets = (java.util.Vector JavaDoc) listeners.clone();
912                 }
913             }
914             
915             // traverse the listeners, notifying each with the new event
916
if (targets != null) {
917                 for (int i = 0; i < targets.size(); i++) {
918                     ProgressListener target = (ProgressListener) targets.elementAt(i);
919                     target.handleProgressEvent(evt);
920                 }
921             }
922         }
923         
924         ////////////////////////////////////////////////////////////////////////////
925
// ProgressObject implementation
926
////////////////////////////////////////////////////////////////////////////
927
/**
928          * A dummy implementation of the ProgressObject method, since this
929          * method is not used anywhere, we omit the reasonable implementation
930          */

931         public ClientConfiguration getClientConfiguration(TargetModuleID targetModuleID) {
932             return null;
933         }
934         
935         /**
936          * Removes the registered listener
937          *
938          * @param progressListener the listener to be removed
939          */

940         public void removeProgressListener(ProgressListener progressListener) {
941             listeners.remove(progressListener);
942         }
943         
944         /**
945          * Adds a new listener
946          *
947          * @param progressListener the listener to be added
948          */

949         public void addProgressListener(ProgressListener progressListener) {
950             listeners.add(progressListener);
951         }
952         
953         /**
954          * Returns the current state of the startup/shutdown process
955          *
956          * @return current state of the process
957          */

958         public DeploymentStatus getDeploymentStatus() {
959             return deploymentStatus;
960         }
961         
962         /**
963          * A dummy implementation of the ProgressObject method, since this
964          * method is not used anywhere, we omit the reasonable implementation
965          */

966         public TargetModuleID[] getResultTargetModuleIDs() {
967             return new TargetModuleID[]{};
968         }
969         
970         /**
971          * A dummy implementation of the ProgressObject method, since this
972          * method is not used anywhere, we omit the reasonable implementation
973          */

974         public boolean isStopSupported() {
975             return false;
976         }
977         
978         /**
979          * A dummy implementation of the ProgressObject method, since this
980          * method is not used anywhere, we omit the reasonable implementation
981          */

982         public void stop() throws OperationUnsupportedException {
983             throw new OperationUnsupportedException(""); // NOI18N
984
}
985         
986         /**
987          * A dummy implementation of the ProgressObject method, since this
988          * method is not used anywhere, we omit the reasonable implementation
989          */

990         public boolean isCancelSupported() {
991             return false;
992         }
993         
994         /**
995          * A dummy implementation of the ProgressObject method, since this
996          * method is not used anywhere, we omit the reasonable implementation
997          */

998         public void cancel() throws OperationUnsupportedException {
999             throw new OperationUnsupportedException(""); // NOI18N
1000
}
1001    }
1002    
1003    /**
1004     * A class that describes the startup/shutdown process state. It is an
1005     * implementation of the DeploymentStatus interface.
1006     */

1007    private static class WSDeploymentStatus implements DeploymentStatus {
1008        /**
1009         * Current action
1010         */

1011        private ActionType action;
1012        
1013        /**
1014         * Current command
1015         */

1016        private CommandType command;
1017        
1018        /**
1019         * Current state
1020         */

1021        private StateType state;
1022        
1023        /**
1024         * Current message
1025         */

1026        private String JavaDoc message;
1027        
1028        /**
1029         * Creates a new WSDeploymentStatus object.
1030         *
1031         * @param action current action
1032         * @param command current command
1033         * @param state current state
1034         * @param message current message
1035         */

1036        public WSDeploymentStatus(ActionType action, CommandType command, StateType state, String JavaDoc message) {
1037            // save the supplied parameters
1038
this.action = action;
1039            this.command = command;
1040            this.state = state;
1041            this.message = message;
1042        }
1043        
1044        /**
1045         * Returns the current action
1046         *
1047         * @return current action
1048         */

1049        public ActionType getAction() {
1050            return action;
1051        }
1052        
1053        /**
1054         * Returns the current command
1055         *
1056         * @return current command
1057         */

1058        public CommandType getCommand() {
1059            return command;
1060        }
1061        
1062        /**
1063         * Returns the current message
1064         *
1065         * @return current message
1066         */

1067        public String JavaDoc getMessage() {
1068            return message;
1069        }
1070        
1071        /**
1072         * Returns the current state
1073         *
1074         * @return current state
1075         */

1076        public StateType getState() {
1077            return state;
1078        }
1079        
1080        /**
1081         * Tells whether the current action has completed successfully
1082         *
1083         * @return true if the action has completed successfully, false
1084         * otherwise
1085         */

1086        public boolean isCompleted() {
1087            return StateType.COMPLETED.equals(state);
1088        }
1089        
1090        /**
1091         * Tells whether the current action has failed
1092         *
1093         * @return true if the action has failed, false otherwise
1094         */

1095        public boolean isFailed() {
1096            return StateType.FAILED.equals(state);
1097        }
1098        
1099        /**
1100         * Tells whether the current action is still running
1101         *
1102         * @return true if the action is still running, false otherwise
1103         */

1104        public boolean isRunning() {
1105            return StateType.RUNNING.equals(state);
1106        }
1107    };
1108    
1109    ////////////////////////////////////////////////////////////////////////////
1110
// Constants section
1111
////////////////////////////////////////////////////////////////////////////
1112
// These constants introduce two additional states to the instance -
1113
// starting and stopping son that we can filter sunsequent requests.
1114
private static final int STATE_STOPPED = 0;
1115    private static final int STATE_STARTING = 1;
1116    private static final int STATE_STARTED = 2;
1117    private static final int STATE_STOPPING = 3;
1118}
Popular Tags