KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > deployapi > ProgressObjectSink


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.deployapi;
25
26 import java.util.Collection JavaDoc;
27 import java.util.Vector JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import javax.enterprise.deploy.spi.status.ProgressListener JavaDoc;
30 import javax.enterprise.deploy.spi.status.ProgressEvent JavaDoc;
31 import javax.enterprise.deploy.spi.status.ProgressObject JavaDoc;
32 import javax.enterprise.deploy.spi.status.DeploymentStatus JavaDoc;
33 import javax.enterprise.deploy.spi.TargetModuleID JavaDoc;
34 import javax.enterprise.deploy.shared.StateType JavaDoc;
35 import javax.enterprise.deploy.spi.exceptions.OperationUnsupportedException JavaDoc;
36 import com.sun.enterprise.util.LocalStringManagerImpl;
37 import com.sun.enterprise.deployment.client.JESProgressObject;
38 import com.sun.enterprise.deployment.client.DeploymentClientUtils;
39
40 /**
41  * This class acts as a sink for ProgressObject. It registers itself
42  * as ProgressObject listener for multiple deployment actions and
43  * tunnel all events to registered ProgressObject listener.
44  *<p>
45  *Whenever this class receives a progress event from one of its sources (one of the deploymentFacility
46  *actions) it forwards that event on to the sink's listeners, changing the state of the event to
47  *"running." Then, after the sink receives the completion or failure event from the last source,
48  *it forwards that event as running (as it had all earlier events) and then sends one final
49  *aggregate completion or failure event.
50  *<p>
51  *The sink always follows this pattern, even if it encapsulates only a single source. JSR88 clients should
52  *be aware of this behavior.
53  *
54  * @author Jerome Dochez
55  */

