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:
Mark Wood
2010-05-20 17:42:25 +00:00
parent 90e529a6d2
commit 31dd9eaec2
19 changed files with 344 additions and 189 deletions

View File

@@ -12,45 +12,67 @@ package org.dspace.constants;
/** /**
* All core DSpace constants * All core DSpace Services constants.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public class Constants { public class Constants {
/** /**
* If this is set to true then DSpace kernel is run as if it is inside a unit test, * If this is set to true then DSpace kernel is run as if it is
* this means that nothing is persisted (things are run in-memory only) and * inside a unit test. This means that nothing is persisted (things
* caches and other speed optimizing parts are reduced, * are run in-memory only) and caches and other speed optimizing
* this should NEVER be set in a production system * parts are reduced. This should NEVER be set true in a production
* system.
*/ */
public static final String DSPACE_TESTING_MODE = "dspace.testing"; 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"; public static final String DSPACE_TIMER_NAME = "DSpaceTimer";
/** /**
* HSQLDB, DERBY, ORACLE, MYSQL, POSTGRES, DB2, MSSQL * Configuration key for the name of the DBMS being used.
* Note that H2 uses HSQLDB key * HSQLDB, DERBY, ORACLE, MYSQL, POSTGRES, DB2, MSSQL.
* Note that H2 uses the HSQLDB key.
*/ */
public static final String DATABASE_TYPE_KEY = "jdbc.database.type"; public static final String DATABASE_TYPE_KEY = "jdbc.database.type";
/** /**
* Class of the JDBC driver.
* Embedded drivers are: * Embedded drivers are:
* org.h2.Driver * <ul>
* org.apache.derby.jdbc.EmbeddedDriver * <li>org.h2.Driver</li>
* org.hsqldb.jdbcDriver * <li>org.apache.derby.jdbc.EmbeddedDriver</li>
* Put your driver in the lib directory for your servlet container * <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_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 DATABASE_CONN_POOLING = "jdbc.dataSource.pooling";
/**
*
*/
public static final String DEFAULT_ENCODING = "UTF-8"; public static final String DEFAULT_ENCODING = "UTF-8";
} }

View File

@@ -0,0 +1,5 @@
/**
* Manifest constants naming configuration data for core services.
*/
package org.dspace.constants;

View File

