001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.kernel.config;
018
019 import java.util.LinkedHashSet;
020 import java.util.Iterator;
021 import java.util.Set;
022
023 import org.apache.geronimo.kernel.repository.Artifact;
024
025 /**
026 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
027 */
028 public class ConfigurationStatus {
029 private Artifact configurationId;
030 private final Set loadParents = new LinkedHashSet();
031 private final Set startParents = new LinkedHashSet();
032 private final LinkedHashSet loadChildren = new LinkedHashSet();
033 private final LinkedHashSet startChildren = new LinkedHashSet();
034 private boolean loaded = false;
035 private boolean started = false;
036 private boolean userLoaded = false;
037 private boolean userStarted = false;
038
039 public ConfigurationStatus(Artifact configId, Set loadParents, Set startParents) {
040 if (configId == null) throw new NullPointerException("configId is null");
041 if (loadParents == null) throw new NullPointerException("loadParents is null");
042 if (startParents == null) throw new NullPointerException("startParents is null");
043 if (!loadParents.containsAll(startParents)) {
044 throw new IllegalArgumentException("loadParents must contain all startParents");
045 }
046 this.configurationId = configId;
047 this.loadParents.addAll(loadParents);
048 this.startParents.addAll(startParents);
049
050 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
051 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
052 loadParent.loadChildren.add(this);
053 }
054
055 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
056 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
057 startParent.startChildren.add(this);
058 }
059 }
060
061 public void destroy() {
062 if (started) {
063 throw new IllegalStateException("Configuration " + configurationId + " is still running");
064 }
065 if (loaded) {
066 throw new IllegalStateException("Configuration " + configurationId + " is still loaded");
067 }
068 if (loadChildren.size() > 0 || startChildren.size() > 0) {
069 throw new IllegalStateException("Configuration " + configurationId + " still has children");
070 }
071
072 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
073 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
074 loadParent.loadChildren.remove(this);
075 }
076 loadParents.clear();
077
078 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
079 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
080 startParent.startChildren.remove(this);
081 }
082 startChildren.clear();
083 }
084
085 public Artifact getConfigurationId() {
086 return configurationId;
087 }
088
089 public LinkedHashSet getStartedChildren() {
090 LinkedHashSet childrenStatuses = new LinkedHashSet();
091 getStartedChildrenInternal(childrenStatuses);
092
093 LinkedHashSet childrenIds = new LinkedHashSet(childrenStatuses.size());
094 for (Iterator iterator = childrenStatuses.iterator(); iterator.hasNext();) {
095 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
096 childrenIds.add(configurationStatus.configurationId);
097 }
098
099 return childrenIds;
100 }
101
102 private void getStartedChildrenInternal(LinkedHashSet childrenStatuses) {
103 // if we aren't started, there is nothing to do
104 if (!started) {
105 return;
106 }
107
108 // visit all children
109 for (Iterator iterator = startChildren.iterator(); iterator.hasNext();) {
110 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
111 if (child.isStarted() && !child.configurationId.equals(configurationId)) {
112 child.getStartedChildrenInternal(childrenStatuses);
113 }
114 }
115 childrenStatuses.add(this);
116 }
117
118 public boolean isLoaded() {
119 return loaded;
120 }
121
122 public boolean isStarted() {
123 return started;
124 }
125
126 public boolean isUserLoaded() {
127 return userLoaded;
128 }
129
130 public boolean isUserStarted() {
131 return userStarted;
132 }
133
134
135 public void upgrade(Artifact newId, Set newLoadParents, Set newStartParents) {
136 this.configurationId = newId;
137
138 //
139 // remove links from the current parents to me
140 //
141 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
142 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
143 loadParent.loadChildren.remove(this);
144 }
145 loadParents.clear();
146
147 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
148 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
149 startParent.startChildren.remove(this);
150 }
151 startChildren.clear();
152
153 //
154 // connect to to the new parents
155 //
156 this.loadParents.addAll(newLoadParents);
157 this.startParents.addAll(newStartParents);
158
159 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
160 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
161 loadParent.loadChildren.add(this);
162 }
163
164 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
165 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
166 startParent.startChildren.add(this);
167 }
168 }
169
170 public LinkedHashSet load() {
171 LinkedHashSet loadList = new LinkedHashSet();
172 loadInternal(loadList);
173 userLoaded = true;
174 return loadList;
175 }
176
177 private void loadInternal(LinkedHashSet loadList) {
178 // visit all unloaded parents
179 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
180 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
181 if (!parent.isLoaded()) {
182 parent.loadInternal(loadList);
183 }
184 }
185
186 if (!loaded) {
187 loadList.add(configurationId);
188 loaded = true;
189 }
190 }
191
192
193 public LinkedHashSet start() {
194 if (!loaded) {
195 throw new IllegalStateException(configurationId + " is not loaded");
196 }
197 LinkedHashSet startList = new LinkedHashSet();
198 startInternal(startList);
199 userLoaded = true;
200 userStarted = true;
201 return startList;
202 }
203
204 private void startInternal(LinkedHashSet startList) {
205 // visit all stopped parents
206 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
207 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
208 if (!parent.isStarted()) {
209 parent.startInternal(startList);
210 }
211 }
212
213 if (!started) {
214 startList.add(configurationId);
215 started = true;
216 }
217 }
218
219 /**
220 * Stop this configuration and its children (if it's running) or do nothing
221 * (if it's not running).
222 */
223 public LinkedHashSet stop(boolean gc) {
224 LinkedHashSet stopStatuses = new LinkedHashSet();
225 stopInternal(stopStatuses, gc);
226
227 LinkedHashSet stopIds = new LinkedHashSet(stopStatuses.size());
228 for (Iterator iterator = stopStatuses.iterator(); iterator.hasNext();) {
229 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
230 stopIds.add(configurationStatus.configurationId);
231 }
232
233 return stopIds;
234 }
235
236 private void stopInternal(LinkedHashSet stopList, boolean gc) {
237 // if we aren't started, there is nothing to do
238 if (!started) {
239 return;
240 }
241
242 // visit all children
243 for (Iterator iterator = startChildren.iterator(); iterator.hasNext();) {
244 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
245 if (child.isStarted()) {
246 child.stopInternal(stopList, gc);
247 }
248 }
249
250 // mark this node as stoped, and add this node to the stop list
251 if (started) {
252 started = false;
253 userStarted = false;
254 stopList.add(this);
255
256 // if we are garbage collecting, visit parents
257 if (gc) {
258 // visit all non-user started parents that haven't already been visited
259 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
260 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
261 if (!parent.isUserStarted() && stopList.containsAll(parent.startChildren)) {
262 parent.stopInternal(stopList, gc);
263 }
264 }
265 }
266 }
267 }
268
269 public LinkedHashSet restart() {
270 if (!started) {
271 throw new IllegalStateException(configurationId + " is not started");
272 }
273
274 LinkedHashSet restartStatuses = new LinkedHashSet();
275 restartInternal(restartStatuses);
276
277 LinkedHashSet restartIds = new LinkedHashSet(restartStatuses.size());
278 for (Iterator iterator = restartStatuses.iterator(); iterator.hasNext();) {
279 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
280 restartIds.add(configurationStatus.configurationId);
281 }
282
283 userLoaded = true;
284 userStarted = true;
285 return restartIds;
286 }
287
288 private void restartInternal(LinkedHashSet restartList) {
289 // if we aren't started, there is nothing to do
290 if (!started) {
291 return;
292 }
293
294 // visit all children
295 for (Iterator iterator = startChildren.iterator(); iterator.hasNext();) {
296 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
297 if (child.isStarted()) {
298 child.restartInternal(restartList);
299 }
300 }
301
302 // add this node to the restart list
303 restartList.add(this);
304 }
305
306 /**
307 * Unload the configuration and all its children (if it's loaded), or do
308 * nothing (if it's not loaded).
309 */
310 public LinkedHashSet unload(boolean gc) {
311
312 LinkedHashSet unloadStatuses = new LinkedHashSet();
313 unloadInternal(unloadStatuses, gc);
314
315 LinkedHashSet unloadIds = new LinkedHashSet(unloadStatuses.size());
316 for (Iterator iterator = unloadStatuses.iterator(); iterator.hasNext();) {
317 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
318 unloadIds.add(configurationStatus.configurationId);
319 }
320
321 return unloadIds;
322 }
323
324 private void unloadInternal(LinkedHashSet unloadList, boolean gc) {
325 // if we aren't loaded, there is nothing to do
326 if (!loaded) {
327 return;
328 }
329
330 // visit all loaded children
331 for (Iterator iterator = loadChildren.iterator(); iterator.hasNext();) {
332 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
333 if (child.isLoaded()) {
334 child.unloadInternal(unloadList, gc);
335 }
336 }
337
338 // mark this node as unloaded, and add this node to the unload list
339 if (loaded) {
340 started = false;
341 userStarted = false;
342 loaded = false;
343 userLoaded = false;
344 unloadList.add(this);
345
346 // if we are garbage collecting, visit parents
347 if (gc) {
348 // visit all non-user loaded parents
349 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
350 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
351 if (!parent.isUserLoaded() && unloadList.containsAll(parent.loadChildren)) {
352 parent.unloadInternal(unloadList, gc);
353 }
354 }
355 }
356 }
357 }
358
359 public LinkedHashSet reload() {
360 if (!loaded) {
361 throw new IllegalStateException(configurationId + " is not loaded");
362 }
363
364 LinkedHashSet reloadStatuses = new LinkedHashSet();
365 reloadInternal(reloadStatuses);
366
367 LinkedHashSet reloadIds = new LinkedHashSet(reloadStatuses.size());
368 for (Iterator iterator = reloadStatuses.iterator(); iterator.hasNext();) {
369 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
370 reloadIds.add(configurationStatus.configurationId);
371 }
372
373 userLoaded = true;
374 return reloadIds;
375 }
376
377 private void reloadInternal(LinkedHashSet reloadList) {
378 // if we aren't loaded, there is nothing to do
379 if (!loaded) {
380 return;
381 }
382
383 // visit all children
384 for (Iterator iterator = loadChildren.iterator(); iterator.hasNext();) {
385 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
386 if (child.isLoaded()) {
387 child.reloadInternal(reloadList);
388 }
389 }
390
391 // add this node to the reload list
392 reloadList.add(this);
393 }
394
395 public String toString() {
396 String load;
397 if (userLoaded) {
398 load = "user-loaded";
399 } else if (loaded) {
400 load = "loaded";
401 } else {
402 load = "not-loaded";
403 }
404 String start;
405 if (userLoaded) {
406 start = "user-started";
407 } else if (loaded) {
408 start = "started";
409 } else {
410 start = "not-started";
411 }
412 return "[" + configurationId + " " + load + " " + start + "]";
413 }
414 }