56 public class ProgressObjectSink implements JESProgressObject, ProgressListener JavaDoc {
57     
58     private static String JavaDoc LINE_SEPARATOR = System.getProperty("line.separator");
59     private Vector JavaDoc registeredPL = new Vector JavaDoc();
60     private Vector JavaDoc deliveredEvents = new Vector JavaDoc();
61     
62     /* aggregate state starts as successful and is changed only if at least one source operation fails */
63     private StateType JavaDoc finalStateType = StateType.COMPLETED;
64     private String JavaDoc finalMessage;
65     
66     private Vector JavaDoc targetModuleIDs = new Vector JavaDoc();
67     private Vector JavaDoc sources = new Vector JavaDoc();
68         
69     private static LocalStringManagerImpl localStrings =
70         new LocalStringManagerImpl(ProgressObjectSink.class);
71     
72     private com.sun.enterprise.deployment.backend.DeploymentStatus completedStatus = new com.sun.enterprise.deployment.backend.DeploymentStatus();
73     private boolean completedStatusReady = false;
74     
75     /**
76      * register to a new ProgressObject for ProgressEvent notifications
77      */

78     public void sinkProgressObject(ProgressObject JavaDoc source) {
79         /*
80          *The following two statements must appear in the order shown. Otherwise, a race condition can exist.
81          */

82         sources.add(source);
83         source.addProgressListener(this);
84     }
85     
86     /**
87      * receives notification of a progress event from one of our
88      * registered interface.
89      */

90     public void handleProgressEvent(ProgressEvent JavaDoc progressEvent) {
91         
92         ProgressEvent JavaDoc forwardedEvent;
93         DeploymentStatus JavaDoc forwardedDS = progressEvent.getDeploymentStatus();
94         
95         // we intercept all events...
96
if (!forwardedDS.isRunning()) {
97             // this mean we are either completed or failed...
98
if (forwardedDS.isFailed()) {
99                 /*
100                  *Once at least one operation fails, we know that the aggregate state will have
101                  *to be failed.
102                  */

103                 finalStateType = StateType.FAILED;
104             }
105             
106             // since this is the completion event
107
// we are done with that progress listener;
108
Object JavaDoc source = progressEvent.getSource();
109             if (source instanceof ProgressObject JavaDoc) {
110                 ProgressObject JavaDoc po = (ProgressObject JavaDoc) source;
111                 po.removeProgressListener(this);
112                 
113                 sources.remove(source);
114                 
115                 if (forwardedDS.isCompleted()) {
116                 
117                     TargetModuleID JavaDoc[] ids = po.getResultTargetModuleIDs();
118                     for (int i=0;i<ids.length;i++) {
119                         targetModuleIDs.add(ids[i]);
120                     }
121                 }
122             } else {
123                 throw new RuntimeException JavaDoc(localStrings.getLocalString(
124                     "enterprise.deployment.client.noprogressobject",
125                     "Progress event does not contain a ProgressObject source"
126                     ));
127             }
128             
129             /*
130              *Update the completionStatus by adding a stage to it and recording the completion
131              *of this event as the newest stage.
132              */

133             updateCompletedStatus(forwardedDS);
134             
135             // now we change our event state to running. We always forward every event from a
136
// source to the listeners with "running" status because the sink is not yet completely
137
// finished. We will also send a final aggregate completion event
138
// if this is a completion event from our last source (see below).
139
DeploymentStatusImpl forwardedStatus = new DeploymentStatusImpl();
140             forwardedStatus.setState(StateType.RUNNING);
141             forwardedStatus.setMessage(forwardedDS.getMessage());
142             forwardedStatus.setCommand(forwardedDS.getCommand());
143             forwardedEvent = new ProgressEvent JavaDoc(this, progressEvent.getTargetModuleID(), forwardedStatus);
144         } else {
145             // This is a "running" event from one of our sources, so we just need to swap the source...
146
forwardedEvent = new ProgressEvent JavaDoc(this, progressEvent.getTargetModuleID(),
147                 forwardedDS);
148         }
149         
150         // we need to fire the received event to our listeners
151
Collection JavaDoc clone;
152         ProgressEvent JavaDoc finalEvent = null;
153         
154         synchronized(registeredPL) {
155             clone = (Collection JavaDoc) registeredPL.clone();
156             deliveredEvents.add(forwardedEvent);
157             /*
158              *If we are done with all of our sources, let's wrap up by creating a final event that will
159              *be broadcast to the listeners along with the forwarded event. Also create the completed status
160              *that meets the requirements of the JESProgressObject interface.
161              */

162             if (sources.isEmpty()) {
163                 prepareCompletedStatus();
164                 DeploymentStatusImpl status = new DeploymentStatusImpl();
165                 status.setState(finalStateType);
166                 if (finalStateType.equals(StateType.FAILED)) {
167                     status.setMessage(localStrings.getLocalString(
168                         "enterprise.deployment.client.aggregatefailure",
169                         "At least one operation failed"
170                         ));
171                 } else {
172                     status.setMessage(localStrings.getLocalString(
173                         "enterprise.deployment.client.aggregatesuccess",
174                         "All operations completed successfully"
175                         ));
176                 }
177                 finalEvent = new ProgressEvent JavaDoc(this, null, status);
178                 deliveredEvents.add(finalEvent);
179             }
180         }
181         
182         for (Iterator JavaDoc itr=clone.iterator();itr.hasNext();) {
183             ProgressListener JavaDoc pl = (ProgressListener JavaDoc) itr.next();
184             pl.handleProgressEvent(forwardedEvent);
185         }
186
187         /*
188          *Send the final event if there is one.
189          */

190         if (finalEvent != null) {
191             for (Iterator JavaDoc itr=clone.iterator();itr.hasNext();) {
192                 ProgressListener JavaDoc pl = (ProgressListener JavaDoc) itr.next();
193                 pl.handleProgressEvent(finalEvent);
194             }
195         }
196     }
197     
198     
199     /**
200      * Register a new ProgressListener
201      * @param the new listener instance
202      */

203     public void addProgressListener(ProgressListener JavaDoc progressListener) {
204         
205     Collection JavaDoc clone;
206         synchronized(registeredPL) {
207             registeredPL.add(progressListener);
208         
209             // now let's deliver all the events we already received.
210
clone = (Collection JavaDoc) deliveredEvents.clone();
211         }
212         
213         for (Iterator JavaDoc itr=clone.iterator();itr.hasNext();) {
214             ProgressEvent JavaDoc pe = (ProgressEvent JavaDoc) itr.next();
215             progressListener.handleProgressEvent(pe);
216         }
217     }
218     
219     /**
220      * removes a ProgressListener from our list of listeners
221      * @param the ProgressListener to remove
222      */

223     public void removeProgressListener(ProgressListener JavaDoc progressListener) {
224         registeredPL.remove(progressListener);
225     }
226     
227     
228     public javax.enterprise.deploy.spi.status.ClientConfiguration JavaDoc getClientConfiguration(TargetModuleID JavaDoc targetModuleID) {
229         // since we are never called upon deploying, I don't
230
// have to deal with this at this time.
231
return null;
232     }
233     
234     public DeploymentStatus JavaDoc getDeploymentStatus() {
235         DeploymentStatusImpl status = new DeploymentStatusImpl();
236         if (sources.isEmpty()) {
237             status.setState(finalStateType);
238             status.setMessage(finalMessage);
239         } else {
240             status.setState(StateType.RUNNING);
241         }
242         return status;
243     }
244     
245     public TargetModuleID JavaDoc[] getResultTargetModuleIDs() {
246         
247         TargetModuleID JavaDoc[] ids = new TargetModuleID JavaDoc[targetModuleIDs.size()];
248         targetModuleIDs.copyInto(ids);
249         return ids;
250     }
251     
252     public boolean isCancelSupported() {
253         
254         // if only one of our sources does not support cancel, we don't
255
for (Iterator JavaDoc itr=getSources().iterator();itr.hasNext();) {
256             ProgressObject JavaDoc source = (ProgressObject JavaDoc) itr.next();
257             if (!source.isCancelSupported()) {
258                 return false;
259             }
260         }
261         return true;
262     }
263     
264     public boolean isStopSupported() {
265         
266         // if only one of our sources does not support stop, we don't
267
for (Iterator JavaDoc itr=getSources().iterator();itr.hasNext();) {
268             ProgressObject JavaDoc source = (ProgressObject JavaDoc) itr.next();
269             if (!source.isStopSupported()) {
270                 return false;
271             }
272         }
273         return true;
274     }
275     
276     public void cancel() throws OperationUnsupportedException JavaDoc {
277         if (!isCancelSupported()) {
278             throw new OperationUnsupportedException JavaDoc("cancel");
279         }
280         for (Iterator JavaDoc itr=getSources().iterator();itr.hasNext();) {
281             ProgressObject JavaDoc source = (ProgressObject JavaDoc) itr.next();
282             source.cancel();
283         }
284     }
285     
286     public void stop() throws OperationUnsupportedException JavaDoc {
287         if (!isStopSupported()) {
288             throw new OperationUnsupportedException JavaDoc("stop");
289         }
290         for (Iterator JavaDoc itr=getSources().iterator();itr.hasNext();) {
291             ProgressObject JavaDoc source = (ProgressObject JavaDoc) itr.next();
292             source.stop();
293         }
294         
295     }
296     
297     private Collection JavaDoc getSources() {
298         return (Collection JavaDoc) sources.clone();
299     }
300     
301     private void prepareCompletedStatus() {
302         /*
303          *The substages may have status values of success when in fact a warning is present
304          *in a substage. Traverse all the substages, composing the true aggregate state and
305          *message based on the most severe state that is present in the entire stage tree.
306          */

307         int worstStatus = com.sun.enterprise.deployment.backend.DeploymentStatus.NOTINITIALIZED;
308         StringBuffer JavaDoc msgs = new StringBuffer JavaDoc();
309
310         int newWorstStatus = aggregateStages(worstStatus, msgs, completedStatus);
311         completedStatus.setStageStatus(newWorstStatus);
312         completedStatus.setStageStatusMessage(msgs.toString());
313         
314         completedStatusReady = true;
315     }
316     
317     private int aggregateStages(int worstStatusSoFar, StringBuffer JavaDoc msgs, com.sun.enterprise.deployment.backend.DeploymentStatus stage) {
318         /*
319          *Starting with the stage passed in, see if its severity is more urgent than that seen so far.
320          *If so, then discard the messages accumulated so far for the less urgent severity and save
321          *this stage's message and severity as the worst seen so far.
322          */

323         int stageStatus = stage.getStageStatus();
324         if (stageStatus < worstStatusSoFar) {
325             worstStatusSoFar = stageStatus;
326             msgs.delete(0,msgs.length());
327         }
328         
329         /*
330          *If the stage's severity is the same as the currently worst seen, then add this stage's message
331          *to the aggregate message.
332          */

333         if (stageStatus == worstStatusSoFar) {
334             msgs.append(stage.getStageStatusMessage()).append(LINE_SEPARATOR);
335         }
336         
337         /*
338          *Now, do the same for each substage.
339          */

340         for (Iterator JavaDoc it = stage.getSubStages(); it.hasNext(); ) {
341             com.sun.enterprise.deployment.backend.DeploymentStatus substage = (com.sun.enterprise.deployment.backend.DeploymentStatus) it.next();
342             worstStatusSoFar = aggregateStages(worstStatusSoFar, msgs, substage);
343         }
344         
345         return worstStatusSoFar;
346     }
347     
348     /**
349      *Report completed status for deploytool.
350      *@return null if not completed, or the backend.DeploymentStatus set to reflect the completion
351      */

352     public com.sun.enterprise.deployment.backend.DeploymentStatus getCompletedStatus() {
353     com.sun.enterprise.deployment.backend.DeploymentStatus answer = null;
354         if (completedStatusReady) {
355             answer = completedStatus;
356         }
357         return answer;
358     }
359
360     private void updateCompletedStatus(DeploymentStatus JavaDoc ds) {
361         /*
362          *If the status passed in is already a backend.DeploymentStatus then add it as a new stage to the
363          *completed status. Otherwise, create a new backend.DeploymentStatus, fill it in as much as
364          *possible, and add it as the next stage.
365          */

366         
367         com.sun.enterprise.deployment.backend.DeploymentStatus newStageStatus = null;
368         if (ds instanceof DeploymentStatusImpl) {
369             DeploymentStatusImpl dsi = (DeploymentStatusImpl) ds;
370             newStageStatus = dsi.progressObject.getCompletedStatus();
371         } else {
372             /*
373              *Create a new status stage and add it to the completed status.
374              */

375             newStageStatus = new com.sun.enterprise.deployment.backend.DeploymentStatus(completedStatus);
376             /*
377              *The new state status depends on the DeploymentStatus outcome.
378              */

379             String JavaDoc msgKey = null;
380             int stageStatus = -1;
381             Throwable JavaDoc exc;
382
383             reviseStatusAndMessage(ds, newStageStatus);
384         }
385         if (newStageStatus != null) {
386             /*
387              *Update the final status state if this new stage's state is worse than the final status's
388              *current state.
389              */

390             completedStatus.addSubStage(newStageStatus);
391             /*
392              *The status being reported may say it is successful but there could be warnings in substages
393              *(or substages of substages...). So the truly final state and message for the completed
394              *status is determined once, after the last source of events is removed.
395              */

396         } else {
397             System.err.println("A newStageStatus was null");
398         }
399     }
400     
401     private void reviseStatusAndMessage(DeploymentStatus JavaDoc ds, com.sun.enterprise.deployment.backend.DeploymentStatus newStageStatus) {
402         String JavaDoc msgKey = null;
403         int stageStatus = -1;
404         
405         if (ds.isCompleted()) {
406             /*
407              *The deployment status for this source was successful.
408              */

409             msgKey = "enterprise.deployment.client.action_completed";
410             stageStatus = com.sun.enterprise.deployment.backend.DeploymentStatus.SUCCESS;
411         } else {
412             /*
413              *The deployment status for this source failed.
414              */

415             msgKey = "enterprise.deployment.client.action_failed";
416             stageStatus = com.sun.enterprise.deployment.backend.DeploymentStatus.FAILURE;
417         }
418
419         String JavaDoc i18msg = localStrings.getLocalString(msgKey, ds.getMessage());
420         newStageStatus.setStageStatus(stageStatus);
421         newStageStatus.setStageStatusMessage(i18msg);
422     }
423 }
424
Popular Tags