EMMA Coverage Report (generated Wed Oct 26 13:47:17 EDT 2011)
[all classes][org.jclouds.lifecycle]

COVERAGE SUMMARY FOR SOURCE FILE [BaseLifeCycle.java]

nameclass, %method, %block, %line, %
BaseLifeCycle.java0%   (0/1)0%   (0/14)0%   (0/335)0%   (0/81)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BaseLifeCycle0%   (0/1)0%   (0/14)0%   (0/335)0%   (0/81)
BaseLifeCycle (ExecutorService, LifeCycle []): void 0%   (0/1)0%   (0/33)0%   (0/9)
addDependency (LifeCycle): void 0%   (0/1)0%   (0/6)0%   (0/2)
awaitShutdown (long): void 0%   (0/1)0%   (0/5)0%   (0/2)
awaitStatus (LifeCycle$Status, long): void 0%   (0/1)0%   (0/41)0%   (0/11)
exceptionIfDepedenciesNotActive (): void 0%   (0/1)0%   (0/35)0%   (0/4)
exceptionIfNotActive (): void 0%   (0/1)0%   (0/18)0%   (0/3)
getException (): Exception 0%   (0/1)0%   (0/5)0%   (0/1)
getExceptionFromDependenciesOrNull (): Exception 0%   (0/1)0%   (0/20)0%   (0/4)
getStatus (): LifeCycle$Status 0%   (0/1)0%   (0/3)0%   (0/1)
run (): void 0%   (0/1)0%   (0/38)0%   (0/11)
shouldDoWork (): boolean 0%   (0/1)0%   (0/19)0%   (0/5)
shutdown (): void 0%   (0/1)0%   (0/4)0%   (0/2)
shutdown (long): void 0%   (0/1)0%   (0/30)0%   (0/9)
start (): void 0%   (0/1)0%   (0/78)0%   (0/17)

1/**
2 * Licensed to jclouds, Inc. (jclouds) under one or more
3 * contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  jclouds licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.jclouds.lifecycle;
20 
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.List;
24import java.util.concurrent.ExecutorService;
25import java.util.concurrent.atomic.AtomicReference;
26 
27import javax.annotation.PostConstruct;
28import javax.annotation.PreDestroy;
29import javax.annotation.Resource;
30 
31import org.jclouds.logging.Logger;
32 
33/**
34 * // TODO: Adrian: Document this!
35 * 
36 * @author Adrian Cole
37 */
38public abstract class BaseLifeCycle implements Runnable, LifeCycle {
39   @Resource
40   protected Logger logger = Logger.NULL;
41   
42   protected final ExecutorService executorService;
43   protected final List<LifeCycle> dependencies;
44   protected final Object statusLock;
45   protected volatile Status status;
46   protected AtomicReference<Exception> exception = new AtomicReference<Exception>();
47 
48   public BaseLifeCycle(ExecutorService executor, LifeCycle... dependencies) {
49      this.executorService = executor;
50      this.dependencies = new ArrayList<LifeCycle>();
51      this.dependencies.addAll(Arrays.asList(dependencies));
52      this.statusLock = new Object();
53      this.status = Status.INACTIVE;
54   }
55 
56   public void addDependency(LifeCycle lifeCycle) {
57      dependencies.add(lifeCycle);
58   }
59 
60   public Status getStatus() {
61      return status;
62   }
63 
64   public void run() {
65      try {
66         while (shouldDoWork()) {
67            doWork();
68         }
69      } catch (Exception e) {
70         logger.error(e, "Exception doing work");
71         exception.set(e);
72      }
73      this.status = Status.SHUTTING_DOWN;
74      doShutdown();
75      this.status = Status.SHUT_DOWN;
76      logger.info("Shutdown %s", this);
77   }
78 
79   protected abstract void doWork() throws Exception;
80 
81   protected abstract void doShutdown();
82 
83   /**
84    * @return false if any dependencies are inactive, or we are inactive, or we have a global
85    *         exception.
86    */
87   protected boolean shouldDoWork() {
88      try {
89         exceptionIfDepedenciesNotActive();
90      } catch (IllegalStateException e) {
91         return false;
92      }
93      return status.equals(Status.ACTIVE) && exception.get() == null;
94   }
95 
96   @PostConstruct
97   public void start() {
98      logger.info("Starting %s", this);
99      synchronized (this.statusLock) {
100         if (this.status.compareTo(Status.SHUTDOWN_REQUEST) >= 0) {
101            doShutdown();
102            this.status = Status.SHUT_DOWN;
103            this.statusLock.notifyAll();
104            return;
105         }
106         if (this.status.compareTo(Status.ACTIVE) == 0) {
107            this.statusLock.notifyAll();
108            return;
109         }
110 
111         if (this.status.compareTo(Status.INACTIVE) != 0) {
112            throw new IllegalStateException("Illegal state: " + this.status);
113         }
114 
115         exceptionIfDepedenciesNotActive();
116 
117         this.status = Status.ACTIVE;
118      }
119      executorService.execute(this);
120   }
121 
122   protected void exceptionIfDepedenciesNotActive() {
123      for (LifeCycle dependency : dependencies) {
124         if (dependency.getStatus().compareTo(Status.ACTIVE) != 0) {
125            throw new IllegalStateException(String.format("Illegal state: %s for component: %s",
126                     dependency.getStatus(), dependency));
127         }
128      }
129   }
130 
131   protected Exception getExceptionFromDependenciesOrNull() {
132      for (LifeCycle dependency : dependencies) {
133         if (dependency.getException() != null) {
134            return dependency.getException();
135         }
136      }
137      return null;
138   }
139 
140   public Exception getException() {
141      return this.exception.get();
142   }
143 
144   protected void awaitShutdown(long timeout) throws InterruptedException {
145      awaitStatus(Status.SHUT_DOWN, timeout);
146   }
147 
148   protected void awaitStatus(Status intended, long timeout) throws InterruptedException {
149      synchronized (this.statusLock) {
150         long deadline = System.currentTimeMillis() + timeout;
151         long remaining = timeout;
152         while (this.status != intended) {
153            this.statusLock.wait(remaining);
154            if (timeout > 0) {
155               remaining = deadline - System.currentTimeMillis();
156               if (remaining <= 0) {
157                  break;
158               }
159            }
160         }
161      }
162   }
163 
164   @PreDestroy
165   public void shutdown() {
166      shutdown(2000);
167   }
168 
169   public void shutdown(long waitMs) {
170      synchronized (this.statusLock) {
171         if (this.status.compareTo(Status.ACTIVE) > 0) {
172            return;
173         }
174         this.status = Status.SHUTDOWN_REQUEST;
175         try {
176            awaitShutdown(waitMs);
177         } catch (InterruptedException ignore) {
178         }
179      }
180   }
181 
182   protected void exceptionIfNotActive() {
183      if (!status.equals(Status.ACTIVE))
184         throw new IllegalStateException(String.format("not active: %s", this));
185   }
186 
187}

[all classes][org.jclouds.lifecycle]
EMMA 2.0.5312 (C) Vladimir Roubtsov