@@ -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 * 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 * 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 * initial classes and the service manager have already been started. All classes which implement this
* must have: <br/> * must have a public empty constructor (takes no parameters) (e.g.
* 1) A public empty constructor (takes no parameters) (e.g. public MyClass() {} ) <br/> * {@code public MyClass() {}} )
* <br/> * <p>
* If you want the system to execute your class then you must list it in the config file with the fully qualified classpath * 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/> * (NOTE that the xxx can be anything as long as it is unique): <br/>
* <b>activator.xxx = org.dspace.MyClass</b> <br/> * {@code activator.xxx = org.dspace.MyClass}
* <br/> * </p>
* <p>
* {@link #start(ServiceManager)} will be called after the class is created during kernel startup. * {@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 * Developers should create their providers/plugins/etc. in this method and
* use the registration methods in the {@link ServiceManager} to register them. * 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 * {@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/> * you like during this phase (unregistering your services here is a good idea). <br/>
* <br/> * </p>
* This is modeled after the OSGi BundleActivator <br/> * <p>This is modeled after the OSGi {@code BundleActivator}.</p>
* <br/> * <p>
* There is another type of activator used in DSpace but it is configured via the configuration service only. * There is another type of activator used in DSpace but it is
* The class activator is configured by creating a config property like this * 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/> * (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/> * {@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 * Unlike the normal activators, these are started up when the kernel
* be accessed from the service manager and referenced in providers and plugins. * 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) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface Activator { 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 * 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 * 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/> * to simply perform some system startup actions if desired.
* Exceptions thrown out of this method will not cause the system startup to fail. <br/> * <p>
* Exceptions thrown out of this method will not cause the system startup to fail.
* *
* @param serviceManager the current system service manager * @param serviceManager the current system service manager
*/ */
public void start(ServiceManager serviceManager); 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 * 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 * 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/> * to simply perform some system shutdown actions if desired.
* Exceptions thrown out of this method will not cause the system shutdown to fail. <br/> * <p>
* WARNING: this can hang the shutdown by performing operations that take a long long time or are deadlocked, * Exceptions thrown out of this method will not cause the system shutdown to fail.
* the developer is expected to ensure this does not happen * <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 * @param serviceManager the current system service manager
*/ */

View File

@@ -13,8 +13,8 @@ package org.dspace.kernel;
import org.dspace.services.ConfigurationService; import org.dspace.services.ConfigurationService;
/** /**
* The interface of the Kernel, * This is the most core piece of the system: instantiating one will
* this is the most core piece of the system and initalizing this will startup the dspace core * startup the dspace services framework.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */

View File

@@ -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) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
@@ -40,8 +40,9 @@ public class DSpaceKernelManager {
private Object lock = new Object(); private Object lock = new Object();
/** /**
* Get the kernel, this will be a single instance for the JVM, but the method will retrieve * Get the kernel. This will be a single instance for the JVM, but
* the same instance regardless of this object instance. * the method will retrieve the same instance regardless of this
* object instance.
* *
* @return the DSpace kernel * @return the DSpace kernel
* @throws IllegalStateException if the kernel is not available * @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 * Get the kernel. This will be a single instance for the JVM, but
* the same instance regardless of this object instance. * 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 * @return the DSpace kernel
* @throws IllegalStateException if the kernel is not available or not running * @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(); private static String defaultKernelName = UUID.randomUUID().toString();
/** /**
* Ensure that we have a name suitable for an mbean.
* @param name the name for the kernel * @param name the name for the kernel
* @return a proper mbean name based on the given name * @return a proper mbean name based on the given name
*/ */

View File

@@ -14,16 +14,17 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* This is the interface for the service manager which allows for non-specific access to the core services, * Allows for non-specific access to the core services.
* no dependency on the underlying mechanism is exposed * No dependency on the underlying mechanism is exposed.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface ServiceManager { public interface ServiceManager {
/** /**
* Allows developers to get the desired service singleton by the provided type <br/> * 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) * This should return all instantiated objects of the type specified
* (may not all be singletons).
* *
* @param <T> * @param <T>
* @param type the type for the requested service (this will typically be the interface class but can be concrete as well) * @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); public <T> List<T> getServicesByType(Class<T> type);
/** /**
* Allows developers to get the desired service singleton by the provided name and 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/> * Provide {@code null} for the name if it is not known, but it is
* NOTE: This also allows special access to the underlying service manager objects, * better to ensure it is set.
* if using spring this allows access to the underlying ApplicationContext object like so: <br/> * <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); * 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); * 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 <T>
* @param name (optional) the unique name for this service, * @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 * 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) * @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 * @return the service singleton OR null if none is found
*/ */
public <T> T getServiceByName(String name, Class<T> type); 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 * @param name the unique name for this service
* @return true if it exists, false otherwise * @return true if it exists, false otherwise
@@ -58,22 +69,31 @@ public interface ServiceManager {
public boolean isServiceExists(String name); public boolean isServiceExists(String name);
/** /**
* Get the names of all registered service singletons (by convention, * Get the names of all registered service singletons. By
* the name typically matches the fully qualified class name) * convention, the name typically matches the fully qualified class
* name).
* *
* @return the list of all current registered services * @return the list of all current registered services
*/ */
public List<String> getServicesNames(); public List<String> getServicesNames();
/** /**
* Allows adding singleton services and providers in at runtime or after the service manager has started up, * Allows adding singleton services and providers in at runtime or
* this is primarily useful for registering providers, filters, and plugins with the DSpace core <br/> * after the service manager has started up.
* NOTE: It is important that you also call {@link #unregisterService(String)} if you are shutting * This is primarily useful for registering providers, filters, and
* down the context (webapp, etc.) that registered the service so that the full lifecycle completes * plugins with the DSpace core.
* correctly <br/> * <p>
* NOTE: if using Guice it is possible to register a Guice Module as a service which will not * <em>NOTE:</em> It is important that you also call
* actually register it but will cause anything in the Module to have existing core services * {@link #unregisterService(String)} if you are shutting
* injected into it, you can use anything as the name in this case * 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 name the name of the service (must be unique)
* @param service the object to register as a singleton service * @param service the object to register as a singleton service
@@ -82,12 +102,16 @@ public interface ServiceManager {
public void registerService(String name, Object service); public void registerService(String name, Object service);
/** /**
* Allows adding singleton services and providers in at runtime or after the service manager has started up, * Allows adding singleton services and providers in at runtime or
* this is the same as {@link #registerService(String, Object)} except that it allows the core service * after the service manager has started up.
* manager to startup your service for you instead of you providing a service to the core. * This is the same as {@link #registerService(String, Object)}
* In general, it is better if you use your own service manager (like Spring or Guice) to manage your services * except that it allows the core service manager to startup your
* and simply inherit the core service beans from the DSpace core service manager using the special * service for you instead of you providing a service to the core.
* capabilities of {@link #getServiceByName(String, Class)} * 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) * @see ServiceManager#getServiceByName(String, Class)
* @param name the name of the service (must be unique) * @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); public <T> T registerServiceClass(String name, Class<T> type);
/** /**
* Allows a service to be unregistered (this will only work if nothing depends on it), * Allows a service to be unregistered (which will only work if
* this is primarily used for providers, filters, plugins, etc. which were registered * nothing depends on it).
* but are no longer available because the context they are running in is shutting down or restarting <br/> * This is primarily used for providers, filters, plugins, etc.
* WARNING: This should not be used to attempt to unregister core services as that will fail * 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) * @param name the name of the service (must be unique)
* @throws IllegalArgumentException if the bean cannot be unregistered * @throws IllegalArgumentException if the bean cannot be unregistered
@@ -108,9 +136,11 @@ public interface ServiceManager {
public void unregisterService(String name); public void unregisterService(String name);
/** /**
* Allows new configuration settings to be pushed into the core DSpace configuration, * Allows new configuration settings to be pushed into the core
* these will cause a settings refresh action to be called for all services which are listening * DSpace configuration.
* and will cause any bean properties to be pushed into existing beans * 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 * @param settings a map of keys (names) and values
*/ */

View File

@@ -15,26 +15,31 @@ import java.util.Map;
/** /**
* DSpace Service/Provider mixin: * Allow a service to be notified when a configuration change occurs.
* Allows a service to be notified when a configuration change occurs, * This is primarily useful for when someone wants to make a
* this is primarily useful for when someone wants to make a configuration change when * configuration change when the system is already running without
* the system is already running without requiring a restart <br/> * requiring a restart.
* This is a DSpace mixin which means it will be triggered because this is a DSpace service or provider, * <p>
* the system will pick up on the fact that the java bean is implementing this interface and will * This is a DSpace mixin, which means it will be triggered because this
* take the appropriate actions, there is no need to register this listener * 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) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface ConfigChangeListener { public interface ConfigChangeListener {
/** /**
* Allows the listener to filter the change notifications so it is only notified when * Allows the listener to filter the change notifications so it is
* the named configuration items change, for example: <br/> * only notified when the named configuration items change. For example,
* If this method returns an array with "upload.enabled" then whenever this configuration setting changes * if this method returns an array containing {@code "upload.enabled"}
* the listener will be called. If any other settings change the listener will not be called * then whenever this configuration setting changes the listener will be
* unless they are specific bean properties for this service (e.g. downloadEnabled@org.dspace.ThisService). * called. If any other settings change the listener will not be
* If you want to be notified when any configuration setting changes then simply return a null * called unless they are specific bean properties for this service
* or an empty string and the listener will be called for every configuration update. * (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 * OR null/empty to be notified for every configuration setting that changes
@@ -42,10 +47,14 @@ public interface ConfigChangeListener {
public String[] notifyForConfigNames(); public String[] notifyForConfigNames();
/** /**
* This listener method will be called whenever the configuration settings change (depending on the filter), * Called whenever the configuration settings change (depending on
* this will only be called once for each config update regardless of the number of settings that were actually changed <br/> * the filter).
* NOTE: This will strip off the beanName from any service property settings, * This will only be called once for each config update regardless
* Example: downloadEnabled@org.dspace.ThisService => downloadEnabled <br/> * 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 =&gt; downloadEnabled
* *
* @param changedSettingNames includes the names of all settings that changed * @param changedSettingNames includes the names of all settings that changed
* @param changedSettings includes the map of all settings that changed * @param changedSettings includes the map of all settings that changed

View File

@@ -11,16 +11,18 @@
package org.dspace.kernel.mixins; package org.dspace.kernel.mixins;
/** /**
* This service mixin will cause the service/provider/etc. to be initialized when it is started by the service * Allow the service or provider to be initialized when it is started
* manager, after all injections are complete the init method will be called, * by the service manager. After all injections are complete the init
* any initialization that a service needs to do should happen here * method will be called. Any initialization that a service needs to do
* should happen here.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface InitializedService { 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(); public void init();

View File

@@ -12,9 +12,10 @@ package org.dspace.kernel.mixins;
/** /**
* This service mixin will cause the service/provider/etc. to be ordered against other * Permit the service or provider to be ordered against other
* classes that implement the same interface (not this one), * classes that implement the same interface (not this one).
* classes that do not implement this interface * Classes that do not implement this interface may be initialized in
* any order.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @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 * 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 * to other beans of the same type. Lower orders (numbers) will be
* (i.e. order 1 will appear before order 3 in the list) and the * loaded first (i.e. order 1 will appear before order 3 in the
* orders do not have to be consecutive (there can be gaps), * list). 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 * Beans with the same order or beans with no order set will be
* ordered randomly.
*
* @return an int which represents the loading order * @return an int which represents the loading order
*/ */
public int getOrder(); public int getOrder();

View File

@@ -13,29 +13,33 @@ package org.dspace.kernel.mixins;
import java.util.List; import java.util.List;
/** /**
* This service manager mixin will allow a service to be notified when other services change, * 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 * This is useful for keeping an eye on changing providers, filters, and
* drop in and out * other services which drop in and out.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface ServiceChangeListener { public interface ServiceChangeListener {
/** /**
* Allows filtering so that notifications are only sent when classes implement * Allows filtering so that notifications are only sent when classes
* or are of one of the types specified, the listener method will only * implement one of the types specified. The listener method will
* be called once regardless of how many types match <br/> * only be called once regardless of how many types match.
* Just return null or empty array to be notified for all service registrations * <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 * @return an array of classes OR null to be notified of all service registrations
*/ */
public Class<?>[] notifyForTypes(); public Class<?>[] notifyForTypes();
/** /**
* This will be called when services are newly registered with the service manager * This will be called when services are newly registered with the
* (will not be called when the core services are starting up though) <br/> * service manager. It will not be called when the core services
* It is not called until the service is fully initialized and * are starting up though.
* is called once and only once per service that is registered <br/> * <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 serviceName the name of the service
* @param service the service bean * @param service the service bean
@@ -44,11 +48,14 @@ public interface ServiceChangeListener {
public void serviceRegistered(String serviceName, Object service, List<Class<?>> implementedTypes); public void serviceRegistered(String serviceName, Object service, List<Class<?>> implementedTypes);
/** /**
* This will be called when services are removed from the service manager, * This will be called when services are removed from the service
* services which are replaced will not have this method called and will only call * manager.
* {@link #serviceRegistered(String, Object, List)} <br/> * 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 * 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 serviceName the name of the service
* @param service the service bean * @param service the service bean

View File

@@ -13,19 +13,23 @@ package org.dspace.kernel.mixins;
import org.dspace.kernel.ServiceManager; import org.dspace.kernel.ServiceManager;
/** /**
* This service manager mixin will cause a service to be notified when the servicemanager has started * 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 * up all known services (including activators). This is useful if a
* of all known services or providers of a certain type when the system startup is complete, * service wants to do lookups of all known services or providers of a
* it can also be used as a way to execute some code when the service manager startup is complete * 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) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface ServiceManagerReadyAware { public interface ServiceManagerReadyAware {
/** /**
* This is called when the startup of all core services and activators is complete <br/> * This is called when the startup of all core services and
* WARNING: This will never be called for providers which are registered with a servicemanager * activators is complete.
* which is already running! * <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 * @param serviceManager the completely started service manager
*/ */

View File

@@ -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, * Allow the service to be notified when the service manager is shutting
* this will typically be called when the kernel is stopped or destroyed, * it down. This will typically be called when the kernel is stopped or
* any cleanup that a service needs to do when it is shutdown should happen here * destroyed. Any cleanup that a service needs to do when it is
* shut down should happen here.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface ShutdownService { 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(); public void shutdown();

View File

@@ -0,0 +1,6 @@
/**
* Interfaces for interacting with the startup, shutdown, or
* reconfiguration of the framework.
*/
package org.dspace.kernel.mixins;

View File

@@ -0,0 +1,5 @@
/**
* The DSpace Services kernel and service manager.
*/
package org.dspace.kernel;

View File

@@ -17,37 +17,45 @@ import org.dspace.services.model.CacheConfig;
/** /**
* This is a provider (pluggable functionality) for DSpace<br/> * This is a provider (pluggable functionality) for DSpace.
* This allows an external system to define how caches are handled in DSpace by implementing this interface * <p>
* and registering it with the service manager<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.
* </p>
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
public interface CacheProvider { 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 * @return a list of all the caches which the caching service knows about
*/ */
public List<Cache> getCaches(); public List<Cache> getCaches();
/** /**
* Construct a {@link Cache} with the given name (must be unique) OR retrieve the one * Construct a {@link Cache} with the given name (must be unique) OR
* that already exists with this name <br/> * retrieve the one that already exists with this name.
* NOTE: providers will never be asked to provide request caches (e.g. {@link CacheConfig.CacheScope#REQUEST}) * <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 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, * @param config (optional) a configuration object. The cache
* if it is null then just use defaults * 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 * @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 * @throws IllegalArgumentException if the cache name is already in use or the config is invalid
*/ */
public Cache getCache(String cacheName, CacheConfig config); public Cache getCache(String cacheName, CacheConfig config);
/** /**
* Flush and destroy the cache with this name, * 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) * 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) * @param cacheName the unique name for this cache (e.g. org.dspace.user.UserCache)
*/ */
public void destroyCache(String cacheName); public void destroyCache(String cacheName);

View File

@@ -0,0 +1,5 @@
/**
* Pluggable alternatives for some core functions
*/
package org.dspace.providers;

View File

@@ -40,13 +40,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* This is the kernel implementation which starts up the core of DSpace and * This is the kernel implementation which starts up the core of DSpace,
* registers the mbean and initializes the {@link DSpace} object, * registers the mbean, and initializes the {@link DSpace} object.
* it also loads up the configuration <br/> * It also loads up the configuration. Sets a JRE shutdown hook.
* Note that this does not start itself and calling the constuctor does not actually * <p>
* start it up either. It has to be explicitly started by calling the start method * Note that this does not start itself and calling the constuctor does
* so something in the system needs to do that. If the bean is already started then calling start on * not actually start it up either. It has to be explicitly started by
* it again has no effect. <br/> * 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. * The name of this instance can be specified if desired.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
@@ -54,9 +57,11 @@ import org.slf4j.LoggerFactory;
public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifecycle<DSpaceKernel> { public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifecycle<DSpaceKernel> {
private static Logger log = LoggerFactory.getLogger(DSpaceKernelImpl.class); private static Logger log = LoggerFactory.getLogger(DSpaceKernelImpl.class);
/** /**
* Creates a DSpace Kernel, does not do any checks though, * Creates a DSpace Kernel, does not do any checks though.
* do not call this, use {@link DSpaceKernelInit#getKernel(String)} * Do not call this; use {@link DSpaceKernelInit#getKernel(String)}.
*
* @param name the name for the kernel * @param name the name for the kernel
*/ */
protected DSpaceKernelImpl(String name) { protected DSpaceKernelImpl(String name) {
@@ -70,6 +75,7 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
private DSpaceKernel kernel = null; private DSpaceKernel kernel = null;
private Thread shutdownHook; private Thread shutdownHook;
protected void registerShutdownHook() { protected void registerShutdownHook() {
if (this.shutdownHook == null) { if (this.shutdownHook == null) {
synchronized (lock) { synchronized (lock) {
@@ -126,8 +132,13 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
start(null); 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) { public void start(String dspaceHome) {
// this starts up the entire core system
if (running) { if (running) {
//log.warn("Kernel ("+this+") is already started"); //log.warn("Kernel ("+this+") is already started");
return; 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() { protected void doDestroy() {
if (! this.destroyed) { if (! this.destroyed) {
@@ -247,10 +258,13 @@ public class DSpaceKernelImpl implements DSpaceKernel, DynamicMBean, CommonLifec
// MBEAN methods // MBEAN methods
private Date lastLoadDate; private Date lastLoadDate;
/** Time that this kernel was started, as a java.util.Date. */
public Date getLastLoadDate() { public Date getLastLoadDate() {
return new Date(lastLoadDate.getTime()); return new Date(lastLoadDate.getTime());
} }
private long loadTime; private long loadTime;
/** Time that this kernel was started, as seconds since the epoch. */
public long getLoadTime() { public long getLoadTime() {
return loadTime; return loadTime;
} }

View File

@@ -15,8 +15,8 @@ import org.dspace.servicemanager.config.DSpaceConfig;
/** /**
* This holds the settings for a service config triple, * This holds the settings for a service config triple.
* can create this from a {@link DSpaceConfig} object * Create this from a {@link DSpaceConfig} object, or by name and value.
* *
* @author Aaron Zeckoski (azeckoski @ gmail.com) * @author Aaron Zeckoski (azeckoski @ gmail.com)
*/ */
@@ -26,6 +26,7 @@ public class ServiceConfig {
private String serviceName; private String serviceName;
private Object value; private Object value;
/** Construct from scratch. */
public ServiceConfig(String paramName, String serviceName, Object value) { public ServiceConfig(String paramName, String serviceName, Object value) {
if (paramName == null || serviceName == null) { if (paramName == null || serviceName == null) {
throw new IllegalArgumentException("paramName and serviceName must not be null"); throw new IllegalArgumentException("paramName and serviceName must not be null");
@@ -35,6 +36,7 @@ public class ServiceConfig {
this.value = value; this.value = value;
} }
/** Construct from an existing DSpaceConfig. */
public ServiceConfig(DSpaceConfig dspaceConfig) { public ServiceConfig(DSpaceConfig dspaceConfig) {
this.paramName = dspaceConfig.getBeanProperty(); this.paramName = dspaceConfig.getBeanProperty();
this.serviceName = dspaceConfig.getBeanName(); this.serviceName = dspaceConfig.getBeanName();

View File

@@ -29,8 +29,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* Borrowed from EntityBus since this already will handle the mixins for something correctly and easily, * Maintain a map of services and their mixin interfaces.
* no need to reinvent this *
* 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) * @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 * 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, * from the bikey made from the serviceName AND the implemented
* in other words, a service which implements 3 interfaces should have 4 entries in the map * 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); 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 * @param serviceName the well known and unique service name
* @return the service OR null if none can be found * @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 <T>
* @param serviceName the well known and unique service name * @param serviceName the well known and unique service name
* @param mixin the class type of the implemented mixin interface * @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 * @return the list of all known service names
*/ */
public List<String> getRegisteredServiceNames() { public List<String> getRegisteredServiceNames() {
@@ -97,6 +103,7 @@ public class ServiceMixinManager {
} }
/** /**
* List known services by FIXME.
* @return all known registered services * @return all known registered services
*/ */
public List<Object> getRegisteredServices() { 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 * @param serviceName the well known and unique service name
* @return the list of all known mixins for this service * @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! * 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 * @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 <T>
* @param mixin an interface which is a service mixin (technically any class) * @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 * @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 <T>
* @param mixin an interface which is a service mixin (technically any class) * @param mixin an interface which is a service mixin (technically any class)
* @return the list of all registered services which implement this mixin interface * @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, * Registers a service with the system and extracts all mixins.
* this will manage and track the mixins and the service * This will manage and track the mixins and the service.
* *
* @param serviceName the well known and unique service name * @param serviceName the well known and unique service name
* @param service the service itself * @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 * @param serviceName the well known and unique service name
* @return the list of mixin classes registered for this service * @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 serviceName the well known and unique service name
* @param mixin an interface which is a service mixin (technically any class) * @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 serviceName the well known and unique service name
* @param mixin * @param mixin a service mixin interface
* @param service * @param entityProvider
* @return true if the service is newly registered, false if it was already registered * @return true if the service is newly registered, false if it was already registered
*/ */
public boolean registerPrefixCapability(String serviceName, 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 * @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 * @return the number of currently registered services
*/ */
public int size() { public int size() {
@@ -378,7 +389,7 @@ public class ServiceMixinManager {
// STATICS - OTHER // 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) * @param className the classname (fully qualified)
* @return the class object * @return the class object
* @throws RuntimeException if the class is not found * @throws RuntimeException if the class is not found
@@ -400,9 +411,10 @@ public class ServiceMixinManager {
} }
/** /**
* Get the mixins implemented by this service, * Get the mixins implemented by this service.
* only gets interfaces and will not pick up superclasses <br/> * Only gets interfaces and will not pick up superclasses.
* WARNING: this is not the fastest ever * <p>
* WARNING: this is not the fastest ever.
* *
* @param service any object * @param service any object
* @return the list of services this class implements * @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 static class ClassComparator implements Comparator<Class<?>>, Serializable {
public final static long serialVersionUID = 1l; 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 static class ServiceComparator implements Comparator<Object>, Serializable {
public final static long serialVersionUID = 1l; 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 static class ServiceHolder<T> {
public String serviceName; public String serviceName;
public T service; public T service;
/** /**
* @return the service object cast to the type requested (probably not the type of the actual object) * @return the service object cast to the type requested (probably not the type of the actual object)
*/ */
public T getService() { public T getService() {
return service; return service;
} }
/** /**
* @return the name the service is registered under * @return the name the service is registered under
*/ */
@@ -473,6 +487,7 @@ public class ServiceMixinManager {
this.serviceName = serviceName; this.serviceName = serviceName;
this.service = service; this.service = service;
} }
@Override @Override
public String toString() { public String toString() {
return serviceName+":"+service.getClass().getName()+":"+super.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 static class ServiceHolderComparator implements Comparator<ServiceHolder<?>>, Serializable {
public final static long serialVersionUID = 1l; public final static long serialVersionUID = 1l;