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 }