mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-10 11:33:11 +00:00
More Javadoc elaboration and cleanup
git-svn-id: http://scm.dspace.org/svn/repo/modules/dspace-services/trunk@4982 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
@@ -12,45 +12,67 @@ package org.dspace.constants;
|
||||
|
||||
|
||||
/**
|
||||
* All core DSpace constants
|
||||
* All core DSpace Services constants.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
/**
|
||||
* If this is set to true then DSpace kernel is run as if it is inside a unit test,
|
||||
* this means that nothing is persisted (things are run in-memory only) and
|
||||
* caches and other speed optimizing parts are reduced,
|
||||
* this should NEVER be set in a production system
|
||||
* If this is set to true then DSpace kernel is run as if it is
|
||||
* inside a unit test. This means that nothing is persisted (things
|
||||
* are run in-memory only) and caches and other speed optimizing
|
||||
* parts are reduced. This should NEVER be set true in a production
|
||||
* system.
|
||||
*/
|
||||
public static final String DSPACE_TESTING_MODE = "dspace.testing";
|
||||
|
||||
/**
|
||||
* This is the name of the timer thread for all DSpace core timers
|
||||
* This is the name of the timer thread for all DSpace core timers.
|
||||
*/
|
||||
public static final String DSPACE_TIMER_NAME = "DSpaceTimer";
|
||||
|
||||
/**
|
||||
* HSQLDB, DERBY, ORACLE, MYSQL, POSTGRES, DB2, MSSQL
|
||||
* Note that H2 uses HSQLDB key
|
||||
* Configuration key for the name of the DBMS being used.
|
||||
* HSQLDB, DERBY, ORACLE, MYSQL, POSTGRES, DB2, MSSQL.
|
||||
* Note that H2 uses the HSQLDB key.
|
||||
*/
|
||||
public static final String DATABASE_TYPE_KEY = "jdbc.database.type";
|
||||
|
||||
/**
|
||||
* Class of the JDBC driver.
|
||||
* Embedded drivers are:
|
||||
* org.h2.Driver
|
||||
* org.apache.derby.jdbc.EmbeddedDriver
|
||||
* org.hsqldb.jdbcDriver
|
||||
* Put your driver in the lib directory for your servlet container
|
||||
* <ul>
|
||||
* <li>org.h2.Driver</li>
|
||||
* <li>org.apache.derby.jdbc.EmbeddedDriver</li>
|
||||
* <li>org.hsqldb.jdbcDriver</li>
|
||||
* </ul>
|
||||
* Put your driver in the lib directory for your servlet container.
|
||||
*/
|
||||
public static final String DATABASE_DRIVER_KEY = "jdbc.driver.class";
|
||||
public static final String DATABASE_CONNECTION_KEY = "jdbc.connection.url";
|
||||
public static final String DATABASE_USERNAME_KEY = "jdbc.username";
|
||||
public static final String DATABASE_PASSWORD_KEY = "jdbc.password";
|
||||
|
||||
/**
|
||||
* Set this to true to enable connection pooling, default true
|
||||
* JDBC database connection URL.
|
||||
*/
|
||||
public static final String DATABASE_CONNECTION_KEY = "jdbc.connection.url";
|
||||
|
||||
/**
|
||||
* Database connection user.
|
||||
*/
|
||||
public static final String DATABASE_USERNAME_KEY = "jdbc.username";
|
||||
|
||||
/**
|
||||
* Database connection password.
|
||||
*/
|
||||
public static final String DATABASE_PASSWORD_KEY = "jdbc.password";
|
||||
|
||||
/**
|
||||
* Set this to true (the default) to enable connection pooling.
|
||||
*/
|
||||
public static final String DATABASE_CONN_POOLING = "jdbc.dataSource.pooling";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
}
|
||||
|
5
api/src/main/java/org/dspace/constants/package-info.java
Normal file
5
api/src/main/java/org/dspace/constants/package-info.java
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Manifest constants naming configuration data for core services.
|
||||
*/
|
||||
|
||||
package org.dspace.constants;
|
@@ -15,53 +15,66 @@ package org.dspace.kernel;
|
||||
* An activator is a special type which allows a provider to be plugged into the system by dropping a jar file
|
||||
* in with the kernel and adding in a hook in the configuration file. Activators are started after the
|
||||
* initial classes and the service manager have already been started. All classes which implement this
|
||||
* must have: <br/>
|
||||
* 1) A public empty constructor (takes no parameters) (e.g. public MyClass() {} ) <br/>
|
||||
* <br/>
|
||||
* If you want the system to execute your class then you must list it in the config file with the fully qualified classpath
|
||||
* must have a public empty constructor (takes no parameters) (e.g.
|
||||
* {@code public MyClass() {}} )
|
||||
* <p>
|
||||
* If you want the system to execute your class then you must list it in
|
||||
* the DSpace configuration with the fully qualified classpath
|
||||
* (NOTE that the xxx can be anything as long as it is unique): <br/>
|
||||
* <b>activator.xxx = org.dspace.MyClass</b> <br/>
|
||||
* <br/>
|
||||
* {@code activator.xxx = org.dspace.MyClass}
|
||||
* </p>
|
||||
* <p>
|
||||
* {@link #start(ServiceManager)} will be called after the class is created during kernel startup.
|
||||
* Developers should create their providers/plugins/etc. in this method and
|
||||
* use the registration methods in the {@link ServiceManager} to register them.
|
||||
* {@link #stop(ServiceManager)} will be called when the kernel shuts down. Perform any cleanup/shutdown actions
|
||||
* you like during this phase (unregistering your services here is a good idea). <br/>
|
||||
* <br/>
|
||||
* This is modeled after the OSGi BundleActivator <br/>
|
||||
* <br/>
|
||||
* There is another type of activator used in DSpace but it is configured via the configuration service only.
|
||||
* The class activator is configured by creating a config property like this
|
||||
* </p>
|
||||
* <p>This is modeled after the OSGi {@code BundleActivator}.</p>
|
||||
* <p>
|
||||
* There is another type of activator used in DSpace but it is
|
||||
* configured via the configuration service only. The class activator
|
||||
* is configured by creating a config property like this
|
||||
* (NOTE that the xxx can be anything as long as it is unique): <br/>
|
||||
* <b>activator.class.xxx = org.dspace.MyClass;org.dspace.MyServiceName;constructor</b> <br/>
|
||||
* Unlike the normal activators, these are started up when the kernel core services start and thus can actually
|
||||
* be accessed from the service manager and referenced in providers and plugins.
|
||||
* {@code activator.class.xxx = org.dspace.MyClass;org.dspace.MyServiceName;constructor}<br/>
|
||||
* Unlike the normal activators, these are started up when the kernel
|
||||
* core services start and thus can actually be accessed from the
|
||||
* service manager and referenced in providers and plugins.
|
||||
* </p>
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface Activator {
|
||||
|
||||
/**
|
||||
* This is called when the service manager is starting this activator, it is only called once.
|
||||
* This is called when the service manager is starting this activator.
|
||||
* It is only called once.
|
||||
* It will be called after the core services are started. The ClassLoader used will be the one
|
||||
* that this class is associated with to ensure all dependencies are available. <br/>
|
||||
* that this class is associated with to ensure all dependencies are available.
|
||||
* <p>
|
||||
* This method should be used to startup and register services in most cases but it can be used
|
||||
* to simply perform some system startup actions if desired. <br/>
|
||||
* Exceptions thrown out of this method will not cause the system startup to fail. <br/>
|
||||
* to simply perform some system startup actions if desired.
|
||||
* <p>
|
||||
* Exceptions thrown out of this method will not cause the system startup to fail.
|
||||
*
|
||||
* @param serviceManager the current system service manager
|
||||
*/
|
||||
public void start(ServiceManager serviceManager);
|
||||
|
||||
/**
|
||||
* This is called when the service manager is shutting down this activator, it is only called once.
|
||||
* This is called when the service manager is shutting down this
|
||||
* activator. It is only called once.
|
||||
* It will be called before the core services are stopped. The ClassLoader used will be the one
|
||||
* that this class is associated with to ensure all dependencies are available. <br/>
|
||||
* that this class is associated with to ensure all dependencies are available.
|
||||
* <p>
|
||||
* This method should be used to shutdown and unregister services in most cases but it can be used
|
||||
* to simply perform some system shutdown actions if desired. <br/>
|
||||
* Exceptions thrown out of this method will not cause the system shutdown to fail. <br/>
|
||||
* WARNING: this can hang the shutdown by performing operations that take a long long time or are deadlocked,
|
||||
* the developer is expected to ensure this does not happen
|
||||
* to simply perform some system shutdown actions if desired.
|
||||
* <p>
|
||||
* Exceptions thrown out of this method will not cause the system shutdown to fail.
|
||||
* <p>
|
||||
* WARNING: this can hang the shutdown by performing operations that
|
||||
* take a long long time or are deadlocked. The developer is
|
||||
* expected to ensure this does not happen.
|
||||
*
|
||||
* @param serviceManager the current system service manager
|
||||
*/
|
||||
|
@@ -13,8 +13,8 @@ package org.dspace.kernel;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
|
||||
/**
|
||||
* The interface of the Kernel,
|
||||
* this is the most core piece of the system and initalizing this will startup the dspace core
|
||||
* This is the most core piece of the system: instantiating one will
|
||||
* startup the dspace services framework.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
|
@@ -22,7 +22,7 @@ import javax.management.ReflectionException;
|
||||
|
||||
|
||||
/**
|
||||
* Allows the DSpace kernel to be accessed if desired
|
||||
* Allows the DSpace kernel to be accessed if desired.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
@@ -40,8 +40,9 @@ public class DSpaceKernelManager {
|
||||
private Object lock = new Object();
|
||||
|
||||
/**
|
||||
* Get the kernel, this will be a single instance for the JVM, but the method will retrieve
|
||||
* the same instance regardless of this object instance.
|
||||
* Get the kernel. This will be a single instance for the JVM, but
|
||||
* the method will retrieve the same instance regardless of this
|
||||
* object instance.
|
||||
*
|
||||
* @return the DSpace kernel
|
||||
* @throws IllegalStateException if the kernel is not available
|
||||
@@ -51,10 +52,12 @@ public class DSpaceKernelManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kernel, this will be a single instance for the JVM, but the method will retrieve
|
||||
* the same instance regardless of this object instance.
|
||||
* Get the kernel. This will be a single instance for the JVM, but
|
||||
* the method will retrieve the same instance regardless of this
|
||||
* object instance.
|
||||
*
|
||||
* @param name this is the name of this kernel instance, if you do not know what this is then use null
|
||||
* @param name this is the name of this kernel instance. If you do
|
||||
* not know what this is then use null.
|
||||
* @return the DSpace kernel
|
||||
* @throws IllegalStateException if the kernel is not available or not running
|
||||
*/
|
||||
@@ -91,6 +94,7 @@ public class DSpaceKernelManager {
|
||||
private static String defaultKernelName = UUID.randomUUID().toString();
|
||||
|
||||
/**
|
||||
* Ensure that we have a name suitable for an mbean.
|
||||
* @param name the name for the kernel
|
||||
* @return a proper mbean name based on the given name
|
||||
*/
|
||||
|
@@ -14,16 +14,17 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is the interface for the service manager which allows for non-specific access to the core services,
|
||||
* no dependency on the underlying mechanism is exposed
|
||||
* Allows for non-specific access to the core services.
|
||||
* No dependency on the underlying mechanism is exposed.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface ServiceManager {
|
||||
|
||||
/**
|
||||
* Allows developers to get the desired service singleton by the provided type <br/>
|
||||
* This should return all instantiated objects of the type specified (may not all be singletons)
|
||||
* Allows developers to get the desired service singleton by the provided type. <br/>
|
||||
* This should return all instantiated objects of the type specified
|
||||
* (may not all be singletons).
|
||||
*
|
||||
* @param <T>
|
||||
* @param type the type for the requested service (this will typically be the interface class but can be concrete as well)
|
||||
@@ -32,25 +33,35 @@ public interface ServiceManager {
|
||||
public <T> List<T> getServicesByType(Class<T> type);
|
||||
|
||||
/**
|
||||
* Allows developers to get the desired service singleton by the provided name and type,
|
||||
* can provide null for the name if it is not known but it is better to ensure it is set <br/>
|
||||
* NOTE: This also allows special access to the underlying service manager objects,
|
||||
* if using spring this allows access to the underlying ApplicationContext object like so: <br/>
|
||||
* Allows developers to get the desired service singleton by the provided name and type.
|
||||
* Provide {@code null} for the name if it is not known, but it is
|
||||
* better to ensure it is set.
|
||||
* <p>
|
||||
* <em>NOTE</em>: This also allows special access to the underlying
|
||||
* service manager objects. If using Spring this allows access to the
|
||||
* underlying ApplicationContext object like so:
|
||||
* <xmp>
|
||||
* getServiceByName(ApplicationContext.class.getName(), ApplicationContext.class);
|
||||
* if using Guice then the same applies like so: <br/>
|
||||
* </xmp>
|
||||
* If using Guice then the same applies like so:
|
||||
* <xmp>
|
||||
* getServiceByName(Injector.class.getName(), Injector.class);
|
||||
* it is also possible to register a module and cause Guice to fill in any injected core services (see register method)
|
||||
* </xmp>
|
||||
* It is also possible to register a module and cause Guice to fill
|
||||
* in any injected core services (see register method).
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* @param name (optional) the unique name for this service,
|
||||
* if null then the bean will be returned if there is only one service of this type
|
||||
* @param name (optional) the unique name for this service.
|
||||
* If null then the bean will be returned if there is only one
|
||||
* service of this type.
|
||||
* @param type the type for the requested service (this will typically be the interface class but can be concrete as well)
|
||||
* @return the service singleton OR null if none is found
|
||||
*/
|
||||
public <T> T getServiceByName(String name, Class<T> type);
|
||||
|
||||
/**
|
||||
* Lookup to see if a service exists with the given name
|
||||
* Lookup to see if a service exists with the given name.
|
||||
*
|
||||
* @param name the unique name for this service
|
||||
* @return true if it exists, false otherwise
|
||||
@@ -58,22 +69,31 @@ public interface ServiceManager {
|
||||
public boolean isServiceExists(String name);
|
||||
|
||||
/**
|
||||
* Get the names of all registered service singletons (by convention,
|
||||
* the name typically matches the fully qualified class name)
|
||||
* Get the names of all registered service singletons. By
|
||||
* convention, the name typically matches the fully qualified class
|
||||
* name).
|
||||
*
|
||||
* @return the list of all current registered services
|
||||
*/
|
||||
public List<String> getServicesNames();
|
||||
|
||||
/**
|
||||
* Allows adding singleton services and providers in at runtime or after the service manager has started up,
|
||||
* this is primarily useful for registering providers, filters, and plugins with the DSpace core <br/>
|
||||
* NOTE: It is important that you also call {@link #unregisterService(String)} if you are shutting
|
||||
* down the context (webapp, etc.) that registered the service so that the full lifecycle completes
|
||||
* correctly <br/>
|
||||
* NOTE: if using Guice it is possible to register a Guice Module as a service which will not
|
||||
* actually register it but will cause anything in the Module to have existing core services
|
||||
* injected into it, you can use anything as the name in this case
|
||||
* Allows adding singleton services and providers in at runtime or
|
||||
* after the service manager has started up.
|
||||
* This is primarily useful for registering providers, filters, and
|
||||
* plugins with the DSpace core.
|
||||
* <p>
|
||||
* <em>NOTE:</em> It is important that you also call
|
||||
* {@link #unregisterService(String)} if you are shutting
|
||||
* down the context (webapp, etc.) that registered the service so
|
||||
* that the full lifecycle completes correctly.
|
||||
* </p>
|
||||
* <p>
|
||||
* <em>NOTE:</em> if using Guice it is possible to register a Guice
|
||||
* Module as a service, which will not actually register it but will
|
||||
* cause anything in the Module to have existing core services injected
|
||||
* into it. You can use anything as the name in this case.
|
||||
* </p>
|
||||
*
|
||||
* @param name the name of the service (must be unique)
|
||||
* @param service the object to register as a singleton service
|
||||
@@ -82,12 +102,16 @@ public interface ServiceManager {
|
||||
public void registerService(String name, Object service);
|
||||
|
||||
/**
|
||||
* Allows adding singleton services and providers in at runtime or after the service manager has started up,
|
||||
* this is the same as {@link #registerService(String, Object)} except that it allows the core service
|
||||
* manager to startup your service for you instead of you providing a service to the core.
|
||||
* In general, it is better if you use your own service manager (like Spring or Guice) to manage your services
|
||||
* and simply inherit the core service beans from the DSpace core service manager using the special
|
||||
* capabilities of {@link #getServiceByName(String, Class)}
|
||||
* Allows adding singleton services and providers in at runtime or
|
||||
* after the service manager has started up.
|
||||
* This is the same as {@link #registerService(String, Object)}
|
||||
* except that it allows the core service manager to startup your
|
||||
* service for you instead of you providing a service to the core.
|
||||
* In general, it is better if you use your own service manager
|
||||
* (like Spring or Guice) to manage your services and simply
|
||||
* inherit the core service beans from the DSpace core service
|
||||
* manager using the special capabilities of
|
||||
* {@link #getServiceByName(String, Class)}.
|
||||
*
|
||||
* @see ServiceManager#getServiceByName(String, Class)
|
||||
* @param name the name of the service (must be unique)
|
||||
@@ -97,10 +121,14 @@ public interface ServiceManager {
|
||||
public <T> T registerServiceClass(String name, Class<T> type);
|
||||
|
||||
/**
|
||||
* Allows a service to be unregistered (this will only work if nothing depends on it),
|
||||
* this is primarily used for providers, filters, plugins, etc. which were registered
|
||||
* but are no longer available because the context they are running in is shutting down or restarting <br/>
|
||||
* WARNING: This should not be used to attempt to unregister core services as that will fail
|
||||
* Allows a service to be unregistered (which will only work if
|
||||
* nothing depends on it).
|
||||
* This is primarily used for providers, filters, plugins, etc.
|
||||
* which were registered but are no longer available because the
|
||||
* context they are running in is shutting down or restarting.
|
||||
* <br/>
|
||||
* WARNING: This should not be used to attempt to unregister core
|
||||
* services as that will fail.
|
||||
*
|
||||
* @param name the name of the service (must be unique)
|
||||
* @throws IllegalArgumentException if the bean cannot be unregistered
|
||||
@@ -108,9 +136,11 @@ public interface ServiceManager {
|
||||
public void unregisterService(String name);
|
||||
|
||||
/**
|
||||
* Allows new configuration settings to be pushed into the core DSpace configuration,
|
||||
* these will cause a settings refresh action to be called for all services which are listening
|
||||
* and will cause any bean properties to be pushed into existing beans
|
||||
* Allows new configuration settings to be pushed into the core
|
||||
* DSpace configuration.
|
||||
* These will cause a settings refresh action to be called for all
|
||||
* services which are listening and will cause any bean properties
|
||||
* to be pushed into existing beans.
|
||||
*
|
||||
* @param settings a map of keys (names) and values
|
||||
*/
|
||||
|
@@ -15,37 +15,46 @@ import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* DSpace Service/Provider mixin:
|
||||
* Allows a service to be notified when a configuration change occurs,
|
||||
* this is primarily useful for when someone wants to make a configuration change when
|
||||
* the system is already running without requiring a restart <br/>
|
||||
* This is a DSpace mixin which means it will be triggered because this is a DSpace service or provider,
|
||||
* the system will pick up on the fact that the java bean is implementing this interface and will
|
||||
* take the appropriate actions, there is no need to register this listener
|
||||
* Allow a service to be notified when a configuration change occurs.
|
||||
* This is primarily useful for when someone wants to make a
|
||||
* configuration change when the system is already running without
|
||||
* requiring a restart.
|
||||
* <p>
|
||||
* This is a DSpace mixin, which means it will be triggered because this
|
||||
* is a DSpace service or provider. The system will pick up on the fact
|
||||
* that the java bean is implementing this interface and will take the
|
||||
* appropriate actions; there is no need to register this listener.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface ConfigChangeListener {
|
||||
|
||||
/**
|
||||
* Allows the listener to filter the change notifications so it is only notified when
|
||||
* the named configuration items change, for example: <br/>
|
||||
* If this method returns an array with "upload.enabled" then whenever this configuration setting changes
|
||||
* the listener will be called. If any other settings change the listener will not be called
|
||||
* unless they are specific bean properties for this service (e.g. downloadEnabled@org.dspace.ThisService).
|
||||
* If you want to be notified when any configuration setting changes then simply return a null
|
||||
* or an empty string and the listener will be called for every configuration update.
|
||||
* Allows the listener to filter the change notifications so it is
|
||||
* only notified when the named configuration items change. For example,
|
||||
* if this method returns an array containing {@code "upload.enabled"}
|
||||
* then whenever this configuration setting changes the listener will be
|
||||
* called. If any other settings change the listener will not be
|
||||
* called unless they are specific bean properties for this service
|
||||
* (e.g. {@code downloadEnabled@org.dspace.ThisService}).
|
||||
* If you want to be notified when <em>any</em> configuration
|
||||
* setting changes then simply return a null or an empty string and
|
||||
* the listener will be called for every configuration update.
|
||||
*
|
||||
* @return an array of configuration string names (e.g. {"system.name","upload.enabled"})
|
||||
* @return an array of configuration string names (e.g. {"system.name","upload.enabled"})
|
||||
* OR null/empty to be notified for every configuration setting that changes
|
||||
*/
|
||||
public String[] notifyForConfigNames();
|
||||
|
||||
/**
|
||||
* This listener method will be called whenever the configuration settings change (depending on the filter),
|
||||
* this will only be called once for each config update regardless of the number of settings that were actually changed <br/>
|
||||
* NOTE: This will strip off the beanName from any service property settings,
|
||||
* Example: downloadEnabled@org.dspace.ThisService => downloadEnabled <br/>
|
||||
* Called whenever the configuration settings change (depending on
|
||||
* the filter).
|
||||
* This will only be called once for each config update regardless
|
||||
* of the number of settings that were actually changed.
|
||||
* <p>
|
||||
* NOTE: This will strip off the beanName from any service property
|
||||
* settings.
|
||||
* Example: downloadEnabled@org.dspace.ThisService => downloadEnabled
|
||||
*
|
||||
* @param changedSettingNames includes the names of all settings that changed
|
||||
* @param changedSettings includes the map of all settings that changed
|
||||
|
@@ -11,16 +11,18 @@
|
||||
package org.dspace.kernel.mixins;
|
||||
|
||||
/**
|
||||
* This service mixin will cause the service/provider/etc. to be initialized when it is started by the service
|
||||
* manager, after all injections are complete the init method will be called,
|
||||
* any initialization that a service needs to do should happen here
|
||||
* Allow the service or provider to be initialized when it is started
|
||||
* by the service manager. After all injections are complete the init
|
||||
* method will be called. Any initialization that a service needs to do
|
||||
* should happen here.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface InitializedService {
|
||||
|
||||
/**
|
||||
* Executed after the service is created and has had all dependencies and configurations injected
|
||||
* Executed after the service is created and all dependencies and
|
||||
* configurations injected.
|
||||
*/
|
||||
public void init();
|
||||
|
||||
|
@@ -12,9 +12,10 @@ package org.dspace.kernel.mixins;
|
||||
|
||||
|
||||
/**
|
||||
* This service mixin will cause the service/provider/etc. to be ordered against other
|
||||
* classes that implement the same interface (not this one),
|
||||
* classes that do not implement this interface
|
||||
* Permit the service or provider to be ordered against other
|
||||
* classes that implement the same interface (not this one).
|
||||
* Classes that do not implement this interface may be initialized in
|
||||
* any order.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
@@ -22,10 +23,12 @@ public interface OrderedService {
|
||||
|
||||
/**
|
||||
* Sets the order to load the bean which implements this method compared
|
||||
* to other beans of the same type, lower orders (numbers) will be loaded first
|
||||
* (i.e. order 1 will appear before order 3 in the list) and the
|
||||
* orders do not have to be consecutive (there can be gaps),
|
||||
* 2 beans with the same order or beans with no order set will be ordered randomly
|
||||
* to other beans of the same type. Lower orders (numbers) will be
|
||||
* loaded first (i.e. order 1 will appear before order 3 in the
|
||||
* list). Orders do not have to be consecutive (there can be gaps).
|
||||
* Beans with the same order or beans with no order set will be
|
||||
* ordered randomly.
|
||||
*
|
||||
* @return an int which represents the loading order
|
||||
*/
|
||||
public int getOrder();
|
||||
|
@@ -13,29 +13,33 @@ package org.dspace.kernel.mixins;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This service manager mixin will allow a service to be notified when other services change,
|
||||
* this is useful for keeping an eye on changing providers, filters, and other services which
|
||||
* drop in and out
|
||||
* Allow a service to be notified when other services change.
|
||||
* This is useful for keeping an eye on changing providers, filters, and
|
||||
* other services which drop in and out.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface ServiceChangeListener {
|
||||
|
||||
/**
|
||||
* Allows filtering so that notifications are only sent when classes implement
|
||||
* or are of one of the types specified, the listener method will only
|
||||
* be called once regardless of how many types match <br/>
|
||||
* Just return null or empty array to be notified for all service registrations
|
||||
* Allows filtering so that notifications are only sent when classes
|
||||
* implement one of the types specified. The listener method will
|
||||
* only be called once regardless of how many types match.
|
||||
* <p>
|
||||
* Just return null or empty array to be notified for all service
|
||||
* registrations.
|
||||
*
|
||||
* @return an array of classes OR null to be notified of all service registrations
|
||||
*/
|
||||
public Class<?>[] notifyForTypes();
|
||||
|
||||
/**
|
||||
* This will be called when services are newly registered with the service manager
|
||||
* (will not be called when the core services are starting up though) <br/>
|
||||
* It is not called until the service is fully initialized and
|
||||
* is called once and only once per service that is registered <br/>
|
||||
* This will be called when services are newly registered with the
|
||||
* service manager. It will not be called when the core services
|
||||
* are starting up though.
|
||||
* <p>
|
||||
* It is not called until the service is fully initialized.
|
||||
* It is called once and only once per service that is registered.
|
||||
*
|
||||
* @param serviceName the name of the service
|
||||
* @param service the service bean
|
||||
@@ -44,11 +48,14 @@ public interface ServiceChangeListener {
|
||||
public void serviceRegistered(String serviceName, Object service, List<Class<?>> implementedTypes);
|
||||
|
||||
/**
|
||||
* This will be called when services are removed from the service manager,
|
||||
* services which are replaced will not have this method called and will only call
|
||||
* {@link #serviceRegistered(String, Object, List)} <br/>
|
||||
* This will be called when services are removed from the service
|
||||
* manager.
|
||||
* Services which are replaced will not have this method called and
|
||||
* will only receive
|
||||
* {@link #serviceRegistered(String, Object, List)}.
|
||||
* <p>
|
||||
* It is called immediately before the service is completely destroyed
|
||||
* so that the service object is still valid <br/>
|
||||
* so that the service object is still valid.
|
||||
*
|
||||
* @param serviceName the name of the service
|
||||
* @param service the service bean
|
||||
|
@@ -13,19 +13,23 @@ package org.dspace.kernel.mixins;
|
||||
import org.dspace.kernel.ServiceManager;
|
||||
|
||||
/**
|
||||
* This service manager mixin will cause a service to be notified when the servicemanager has started
|
||||
* up all known services (including activators), this is useful if a service wants to do lookups
|
||||
* of all known services or providers of a certain type when the system startup is complete,
|
||||
* it can also be used as a way to execute some code when the service manager startup is complete
|
||||
* Allow a service to be notified when the service manager has started
|
||||
* up all known services (including activators). This is useful if a
|
||||
* service wants to do lookups of all known services or providers of a
|
||||
* certain type when the system startup is complete. It can also be
|
||||
* used as a way to execute some code when the service manager startup
|
||||
* is complete.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface ServiceManagerReadyAware {
|
||||
|
||||
/**
|
||||
* This is called when the startup of all core services and activators is complete <br/>
|
||||
* WARNING: This will never be called for providers which are registered with a servicemanager
|
||||
* which is already running!
|
||||
* This is called when the startup of all core services and
|
||||
* activators is complete.
|
||||
* <p>
|
||||
* WARNING: This will never be called for providers which are
|
||||
* registered with a service manager which is already running!
|
||||
*
|
||||
* @param serviceManager the completely started service manager
|
||||
*/
|
||||
|
@@ -12,16 +12,17 @@ package org.dspace.kernel.mixins;
|
||||
|
||||
|
||||
/**
|
||||
* This service mixin will cause the service/provider/etc. to be shutdown when the service manager is shutting down the service,
|
||||
* this will typically be called when the kernel is stopped or destroyed,
|
||||
* any cleanup that a service needs to do when it is shutdown should happen here
|
||||
* Allow the service to be notified when the service manager is shutting
|
||||
* it down. This will typically be called when the kernel is stopped or
|
||||
* destroyed. Any cleanup that a service needs to do when it is
|
||||
* shut down should happen here.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface ShutdownService {
|
||||
|
||||
/**
|
||||
* Called as the service manager is stopping or shutting down
|
||||
* Called as the service manager is stopping or shutting down.
|
||||
*/
|
||||
public void shutdown();
|
||||
|
||||
|
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Interfaces for interacting with the startup, shutdown, or
|
||||
* reconfiguration of the framework.
|
||||
*/
|
||||
|
||||
package org.dspace.kernel.mixins;
|
5
api/src/main/java/org/dspace/kernel/package-info.java
Normal file
5
api/src/main/java/org/dspace/kernel/package-info.java
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* The DSpace Services kernel and service manager.
|
||||
*/
|
||||
|
||||
package org.dspace.kernel;
|
@@ -17,37 +17,45 @@ import org.dspace.services.model.CacheConfig;
|
||||
|
||||
|
||||
/**
|
||||
* This is a provider (pluggable functionality) for DSpace<br/>
|
||||
* This allows an external system to define how caches are handled in DSpace by implementing this interface
|
||||
* and registering it with the service manager<br/>
|
||||
* This is a provider (pluggable functionality) for DSpace.
|
||||
* <p>
|
||||
* This allows an external system to define how caches are handled in
|
||||
* DSpace by implementing this interface and registering it with the
|
||||
* service manager.
|
||||
* </p>
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public interface CacheProvider {
|
||||
|
||||
/**
|
||||
* Gets all the caches that this provider knows about
|
||||
* Gets all the caches that this provider knows about.
|
||||
*
|
||||
* @return a list of all the caches which the caching service knows about
|
||||
*/
|
||||
public List<Cache> getCaches();
|
||||
|
||||
/**
|
||||
* Construct a {@link Cache} with the given name (must be unique) OR retrieve the one
|
||||
* that already exists with this name <br/>
|
||||
* NOTE: providers will never be asked to provide request caches (e.g. {@link CacheConfig.CacheScope#REQUEST})
|
||||
* Construct a {@link Cache} with the given name (must be unique) OR
|
||||
* retrieve the one that already exists with this name.
|
||||
* <p>
|
||||
* NOTE: providers will never be asked to provide request caches
|
||||
* (e.g. {@link CacheConfig.CacheScope#REQUEST})
|
||||
*
|
||||
* @param cacheName the unique name for this cache (e.g. org.dspace.user.UserCache)
|
||||
* @param config (optional) a configuration object, the cache should adhere to the settings in it,
|
||||
* if it is null then just use defaults
|
||||
* @param config (optional) a configuration object. The cache
|
||||
* should adhere to the settings in it. If it is null then just use
|
||||
* defaults.
|
||||
* @return a cache which can be used to store serializable objects
|
||||
* @throws IllegalArgumentException if the cache name is already in use or the config is invalid
|
||||
*/
|
||||
public Cache getCache(String cacheName, CacheConfig config);
|
||||
|
||||
/**
|
||||
* Flush and destroy the cache with this name,
|
||||
* if the cache does not exist then this does nothing (should not fail if the cache does not exist)
|
||||
* Flush and destroy the cache with this name.
|
||||
* If the cache does not exist then this does nothing (should not
|
||||
* fail if the cache does not exist).
|
||||
*
|
||||
* @param cacheName the unique name for this cache (e.g. org.dspace.user.UserCache)
|
||||
*/
|
||||
public void destroyCache(String cacheName);
|
||||
|
5
api/src/main/java/org/dspace/providers/package-info.java
Normal file
5
api/src/main/java/org/dspace/providers/package-info.java
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Pluggable alternatives for some core functions
|
||||
*/
|
||||
|
||||
package org.dspace.providers;
|
@@ -40,13 +40,16 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is the kernel implementation which starts up the core of DSpace and
|
||||
* registers the mbean and initializes the {@link DSpace} object,
|
||||
* it also loads up the configuration <br/>
|
||||
* Note that this does not start itself and calling the constuctor does not actually
|
||||
* start it up either. It has to be explicitly started by calling the start method
|
||||
* so something in the system needs to do that. If the bean is already started then calling start on
|
||||
* it again has no effect. <br/>
|
||||
* This is the kernel implementation which starts up the core of DSpace,
|
||||
* registers the mbean, and initializes the {@link DSpace} object.
|
||||
* It also loads up the configuration. Sets a JRE shutdown hook.
|
||||
* <p>
|
||||
* Note that this does not start itself and calling the constuctor does
|
||||
* not actually start it up either. It has to be explicitly started by
|
||||
* calling the start method so something in the system needs to do that.
|
||||
* If the bean is already started then calling start on it again has no
|
||||
* effect.
|
||||
* <p>
|
||||
* The name of this instance can be specified if desired.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
@@ -54,9 +57,11 @@ import org.slf4j.LoggerFactory;
|
||||
public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifecycle<DSpaceKernel> {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(DSpaceKernelImpl.class);
|
||||
|
||||
/**
|
||||
* Creates a DSpace Kernel, does not do any checks though,
|
||||
* do not call this, use {@link DSpaceKernelInit#getKernel(String)}
|
||||
* Creates a DSpace Kernel, does not do any checks though.
|
||||
* Do not call this; use {@link DSpaceKernelInit#getKernel(String)}.
|
||||
*
|
||||
* @param name the name for the kernel
|
||||
*/
|
||||
protected DSpaceKernelImpl(String name) {
|
||||
@@ -70,6 +75,7 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
|
||||
private DSpaceKernel kernel = null;
|
||||
|
||||
private Thread shutdownHook;
|
||||
|
||||
protected void registerShutdownHook() {
|
||||
if (this.shutdownHook == null) {
|
||||
synchronized (lock) {
|
||||
@@ -125,9 +131,14 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
|
||||
public void start() {
|
||||
start(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This starts up the entire core system. May be called more than
|
||||
* once: subsequent calls return without effect.
|
||||
*
|
||||
* @param dspaceHome path to FIXME
|
||||
*/
|
||||
public void start(String dspaceHome) {
|
||||
// this starts up the entire core system
|
||||
if (running) {
|
||||
//log.warn("Kernel ("+this+") is already started");
|
||||
return;
|
||||
@@ -221,7 +232,7 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
|
||||
}
|
||||
|
||||
/**
|
||||
* allows this to be called from within the shutdown thread
|
||||
* Called from within the shutdown thread.
|
||||
*/
|
||||
protected void doDestroy() {
|
||||
if (! this.destroyed) {
|
||||
@@ -247,10 +258,13 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
|
||||
// MBEAN methods
|
||||
|
||||
private Date lastLoadDate;
|
||||
/** Time that this kernel was started, as a java.util.Date. */
|
||||
public Date getLastLoadDate() {
|
||||
return new Date(lastLoadDate.getTime());
|
||||
}
|
||||
|
||||
private long loadTime;
|
||||
/** Time that this kernel was started, as seconds since the epoch. */
|
||||
public long getLoadTime() {
|
||||
return loadTime;
|
||||
}
|
||||
|
@@ -15,8 +15,8 @@ import org.dspace.servicemanager.config.DSpaceConfig;
|
||||
|
||||
|
||||
/**
|
||||
* This holds the settings for a service config triple,
|
||||
* can create this from a {@link DSpaceConfig} object
|
||||
* This holds the settings for a service config triple.
|
||||
* Create this from a {@link DSpaceConfig} object, or by name and value.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
@@ -26,6 +26,7 @@ public class ServiceConfig {
|
||||
private String serviceName;
|
||||
private Object value;
|
||||
|
||||
/** Construct from scratch. */
|
||||
public ServiceConfig(String paramName, String serviceName, Object value) {
|
||||
if (paramName == null || serviceName == null) {
|
||||
throw new IllegalArgumentException("paramName and serviceName must not be null");
|
||||
@@ -35,6 +36,7 @@ public class ServiceConfig {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** Construct from an existing DSpaceConfig. */
|
||||
public ServiceConfig(DSpaceConfig dspaceConfig) {
|
||||
this.paramName = dspaceConfig.getBeanProperty();
|
||||
this.serviceName = dspaceConfig.getBeanName();
|
||||
|
@@ -29,8 +29,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Borrowed from EntityBus since this already will handle the mixins for something correctly and easily,
|
||||
* no need to reinvent this
|
||||
* Maintain a map of services and their mixin interfaces.
|
||||
*
|
||||
* Borrowed from EntityBus since this already will handle the mixins for
|
||||
* something correctly and easily. No need to reinvent this.
|
||||
*
|
||||
* @author Aaron Zeckoski (aaronz@vt.edu)
|
||||
*/
|
||||
@@ -40,13 +42,15 @@ public class ServiceMixinManager {
|
||||
|
||||
/**
|
||||
* This is a map from the serviceName only to the service and also
|
||||
* from the bikey made from the serviceName AND the implemented interfaces and superclasses to the service,
|
||||
* in other words, a service which implements 3 interfaces should have 4 entries in the map
|
||||
* from the bikey made from the serviceName AND the implemented
|
||||
* interfaces and superclasses to the service.
|
||||
* In other words, a service which implements 3 interfaces should
|
||||
* have 4 entries in the map.
|
||||
*/
|
||||
protected ReferenceMap<String, Object> serviceNameMap = new ReferenceMap<String, Object>(ReferenceType.STRONG, ReferenceType.SOFT);
|
||||
|
||||
/**
|
||||
* Looks up a service by the well known name
|
||||
* Looks up a service by the well known name.
|
||||
* @param serviceName the well known and unique service name
|
||||
* @return the service OR null if none can be found
|
||||
*/
|
||||
@@ -60,6 +64,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a service by name and mixin type.
|
||||
* @param <T>
|
||||
* @param serviceName the well known and unique service name
|
||||
* @param mixin the class type of the implemented mixin interface
|
||||
@@ -81,6 +86,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* List known services by name.
|
||||
* @return the list of all known service names
|
||||
*/
|
||||
public List<String> getRegisteredServiceNames() {
|
||||
@@ -97,6 +103,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* List known services by FIXME.
|
||||
* @return all known registered services
|
||||
*/
|
||||
public List<Object> getRegisteredServices() {
|
||||
@@ -114,6 +121,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* List known mixin types for a named service.
|
||||
* @param serviceName the well known and unique service name
|
||||
* @return the list of all known mixins for this service
|
||||
*/
|
||||
@@ -134,6 +142,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Map service names to mixin types.
|
||||
* WARNING: this is slow so do not use it unless you really need it!
|
||||
* @return the map of all service names -> mixins that are currently registered
|
||||
*/
|
||||
@@ -152,7 +161,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows retrieval of service and their names
|
||||
* Allows retrieval of service and their names.
|
||||
* @param <T>
|
||||
* @param mixin an interface which is a service mixin (technically any class)
|
||||
* @return the list of all registered services wrapped in service holders which implement this mixin interface
|
||||
@@ -176,6 +185,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* List services implementing a given mixin.
|
||||
* @param <T>
|
||||
* @param mixin an interface which is a service mixin (technically any class)
|
||||
* @return the list of all registered services which implement this mixin interface
|
||||
@@ -198,8 +208,8 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a service with the system and extracts all mixins,
|
||||
* this will manage and track the mixins and the service
|
||||
* Registers a service with the system and extracts all mixins.
|
||||
* This will manage and track the mixins and the service.
|
||||
*
|
||||
* @param serviceName the well known and unique service name
|
||||
* @param service the service itself
|
||||
@@ -239,7 +249,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a service and throws out all the mapped mixins
|
||||
* Unregisters a service and throws out all the mapped mixins.
|
||||
*
|
||||
* @param serviceName the well known and unique service name
|
||||
* @return the list of mixin classes registered for this service
|
||||
@@ -270,7 +280,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a single mixin from a service
|
||||
* Unregisters a single mixin from a service.
|
||||
*
|
||||
* @param serviceName the well known and unique service name
|
||||
* @param mixin an interface which is a service mixin (technically any class)
|
||||
@@ -291,11 +301,11 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for easy registration of a serviceName and mixin
|
||||
* Allows for easy registration of a serviceName and mixin.
|
||||
*
|
||||
* @param serviceName
|
||||
* @param mixin
|
||||
* @param service
|
||||
* @param serviceName the well known and unique service name
|
||||
* @param mixin a service mixin interface
|
||||
* @param entityProvider
|
||||
* @return true if the service is newly registered, false if it was already registered
|
||||
*/
|
||||
public boolean registerPrefixCapability(String serviceName,
|
||||
@@ -305,7 +315,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all service registrations
|
||||
* Clears all service registrations.
|
||||
*
|
||||
* @return the number of currently registered service names
|
||||
*/
|
||||
@@ -317,6 +327,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Count registered services.
|
||||
* @return the number of currently registered services
|
||||
*/
|
||||
public int size() {
|
||||
@@ -378,7 +389,7 @@ public class ServiceMixinManager {
|
||||
// STATICS - OTHER
|
||||
|
||||
/**
|
||||
* Attempts to get a class by name in the current classloader
|
||||
* Attempts to get a class by name in the current classloader.
|
||||
* @param className the classname (fully qualified)
|
||||
* @return the class object
|
||||
* @throws RuntimeException if the class is not found
|
||||
@@ -400,9 +411,10 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mixins implemented by this service,
|
||||
* only gets interfaces and will not pick up superclasses <br/>
|
||||
* WARNING: this is not the fastest ever
|
||||
* Get the mixins implemented by this service.
|
||||
* Only gets interfaces and will not pick up superclasses.
|
||||
* <p>
|
||||
* WARNING: this is not the fastest ever.
|
||||
*
|
||||
* @param service any object
|
||||
* @return the list of services this class implements
|
||||
@@ -423,7 +435,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares based on the class name
|
||||
* Compares classes by name.
|
||||
*/
|
||||
public static class ClassComparator implements Comparator<Class<?>>, Serializable {
|
||||
public final static long serialVersionUID = 1l;
|
||||
@@ -436,7 +448,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares based on the class name
|
||||
* Compares objects by class name.
|
||||
*/
|
||||
public static class ServiceComparator implements Comparator<Object>, Serializable {
|
||||
public final static long serialVersionUID = 1l;
|
||||
@@ -449,17 +461,19 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* A class designed to carry services and their names for type safety
|
||||
* Carry services and their names for type safety.
|
||||
*/
|
||||
public static class ServiceHolder<T> {
|
||||
public String serviceName;
|
||||
public T service;
|
||||
|
||||
/**
|
||||
* @return the service object cast to the type requested (probably not the type of the actual object)
|
||||
*/
|
||||
public T getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name the service is registered under
|
||||
*/
|
||||
@@ -473,6 +487,7 @@ public class ServiceMixinManager {
|
||||
this.serviceName = serviceName;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return serviceName+":"+service.getClass().getName()+":"+super.toString();
|
||||
@@ -480,7 +495,7 @@ public class ServiceMixinManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares based on the service
|
||||
* Compares {@code ServiceHolder}s by name.
|
||||
*/
|
||||
public static class ServiceHolderComparator implements Comparator<ServiceHolder<?>>, Serializable {
|
||||
public final static long serialVersionUID = 1l;
|
||||
|
Reference in New Issue
Block a user