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: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 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 }