001 /**
002 *
003 * Copyright 2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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: 410741 $ $Date: 2006-05-31 21:35:48 -0700 (Wed, 31 May 2006) $
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 boolean isLoaded() {
090 return loaded;
091 }
092
093 public boolean isStarted() {
094 return started;
095 }
096
097 public boolean isUserLoaded() {
098 return userLoaded;
099 }
100
101 public boolean isUserStarted() {
102 return userStarted;
103 }
104
105
106 public void upgrade(Artifact newId, Set newLoadParents, Set newStartParents) {
107 this.configurationId = newId;
108
109 //
110 // remove links from the current parents to me
111 //
112 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
113 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
114 loadParent.loadChildren.remove(this);
115 }
116 loadParents.clear();
117
118 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
119 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
120 startParent.startChildren.remove(this);
121 }
122 startChildren.clear();
123
124 //
125 // connect to to the new parents
126 //
127 this.loadParents.addAll(newLoadParents);
128 this.startParents.addAll(newStartParents);
129
130 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
131 ConfigurationStatus loadParent = (ConfigurationStatus) iterator.next();
132 loadParent.loadChildren.add(this);
133 }
134
135 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
136 ConfigurationStatus startParent = (ConfigurationStatus) iterator.next();
137 startParent.startChildren.add(this);
138 }
139 }
140
141 public LinkedHashSet load() {
142 LinkedHashSet loadList = new LinkedHashSet();
143 loadInternal(loadList);
144 userLoaded = true;
145 return loadList;
146 }
147
148 private void loadInternal(LinkedHashSet loadList) {
149 // visit all unloaded parents
150 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
151 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
152 if (!parent.isLoaded()) {
153 parent.loadInternal(loadList);
154 }
155 }
156
157 if (!loaded) {
158 loadList.add(configurationId);
159 loaded = true;
160 }
161 }
162
163
164 public LinkedHashSet start() {
165 if (!loaded) {
166 throw new IllegalStateException(configurationId + " is not loaded");
167 }
168 LinkedHashSet startList = new LinkedHashSet();
169 startInternal(startList);
170 userLoaded = true;
171 userStarted = true;
172 return startList;
173 }
174
175 private void startInternal(LinkedHashSet startList) {
176 // visit all stopped parents
177 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
178 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
179 if (!parent.isStarted()) {
180 parent.startInternal(startList);
181 }
182 }
183
184 if (!started) {
185 startList.add(configurationId);
186 started = true;
187 }
188 }
189
190 /**
191 * Stop this configuration and its children (if it's running) or do nothing
192 * (if it's not running).
193 */
194 public LinkedHashSet stop(boolean gc) {
195 LinkedHashSet stopStatuses = new LinkedHashSet();
196 stopInternal(stopStatuses, gc);
197
198 LinkedHashSet stopIds = new LinkedHashSet(stopStatuses.size());
199 for (Iterator iterator = stopStatuses.iterator(); iterator.hasNext();) {
200 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
201 stopIds.add(configurationStatus.configurationId);
202 }
203
204 return stopIds;
205 }
206
207 private void stopInternal(LinkedHashSet stopList, boolean gc) {
208 // if we aren't started, there is nothing to do
209 if (!started) {
210 return;
211 }
212
213 // visit all children
214 for (Iterator iterator = startChildren.iterator(); iterator.hasNext();) {
215 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
216 if (child.isStarted()) {
217 child.stopInternal(stopList, gc);
218 }
219 }
220
221 // mark this node as stoped, and add this node to the stop list
222 if (started) {
223 started = false;
224 userStarted = false;
225 stopList.add(this);
226
227 // if we are garbage collecting, visit parents
228 if (gc) {
229 // visit all non-user started parents that haven't already been visited
230 for (Iterator iterator = startParents.iterator(); iterator.hasNext();) {
231 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
232 if (!parent.isUserStarted() && stopList.containsAll(parent.startChildren)) {
233 parent.stopInternal(stopList, gc);
234 }
235 }
236 }
237 }
238 }
239
240 public LinkedHashSet restart() {
241 if (!started) {
242 throw new IllegalStateException(configurationId + " is not started");
243 }
244
245 LinkedHashSet restartStatuses = new LinkedHashSet();
246 restartInternal(restartStatuses);
247
248 LinkedHashSet restartIds = new LinkedHashSet(restartStatuses.size());
249 for (Iterator iterator = restartStatuses.iterator(); iterator.hasNext();) {
250 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
251 restartIds.add(configurationStatus.configurationId);
252 }
253
254 userLoaded = true;
255 userStarted = true;
256 return restartIds;
257 }
258
259 private void restartInternal(LinkedHashSet restartList) {
260 // if we aren't started, there is nothing to do
261 if (!started) {
262 return;
263 }
264
265 // visit all children
266 for (Iterator iterator = startChildren.iterator(); iterator.hasNext();) {
267 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
268 if (child.isStarted()) {
269 child.restartInternal(restartList);
270 }
271 }
272
273 // add this node to the restart list
274 restartList.add(this);
275 }
276
277 /**
278 * Unload the configuration and all its children (if it's loaded), or do
279 * nothing (if it's not loaded).
280 */
281 public LinkedHashSet unload(boolean gc) {
282
283 LinkedHashSet unloadStatuses = new LinkedHashSet();
284 unloadInternal(unloadStatuses, gc);
285
286 LinkedHashSet unloadIds = new LinkedHashSet(unloadStatuses.size());
287 for (Iterator iterator = unloadStatuses.iterator(); iterator.hasNext();) {
288 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
289 unloadIds.add(configurationStatus.configurationId);
290 }
291
292 return unloadIds;
293 }
294
295 private void unloadInternal(LinkedHashSet unloadList, boolean gc) {
296 // if we aren't loaded, there is nothing to do
297 if (!loaded) {
298 return;
299 }
300
301 // visit all loaded children
302 for (Iterator iterator = loadChildren.iterator(); iterator.hasNext();) {
303 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
304 if (child.isLoaded()) {
305 child.unloadInternal(unloadList, gc);
306 }
307 }
308
309 // mark this node as unloaded, and add this node to the unload list
310 if (loaded) {
311 started = false;
312 userStarted = false;
313 loaded = false;
314 userLoaded = false;
315 unloadList.add(this);
316
317 // if we are garbage collecting, visit parents
318 if (gc) {
319 // visit all non-user loaded parents
320 for (Iterator iterator = loadParents.iterator(); iterator.hasNext();) {
321 ConfigurationStatus parent = (ConfigurationStatus) iterator.next();
322 if (!parent.isUserLoaded() && unloadList.containsAll(parent.loadChildren)) {
323 parent.unloadInternal(unloadList, gc);
324 }
325 }
326 }
327 }
328 }
329
330 public LinkedHashSet reload() {
331 if (!loaded) {
332 throw new IllegalStateException(configurationId + " is not loaded");
333 }
334
335 LinkedHashSet reloadStatuses = new LinkedHashSet();
336 reloadInternal(reloadStatuses);
337
338 LinkedHashSet reloadIds = new LinkedHashSet(reloadStatuses.size());
339 for (Iterator iterator = reloadStatuses.iterator(); iterator.hasNext();) {
340 ConfigurationStatus configurationStatus = (ConfigurationStatus) iterator.next();
341 reloadIds.add(configurationStatus.configurationId);
342 }
343
344 userLoaded = true;
345 return reloadIds;
346 }
347
348 private void reloadInternal(LinkedHashSet reloadList) {
349 // if we aren't loaded, there is nothing to do
350 if (!loaded) {
351 return;
352 }
353
354 // visit all children
355 for (Iterator iterator = loadChildren.iterator(); iterator.hasNext();) {
356 ConfigurationStatus child = (ConfigurationStatus) iterator.next();
357 if (child.isLoaded()) {
358 child.reloadInternal(reloadList);
359 }
360 }
361
362 // add this node to the reload list
363 reloadList.add(this);
364 }
365
366 public String toString() {
367 String load;
368 if (userLoaded) {
369 load = "user-loaded";
370 } else if (loaded) {
371 load = "loaded";
372 } else {
373 load = "not-loaded";
374 }
375 String start;
376 if (userLoaded) {
377 start = "user-started";
378 } else if (loaded) {
379 start = "started";
380 } else {
381 start = "not-started";
382 }
383 return "[" + configurationId + " " + load + " " + start + "]";
384 }
385 }