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 249 standby(); 250 251 /** 252 * Same as {@link #standby()} but log a warning if the timeout is reached while stopping components 253 * 254 * @since 9.2 255 */ 256 void standby(int timeout); 257 258 /** 259 * Start standby components. If components are not in standby mode the it does nothing. 260 * 261 * @since 9.2 262 */ 263 void resume(); 264 265 /** 266 * Make a snapshot of the component registry. When calling restart 267 * 268 * @since 9.2 269 */ 270 void snapshot(); 271 272 /** 273 * Optionally reset the registry to the last snapshot and restart the components. 274 * <p> 275 * When restarting components all components will be stopped, deactivated and re-instantiated. It means that all 276 * references to components before a restart will become invalid after the restart. 277 * <p> 278 * If no snapshot was created then the components will be restarted without changing the registry. 279 * <p> 280 * If the <code>reset</code> argument is true then the registry will be reverted to the last snapshot before 281 * starting the components. 282 * 283 * @param reset whether or not to revert to the last snapshot 284 * @since 9.2 285 */ 286 void restart(boolean reset); 287 288 /** 289 * Reset the registry to the last snapshot if any and stop the components (if they are currently started). After a 290 * reset all the components are stopped so we can contribute new components if needed. You must call 291 * {@link #start()} to start again the components 292 * 293 * @return true if the components were stopped, false otherwise 294 * @since 9.2 295 */ 296 boolean reset(); 297 298 /** 299 * Refresh the registry using stashed registrations if any. If the <code>reset</code> argument is true then the 300 * registry will be reverted to the last snapshot before applying the stash. 301 * <p> 302 * If the stash is empty it does nothing and return true, otherwise it will: 303 * <ol> 304 * <li>stop the components (if they are started) 305 * <li>revert to the last snapshot (if reset flag is true) 306 * <li>apply the stash (the stash will remain empty after this operation) 307 * <li>start the components (if they was started) 308 * </ol> 309 * 310 * @param reset whether or not to revert to the last snapshot 311 * @return false if stash is empty and nothing was done, true otherwise 312 * @since 9.2 313 */ 314 boolean refresh(boolean reset); 315 316 /** 317 * Shortcut for refresh(false). 318 * 319 * @see #refresh(boolean) 320 * @since 9.2 321 */ 322 default boolean refresh() { 323 return refresh(false); 324 } 325 326 /** 327 * Tests whether the components were already started. 328 * 329 * @return true if components are started, false 330 * @since 9.2 331 */ 332 boolean isStarted(); 333 334 /** 335 * Tests whether the components are in standby mode. That means they were started and then stopped - waiting to be 336 * started again. 337 * <p> 338 * When putting components in standby they are stopped but not deactivated. You start back the standby components by 339 * calling #resume 340 * <p> 341 * While in standby mode the component manager remains in running state. 342 * 343 * @since 9.2 344 */ 345 boolean isStandby(); 346 347 /** 348 * Tests whether the components are running. That means they are either started either in standby mode. 349 * 350 * @since 9.2 351 */ 352 boolean isRunning(); 353 354 /** 355 * Tests whether components were deployed over the initial snapshot (i.e. the actual registry differs from the 356 * snapshot) If no snapshot was done returns false. 357 * 358 * @since 9.2 359 */ 360 boolean hasChanged(); 361 362 /** 363 * Check if a snapshot was done 364 * 365 * @return true if a snapshot already exists, false otherwise 366 * @since 9.2 367 */ 368 boolean hasSnapshot(); 369 370 /** 371 * Tests if the stash is empty 372 * 373 * @since 9.2 374 */ 375 boolean isStashEmpty(); 376 377 /** 378 * Apply the stash if not empty. This is a low level operation and may not be safe to call when the component 379 * manager is running {@link #isRunning()}. 380 * <p> 381 * For compatibility reasons (to be able to emulate the old hot deploy mechanism or to speed up tests) this method 382 * will force a registry refresh in all 3 component manager states: stopped, standby, started. 383 * <p> 384 * Usually you should apply the stash by calling {@link #refresh()} which is similar to 385 * <code>stop(); [restoreSnapshot();] unstash(); start();</code> 386 * 387 * @since 9.2 388 */ 389 void unstash(); 390 391 /** 392 * Add a listener to be notified on manager actions like start / stop components. 393 * 394 * @since 9.2 395 */ 396 void addListener(ComponentManager.Listener listener); 397 398 /** 399 * Remove the component manager listener previously added by {@link #addListener(Listener)}. If the listener were 400 * not added then nothing is done. 401 * 402 * @since 9.2 403 */ 404 void removeListener(ComponentManager.Listener listener); 405 406 /** 407 * Listener interface for component manager events 408 * 409 * @author bogdan 410 * @since 9.2 411 */ 412 interface Listener { 413 414 /** 415 * Called just before activating components. This is fired when entering {@link ComponentManager#start()} 416 */ 417 default void beforeActivation(ComponentManager mgr) { 418 } 419 420 /** 421 * Called just after all the components were activated. 422 */ 423 default void afterActivation(ComponentManager mgr) { 424 } 425 426 /** 427 * Called just before activating components. 428 */ 429 default void beforeDeactivation(ComponentManager mgr) { 430 } 431 432 /** 433 * Called just after all the components were deactivated. This is fired just before exiting from 434 * {@link ComponentManager#stop()}. 435 */ 436 default void afterDeactivation(ComponentManager mgr) { 437 } 438 439 /** 440 * Called just before starting components. 441 * 442 * @param isResume true if the event was initiated by a {@link ComponentManager#resume()} call, false otherwise. 443 */ 444 default void beforeStart(ComponentManager mgr, boolean isResume) { 445 } 446 447 /** 448 * Called just after all components were started 449 * 450 * @param isResume true if the event was initiated by a {@link ComponentManager#resume()} call, false otherwise. 451 */ 452 default void afterStart(ComponentManager mgr, boolean isResume) { 453 } 454 455 /** 456 * Called just before stopping components. 457 * 458 * @param isStandby true if the event was initiated by a {@link ComponentManager#standby()} call, false 459 * otherwise 460 */ 461 default void beforeStop(ComponentManager mgr, boolean isStandby) { 462 } 463 464 /** 465 * Called just after the components were stopped. 466 * 467 * @param isStandby true if the event was initiated by a {@link ComponentManager#standby()} call, false 468 * otherwise 469 */ 470 default void afterStop(ComponentManager mgr, boolean isStandby) { 471 } 472 473 default Listener install() { 474 Framework.getRuntime().getComponentManager().addListener(this); 475 return this; 476 } 477 478 default Listener uninstall() { 479 Framework.getRuntime().getComponentManager().removeListener(this); 480 return this; 481 } 482 483 } 484 485}