001/* 002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Bogdan Stefanescu 018 * Florent Guillaume 019 */ 020package org.nuxeo.runtime.model; 021 022import java.util.Collection; 023import java.util.Map; 024import java.util.Set; 025 026import org.nuxeo.runtime.ComponentListener; 027import org.nuxeo.runtime.api.Framework; 028import org.nuxeo.runtime.model.impl.DefaultRuntimeContext; 029 030/** 031 * @author Bogdan Stefanescu 032 * @author Florent Guillaume 033 */ 034public interface ComponentManager { 035 036 /** 037 * Adds a component listener. 038 * <p> 039 * Does nothing if the given listener is already registered. 040 * 041 * @param listener the component listener to add 042 */ 043 void addComponentListener(ComponentListener listener); 044 045 /** 046 * Removes a component listener. 047 * <p> 048 * Does nothing if the given listener is not registered. 049 * 050 * @param listener the component listener to remove 051 */ 052 void removeComponentListener(ComponentListener listener); 053 054 /** 055 * Handles the registration of the given registration info. 056 * <p> 057 * This is called by the main registry when all dependencies of this registration info were solved and the object 058 * can be registered. 059 * <p> 060 * If true is returned, the object will be added to the main registry under the name given in RegistrationInfo. 061 * 062 * @param ri the registration info 063 */ 064 void register(RegistrationInfo ri); 065 066 /** 067 * Handles the unregistration of the given registration info. 068 * <p> 069 * This is called by the main registry when the object is unregistered. 070 * <p> 071 * If true is returned, the object will be removed from the main registry. 072 * 073 * @param ri the registration info 074 */ 075 void unregister(RegistrationInfo ri); 076 077 /** 078 * Unregisters a component given its name. 079 * 080 * @param name the component name 081 */ 082 void unregister(ComponentName name); 083 084 /** 085 * This method was added only to support unregistering by location which is used by some tests. Removing by location 086 * should be managed at a higher level (it is useful only for tests) and this method should be removed 087 * 088 * @param sourceId the location from where the component was deployed 089 * @return false if no component was registered from that location, true otherwise 090 * @see DefaultRuntimeContext for more on this 091 * @since 9.2 092 * @deprecated since 9.2 093 */ 094 @Deprecated 095 boolean unregisterByLocation(String sourceId); 096 097 /** 098 * Given a source location tests if a component was deployed from that location <br> 099 * This method was added to support undeploying by location needed by tests. Should be removed and a test specific 100 * helper implemented to support locations 101 * 102 * @deprecated since 9.2 103 */ 104 @Deprecated 105 boolean hasComponentFromLocation(String sourceId); 106 107 /** 108 * Gets the component if there is one having the given name. 109 * 110 * @param name the component name 111 * @return the component if any was registered with that name, null otherwise 112 */ 113 RegistrationInfo getRegistrationInfo(ComponentName name); 114 115 /** 116 * Gets object instance managed by the named component. 117 * 118 * @param name the object name 119 * @return the object instance if any. may be null 120 */ 121 ComponentInstance getComponent(ComponentName name); 122 123 /** 124 * Checks whether or not a component with the given name was registered. 125 * 126 * @param name the object name 127 * @return true if an object with the given name was registered, false otherwise 128 */ 129 boolean isRegistered(ComponentName name); 130 131 /** 132 * Gets the registered components. 133 * 134 * @return a read-only collection of components 135 */ 136 Collection<RegistrationInfo> getRegistrations(); 137 138 /** 139 * Gets the pending registrations and their dependencies. 140 * 141 * @return the pending registrations 142 */ 143 Map<ComponentName, Set<ComponentName>> getPendingRegistrations(); 144 145 /** 146 * Returns the missing registrations, linked to missing target extension points. 147 * 148 * @since 8.10 149 */ 150 Map<ComponentName, Set<Extension>> getMissingRegistrations(); 151 152 /** 153 * Gets the pending extensions by component. 154 * 155 * @return the pending extensions 156 */ 157 Collection<ComponentName> getActivatingRegistrations(); 158 159 /** 160 * Gets the resolved component names in the order they were resolved 161 * 162 * @since 9.2 163 */ 164 Collection<ComponentName> getResolvedRegistrations(); 165 166 /** 167 * Gets the components that fail on applicationStarted notification 168 * 169 * @since 7.4 170 */ 171 Collection<ComponentName> getStartFailureRegistrations(); 172 173 /** 174 * Gets the number of registered objects in this registry. 175 * 176 * @return the number of registered objects 177 */ 178 int size(); 179 180 /** 181 * Shuts down the component registry. 182 * <p> 183 * This unregisters all objects registered in this registry. 184 */ 185 void shutdown(); 186 187 /** 188 * Gets the service of type serviceClass if such a service was declared by a resolved runtime component. 189 * <p> 190 * If the component is not yet activated it will be prior to return the service. 191 * 192 * @param <T> the service type 193 * @param serviceClass the service class 194 * @return the service object 195 */ 196 <T> T getService(Class<T> serviceClass); 197 198 /** 199 * Get the list of all registered service names An empty array is returned if no registered services are found. 200 * 201 * @return an array of registered service. 202 */ 203 String[] getServices(); 204 205 /** 206 * Gets the component that provides the given service. 207 * 208 * @param serviceClass the service class 209 * @return the component or null if none 210 */ 211 ComponentInstance getComponentProvidingService(Class<?> serviceClass); 212 213 Set<String> getBlacklist(); 214 215 void setBlacklist(Set<String> blacklist); 216 217 /** 218 * Activate and start all resolved components. If components were already started do nothing. 219 * 220 * @return false if components were already started, true otherwise 221 * @since 9.2 222 */ 223 boolean start(); 224 225 /** 226 * Stop and deactivate all resolved components. If components were not yet started do nothing 227 * 228 * @return false if components were not yet started, true otherwise 229 * @since 9.2 230 */ 231 boolean stop(); 232 233 /** 234 * Same as {@link #stop()} but log a warning if the timeout is reached while stopping components 235 * 236 * @since 9.2 237 */ 238 void stop(int timeout); 239 240 /** 241 * Stop all started components but don't deactivate them. After calling this method you can safely contribute new 242 * extensions (i.e. modify extension registries). 243 * <p> 244 * If any components were previously started do nothing 245 * 246 * @since 9.2 247 */ 248 void standby(); 249 250 /** 251 * Same as {@link #standby()} but log a warning if the timeout is reached while stopping components 252 * 253 * @since 9.2 254 */ 255 void standby(int timeout); 256 257 /** 258 * Start standby components. If components are not in standby mode the it does nothing. 259 * 260 * @since 9.2 261 */ 262 void resume(); 263 264 /** 265 * Make a snapshot of the component registry. When calling restart 266 * 267 * @since 9.2 268 */ 269 void snapshot(); 270 271 /** 272 * Optionally reset the registry to the last snapshot and restart the components. 273 * <p> 274 * When restarting components all components will be stopped, deactivated and re-instantiated. It means that all 275 * references to components before a restart will become invalid after the restart. 276 * <p> 277 * If no snapshot was created then the components will be restarted without changing the registry. 278 * <p> 279 * If the <code>reset</code> argument is true then the registry will be reverted to the last snapshot before 280 * starting the components. 281 * 282 * @param reset whether or not to revert to the last snapshot 283 * @since 9.2 284 */ 285 void restart(boolean reset); 286 287 /** 288 * Reset the registry to the last snapshot if any and stop the components (if they are currently started). After a 289 * reset all the components are stopped so we can contribute new components if needed. You must call 290 * {@link #start()} to start again the components 291 * 292 * @return true if the components were stopped, false otherwise 293 * @since 9.2 294 */ 295 boolean reset(); 296 297 /** 298 * Refresh the registry using stashed registrations if any. If the <code>reset</code> argument is true then the 299 * registry will be reverted to the last snapshot before applying the stash. 300 * <p> 301 * If the stash is empty it does nothing and return true, otherwise it will: 302 * <ol> 303 * <li>stop the components (if they are started) 304 * <li>revert to the last snapshot (if reset flag is true) 305 * <li>apply the stash (the stash will remain empty after this operation) 306 * <li>start the components (if they was started) 307 * </ol> 308 * 309 * @param reset whether or not to revert to the last snapshot 310 * @return false if stash is empty and nothing was done, true otherwise 311 * @since 9.2 312 */ 313 boolean refresh(boolean reset); 314 315 /** 316 * Shortcut for refresh(false). 317 * 318 * @see #refresh(boolean) 319 * @since 9.2 320 */ 321 default boolean refresh() { 322 return refresh(false); 323 } 324 325 /** 326 * Tests whether the components were already started. 327 * 328 * @return true if components are started, false 329 * @since 9.2 330 */ 331 boolean isStarted(); 332 333 /** 334 * Tests whether the components are in standby mode. That means they were started and then stopped - waiting to be 335 * started again. 336 * <p> 337 * When putting components in standby they are stopped but not deactivated. You start back the standby components by 338 * calling #resume 339 * <p> 340 * While in standby mode the component manager remains in running state. 341 * 342 * @since 9.2 343 */ 344 boolean isStandby(); 345 346 /** 347 * Tests whether the components are running. That means they are either started either in standby mode. 348 * 349 * @since 9.2 350 */ 351 boolean isRunning(); 352 353 /** 354 * Tests whether components were deployed over the initial snapshot (i.e. the actual registry differs from the 355 * snapshot) If no snapshot was done returns false. 356 * 357 * @since 9.2 358 */ 359 boolean hasChanged(); 360 361 /** 362 * Check if a snapshot was done 363 * 364 * @return true if a snapshot already exists, false otherwise 365 * @since 9.2 366 */ 367 boolean hasSnapshot(); 368 369 /** 370 * Tests if the stash is empty 371 * 372 * @since 9.2 373 */ 374 boolean isStashEmpty(); 375 376 /** 377 * Apply the stash if not empty. This is a low level operation and may not be safe to call when the component 378 * manager is running {@link #isRunning()}. 379 * <p> 380 * For compatibility reasons (to be able to emulate the old hot deploy mechanism or to speed up tests) this method 381 * will force a registry refresh in all 3 component manager states: stopped, standby, started. 382 * <p> 383 * Usually you should apply the stash by calling {@link #refresh()} which is similar to 384 * <code>stop(); [restoreSnapshot();] unstash(); start();</code> 385 * 386 * @since 9.2 387 */ 388 void unstash(); 389 390 /** 391 * Add a listener to be notified on manager actions like start / stop components. 392 * 393 * @since 9.2 394 */ 395 void addListener(ComponentManager.Listener listener); 396 397 /** 398 * Remove the component manager listener previously added by {@link #addListener(Listener)}. If the listener were 399 * not added then nothing is done. 400 * 401 * @since 9.2 402 */ 403 void removeListener(ComponentManager.Listener listener); 404 405 /** 406 * Listener interface for component manager events 407 * 408 * @author bogdan 409 * @since 9.2 410 */ 411 interface Listener { 412 413 /** 414 * Called just before activating components. This is fired when entering {@link ComponentManager#start()} 415 */ 416 void beforeActivation(ComponentManager mgr); 417 418 /** 419 * Called just after all the components were activated. 420 */ 421 void afterActivation(ComponentManager mgr); 422 423 /** 424 * Called just before activating components. 425 */ 426 void beforeDeactivation(ComponentManager mgr); 427 428 /** 429 * Called just after all the components were deactivated. This is fired just before exiting from 430 * {@link ComponentManager#stop()}. 431 */ 432 void afterDeactivation(ComponentManager mgr); 433 434 /** 435 * Called just before starting components. 436 * 437 * @param isResume true if the event was initiated by a {@link ComponentManager#resume()} call, false otherwise. 438 */ 439 void beforeStart(ComponentManager mgr, boolean isResume); 440 441 /** 442 * Called just after all components were started 443 * 444 * @param isResume true if the event was initiated by a {@link ComponentManager#resume()} call, false otherwise. 445 */ 446 void afterStart(ComponentManager mgr, boolean isResume); 447 448 /** 449 * Called just before stopping components. 450 * 451 * @param isStandby true if the event was initiated by a {@link ComponentManager#standby()} call, false 452 * otherwise 453 */ 454 void beforeStop(ComponentManager mgr, boolean isStandby); 455 456 /** 457 * Called just after the components were stopped. 458 * 459 * @param isStandby true if the event was initiated by a {@link ComponentManager#standby()} call, false 460 * otherwise 461 */ 462 void afterStop(ComponentManager mgr, boolean isStandby); 463 } 464 465 /** 466 * Abstract base class for component manager listeners. Subclass this instead of directly implementing 467 * {@link Listener} 468 * 469 * @author bogdan 470 * @since 9.2 471 */ 472 class LifeCycleHandler implements Listener { 473 474 @Override 475 public void beforeActivation(ComponentManager mgr) { 476 } 477 478 @Override 479 public void afterActivation(ComponentManager mgr) { 480 } 481 482 @Override 483 public void beforeDeactivation(ComponentManager mgr) { 484 } 485 486 @Override 487 public void afterDeactivation(ComponentManager mgr) { 488 } 489 490 @Override 491 public void beforeStart(ComponentManager mgr, boolean isResume) { 492 } 493 494 @Override 495 public void afterStart(ComponentManager mgr, boolean isResume) { 496 } 497 498 @Override 499 public void beforeStop(ComponentManager mgr, boolean isStandby) { 500 } 501 502 @Override 503 public void afterStop(ComponentManager mgr, boolean isStandby) { 504 } 505 506 public LifeCycleHandler install() { 507 Framework.getRuntime().getComponentManager().addListener(this); 508 return this; 509 } 510 511 public LifeCycleHandler uninstall() { 512 Framework.getRuntime().getComponentManager().removeListener(this); 513 return this; 514 } 515 } 516 517}