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: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.tomcat5.nodes;
043:
044: import java.util.Comparator;
045: import javax.enterprise.deploy.spi.DeploymentManager;
046: import javax.enterprise.deploy.spi.TargetModuleID;
047: import javax.enterprise.deploy.spi.status.ProgressListener;
048: import javax.enterprise.deploy.spi.status.ProgressObject;
049: import javax.enterprise.deploy.shared.StateType;
050: import javax.enterprise.deploy.shared.CommandType;
051: import org.netbeans.modules.tomcat5.TomcatModule;
052: import org.netbeans.modules.tomcat5.nodes.actions.TomcatWebModuleCookie;
053: import org.openide.awt.StatusDisplayer;
054: import org.openide.nodes.Node;
055: import org.openide.util.RequestProcessor.Task;
056: import org.openide.util.NbBundle;
057: import org.openide.util.RequestProcessor;
058: import org.openide.NotifyDescriptor;
059: import org.openide.DialogDisplayer;
060: import javax.enterprise.deploy.spi.status.ProgressEvent;
061: import javax.enterprise.deploy.spi.status.DeploymentStatus;
062: import org.netbeans.modules.tomcat5.TomcatManager;
063: import org.openide.util.Parameters;
064:
065: /**
066: *
067: * @author Petr Pisl
068: * @author Petr Hejl
069: */
070: public class TomcatWebModule implements TomcatWebModuleCookie {
071:
072: /** Simple comparator for sorting nodes by name. */
073: public static final Comparator<TomcatWebModule> TOMCAT_WEB_MODULE_COMPARATOR = new Comparator<TomcatWebModule>() {
074:
075: public int compare(TomcatWebModule wm1, TomcatWebModule wm2) {
076: return wm1.getTomcatModule().getModuleID().compareTo(
077: wm2.getTomcatModule().getModuleID());
078: }
079: };
080:
081: private final TomcatModule tomcatModule;
082: private final TomcatManager manager;
083:
084: private volatile boolean isRunning;
085:
086: private Node node;
087:
088: private final TargetModuleID[] target;
089:
090: /** Creates a new instance of TomcatWebModule */
091: public TomcatWebModule(DeploymentManager manager,
092: TomcatModule tomcatModule, boolean isRunning) {
093: this .tomcatModule = tomcatModule;
094: this .manager = (TomcatManager) manager;
095: this .isRunning = isRunning;
096: target = new TargetModuleID[] { tomcatModule };
097: }
098:
099: public TomcatModule getTomcatModule() {
100: return tomcatModule;
101: }
102:
103: public void setRepresentedNode(Node node) {
104: this .node = node;
105: }
106:
107: public Node getRepresentedNode() {
108: return node;
109: }
110:
111: public DeploymentManager getDeploymentManager() {
112: return manager;
113: }
114:
115: /**
116: * Undeploys the web application described by this module.
117: *
118: * @return task in which the undeployment itself is processed. When the
119: * task is finished it implicate that undeployment is finished
120: * (failed or completed).
121: */
122: public Task undeploy() {
123: return RequestProcessor.getDefault().post(new Runnable() {
124: public void run() {
125: StatusDisplayer.getDefault().setStatusText(
126: NbBundle.getMessage(TomcatWebModule.class,
127: "MSG_START_UNDEPLOY", // NOI18N
128: new Object[] { getTomcatModule()
129: .getPath() }));
130:
131: ProgressObject po = manager.undeploy(target);
132: TomcatProgressListener listener = new TomcatProgressListener(
133: po);
134: po.addProgressListener(listener);
135: listener.updateState();
136:
137: CompletionWait wait = new CompletionWait(po);
138: wait.init();
139: wait.waitFinished();
140: }
141: }, 0);
142: }
143:
144: public void start() {
145: RequestProcessor.getDefault().post(new Runnable() {
146: public void run() {
147: StatusDisplayer.getDefault().setStatusText(
148: NbBundle.getMessage(TomcatWebModule.class,
149: "MSG_START_STARTING", // NOI18N
150: new Object[] { getTomcatModule()
151: .getPath() }));
152: ProgressObject po = manager.start(target);
153: TomcatProgressListener listener = new TomcatProgressListener(
154: po);
155: po.addProgressListener(listener);
156: listener.updateState();
157: }
158: }, 0);
159: }
160:
161: public void stop() {
162: RequestProcessor.getDefault().post(new Runnable() {
163: public void run() {
164: StatusDisplayer.getDefault().setStatusText(
165: NbBundle.getMessage(TomcatWebModule.class,
166: "MSG_START_STOPPING", // NOI18N
167: new Object[] { getTomcatModule()
168: .getPath() }));
169: ProgressObject po = manager.stop(target);
170: TomcatProgressListener listener = new TomcatProgressListener(
171: po);
172: po.addProgressListener(listener);
173: listener.updateState();
174: }
175: }, 0);
176: }
177:
178: public boolean isRunning() {
179: return isRunning;
180: }
181:
182: private String constructDisplayName() {
183: if (isRunning())
184: return getTomcatModule().getPath();
185: else
186: return getTomcatModule().getPath()
187: + " ["
188: + NbBundle.getMessage(TomcatWebModuleNode.class,
189: "LBL_Stopped") // NOI18N
190: + "]";
191: }
192:
193: /**
194: * Opens the log file defined for this web moudel in the ouput window.
195: */
196: public void openLog() {
197: manager.logManager().openContextLog(tomcatModule);
198: }
199:
200: /**
201: * Returns <code>true</code> if there is a logger defined for this module,
202: * <code>false</code> otherwise.
203: *
204: * @return <code>true</code> if there is a logger defined for this module,
205: * <code>false</code> otherwise.
206: */
207: public boolean hasLogger() {
208: return manager.logManager().hasContextLogger(tomcatModule);
209: }
210:
211: private class TomcatProgressListener implements ProgressListener {
212:
213: private final ProgressObject progressObject;
214:
215: private boolean finished;
216:
217: public TomcatProgressListener(ProgressObject progressObject) {
218: this .progressObject = progressObject;
219: }
220:
221: public void handleProgressEvent(ProgressEvent progressEvent) {
222: updateState();
223: }
224:
225: public synchronized void updateState() {
226: if (finished) {
227: return;
228: }
229:
230: DeploymentStatus deployStatus = progressObject
231: .getDeploymentStatus();
232: if (deployStatus == null) {
233: return;
234: }
235:
236: if (deployStatus.isCompleted() || deployStatus.isFailed()) {
237: finished = true;
238: }
239:
240: if (deployStatus.getState() == StateType.COMPLETED) {
241: CommandType command = deployStatus.getCommand();
242:
243: if (command == CommandType.START
244: || command == CommandType.STOP) {
245: StatusDisplayer.getDefault().setStatusText(
246: deployStatus.getMessage());
247: if (command == CommandType.START) {
248: isRunning = true;
249: } else {
250: isRunning = false;
251: }
252: node.setDisplayName(constructDisplayName());
253: } else if (command == CommandType.UNDEPLOY) {
254: StatusDisplayer.getDefault().setStatusText(
255: deployStatus.getMessage());
256: }
257: } else if (deployStatus.getState() == StateType.FAILED) {
258: NotifyDescriptor notDesc = new NotifyDescriptor.Message(
259: deployStatus.getMessage(),
260: NotifyDescriptor.ERROR_MESSAGE);
261: DialogDisplayer.getDefault().notify(notDesc);
262: StatusDisplayer.getDefault().setStatusText(
263: deployStatus.getMessage());
264: }
265: }
266: }
267:
268: /**
269: * Helper class for blocking wait until the deployment manager operation
270: * gets finished.
271: * <p>
272: * The class is <i>thread safe</i>.
273: *
274: * @author Petr Hejl
275: */
276: private static class CompletionWait implements ProgressListener {
277:
278: private final ProgressObject progressObject;
279:
280: private boolean completed;
281:
282: /**
283: * Constructs the CompletionWait object that will wait for
284: * given ProgressObject.
285: *
286: * @param progressObject object that we want to wait for
287: * must not be <code>null</code>
288: */
289: public CompletionWait(ProgressObject progressObject) {
290: Parameters.notNull("progressObject", progressObject);
291:
292: this .progressObject = progressObject;
293: }
294:
295: /**
296: * Initialize this object. Until calling this method any thread that
297: * has called {@link #waitFinished()} will wait unconditionaly (does not
298: * matter what is the state of the ProgressObject.
299: */
300: public void init() {
301: synchronized (this ) {
302: progressObject.addProgressListener(this );
303: // to be sure we didn't missed the state
304: handleProgressEvent(null);
305: }
306: }
307:
308: /**
309: * Handles the progress. May lead to notifying threads waiting in
310: * {@link #waitFinished()}.
311: *
312: * @param evt event to handle
313: */
314: public void handleProgressEvent(ProgressEvent evt) {
315: synchronized (this ) {
316: DeploymentStatus status = progressObject
317: .getDeploymentStatus();
318: if (status.isCompleted() || status.isFailed()) {
319: completed = true;
320: notifyAll();
321: }
322: }
323: }
324:
325: /**
326: * Block the calling thread until the progress object indicates the
327: * competion or failure. If the task described by ProgressObject is
328: * already finished returns immediately.
329: */
330: public void waitFinished() {
331: synchronized (this ) {
332: if (completed) {
333: return;
334: }
335:
336: while (!completed) {
337: try {
338: wait();
339: } catch (InterruptedException ex) {
340: // don't response to interrupt
341: }
342: }
343: }
344: }
345: }
346: }
|