Trusted User Rolle und Workflow (#1209)

* eingebaut
* Allen Rollen wird beim Erstellen automatisch der Site-wide Admin hinzugefügt
* Vorbereitungen für eine einfacher Erstellung von ContentSections getroffen

git-svn-id: https://svn.libreccm.org/ccm/trunk@1594 8810af33-2d31-482b-a856-94f89814c4df
master
quasi 2012-04-15 08:33:42 +00:00
parent 1f88a7bd25
commit 27796f0c86
6 changed files with 803 additions and 850 deletions

View File

@ -18,13 +18,14 @@
*/ */
package com.arsdigita.cms; package com.arsdigita.cms;
import com.arsdigita.cms.contentsection.ContentSectionConfig;
import com.arsdigita.cms.contentsection.ContentSectionSetup; import com.arsdigita.cms.contentsection.ContentSectionSetup;
import com.arsdigita.cms.util.Util;
import com.arsdigita.cms.contenttypes.XMLContentTypeHandler; import com.arsdigita.cms.contenttypes.XMLContentTypeHandler;
import com.arsdigita.cms.portlet.ContentDirectoryPortlet; import com.arsdigita.cms.portlet.ContentDirectoryPortlet;
import com.arsdigita.cms.portlet.ContentItemPortlet; import com.arsdigita.cms.portlet.ContentItemPortlet;
import com.arsdigita.cms.portlet.ContentSectionsPortlet; import com.arsdigita.cms.portlet.ContentSectionsPortlet;
import com.arsdigita.cms.portlet.TaskPortlet; import com.arsdigita.cms.portlet.TaskPortlet;
import com.arsdigita.cms.util.Util;
import com.arsdigita.formbuilder.util.FormbuilderSetup; import com.arsdigita.formbuilder.util.FormbuilderSetup;
import com.arsdigita.kernel.Kernel; import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion; import com.arsdigita.kernel.KernelExcursion;
@ -38,35 +39,31 @@ import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.web.Application; import com.arsdigita.web.Application;
import com.arsdigita.web.ApplicationType; import com.arsdigita.web.ApplicationType;
import com.arsdigita.xml.XML; import com.arsdigita.xml.XML;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* <p>Executes nonrecurring at install time and loads (installs and initializes) * <p>Executes nonrecurring at install time and loads (installs and initializes)
* the Content Management System module,including the Content Center, CMS Service * the Content Management System module,including the Content Center, CMS
* applications, and CMS Mime Types service persistently into database.</p> * Service applications, and CMS Mime Types service persistently into
* database.</p>
* *
* <p>This class also optionally initializes user-defined content types. </p> * <p>This class also optionally initializes user-defined content types. </p>
* <p>Additional user-defined content sections can be loaded and initilized * <p>Additional user-defined content sections can be loaded and initilized
* using the recurring <pre>initializer</pre> at any startup. * using the recurring
* <pre>initializer</pre> at any startup.
* *
* <p>The tasks to perform are:</p> * <p>The tasks to perform are:</p> <ol> <li>create CMS package
* <ol> * type(content-section)</li> <li>create Workspace package type and
* <li>create CMS package type(content-section)</li> * instance</li> <li>create CMS Service package type and instance</li>
* <li>create Workspace package type and instance</li> * <li>create CMS package (content-section) instance</li> </ol>
* <li>create CMS Service package type and instance</li>
* <li>create CMS package (content-section) instance</li>
* </ol>
* *
* <p>Configuration can be modified by configuration parameters before processing, * <p>Configuration can be modified by configuration parameters before
* otherwise hardcoded default values take effect. After processing, the * processing, otherwise hardcoded default values take effect. After processing,
* installation values can not be modified anymore without a fresh installation * the installation values can not be modified anymore without a fresh
* of the whole system.</p> * installation of the whole system.</p>
* *
* @author Peter Boy &lt;pboy@barkhof.uni-bremen.de&gt; * @author Peter Boy &lt;pboy@barkhof.uni-bremen.de&gt;
* @since ccm-cms version 6.6.0 * @since ccm-cms version 6.6.0
@ -74,39 +71,38 @@ import org.apache.log4j.Logger;
*/ */
public class Loader extends PackageLoader { public class Loader extends PackageLoader {
/** Creates a s_logging category with name = full name of class */ /**
* Creates a s_logging category with name = full name of class
*/
private static final Logger s_log = Logger.getLogger(Loader.class); private static final Logger s_log = Logger.getLogger(Loader.class);
/**
/** Loader configuration object, singleton design pattern * Loader configuration object, singleton design pattern NOTE: LoaderConfig
* NOTE: LoaderConfig only supplies unmutable hard coded defaults! It is * only supplies unmutable hard coded defaults! It is not possible to alter
* not possible to alter any of the contained values by specifiying an * any of the contained values by specifiying an configuration parameter
* configuration parameter during load step. If a configuration value * during load step. If a configuration value has to be configurable at load
* has to be configurable at load time, the parameter must be relocated * time, the parameter must be relocated into this Loader class!
* into this Loader class! */ */
private static final LoaderConfig s_conf = LoaderConfig.getInstance(); private static final LoaderConfig s_conf = LoaderConfig.getInstance();
// /////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////
// Configurable parameters during load step. // Configurable parameters during load step.
// /////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////
/** /**
* The name(s) of the content section(s). In case of more than one name the * The name(s) of the content section(s). In case of more than one name the
* first is treated as default section. Otherwise the section created is the * first is treated as default section. Otherwise the section created is the
* default section. More sections can always be created during a subsequent * default section. More sections can always be created during a subsequent
* system startup using initialization parameters. * system startup using initialization parameters.
*/ */
private final Parameter m_contentSectionNames = new StringArrayParameter( private final Parameter m_contentSectionNames = new StringArrayParameter(
"com.arsdigita.cms.loader.section_names", "com.arsdigita.cms.loader.section_names",
Parameter.REQUIRED, Parameter.REQUIRED,
new String[] {"content"} new String[]{"content"});
); /**
* List of classnames of internal base content types (needed in every
/** List of classnames of internal base content types (needed in every * section created), generated while loading those content types in
* section created), generated while loading those content types in * loadContentTypeDefinitions(files) for later use in register step.
* loadContentTypeDefinitions(files) for later use in register step. */ */
private ArrayList m_content_type_list = new ArrayList(); private ArrayList m_content_type_list = new ArrayList();
/** /**
* Standard constructor. * Standard constructor.
*/ */
@ -114,12 +110,12 @@ public class Loader extends PackageLoader {
s_log.debug("CMS.loader (Constructor) invoked"); s_log.debug("CMS.loader (Constructor) invoked");
register(m_contentSectionNames); register(m_contentSectionNames);
s_log.debug("CMS.loader (Constructor) completed"); s_log.debug("CMS.loader (Constructor) completed");
} }
/** /**
* *
*/ */
public void run(final ScriptContext ctx) { public void run(final ScriptContext ctx) {
s_log.debug("CMS.loader.run() invoked"); s_log.debug("CMS.loader.run() invoked");
@ -142,7 +138,7 @@ public class Loader extends PackageLoader {
// Step 4) Load CMS content section // Step 4) Load CMS content section
// Loads content section application type and instance in one step // Loads content section application type and instance in one step
loadContentSection( (String[]) get(m_contentSectionNames) ); loadContentSection((String[]) get(m_contentSectionNames));
// Step 5) Loading CMS portlets // Step 5) Loading CMS portlets
s_log.debug("CMS.loader going to load portlets"); s_log.debug("CMS.loader going to load portlets");
@ -154,8 +150,8 @@ public class Loader extends PackageLoader {
// Loading forms widget into database // Loading forms widget into database
FormbuilderSetup fbs = new FormbuilderSetup(); FormbuilderSetup fbs = new FormbuilderSetup();
fbs.setup(s_conf.getWidgetTypes(), fbs.setup(s_conf.getWidgetTypes(),
s_conf.getProcessListenerTypes(), s_conf.getProcessListenerTypes(),
s_conf.getDataQueries()); s_conf.getDataQueries());
} }
@ -165,23 +161,23 @@ public class Loader extends PackageLoader {
/** /**
* Loads the Workspace subpackage (content-center) into the database. * Loads the Workspace subpackage (content-center) into the database.
* *
* It is made public to be able to invoke it from the update script * It is made public to be able to invoke it from the update script (e.g.
* (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating * 6.6.1-6.6.2). We need separate steps for loading and instantiating
* because update skript requires. * because update skript requires.
*/ */
public static ApplicationType loadWorkspaceApplicationType() { public static ApplicationType loadWorkspaceApplicationType() {
s_log.debug("Creating CMS Workspace..."); s_log.debug("Creating CMS Workspace...");
/* Create new type legacy free application type /*
* NOTE: The wording in the title parameter of ApplicationType * Create new type legacy free application type NOTE: The wording in the
* determines the name of the subdirectory for the XSL stylesheets. * title parameter of ApplicationType determines the name of the
* It gets "urlized", i.e. trimming leading and trailing blanks and * subdirectory for the XSL stylesheets. It gets "urlized", i.e.
* replacing blanks between words and illegal characters with an * trimming leading and trailing blanks and replacing blanks between
* hyphen and converted to lower case. * words and illegal characters with an hyphen and converted to lower
* "Content Center" will become "content-center". */ * case. "Content Center" will become "content-center".
ApplicationType type = new */
ApplicationType(Workspace.INSTANCE_NAME, ApplicationType type = new ApplicationType(Workspace.INSTANCE_NAME,
Workspace.BASE_DATA_OBJECT_TYPE ); Workspace.BASE_DATA_OBJECT_TYPE);
type.setDescription("The content center workspace for content creators."); type.setDescription("The content center workspace for content creators.");
type.save(); type.save();
@ -193,14 +189,14 @@ public class Loader extends PackageLoader {
/** /**
* Instantiates the Workspace subpackage (content-center) (in the database). * Instantiates the Workspace subpackage (content-center) (in the database).
* *
* It is made public to be able to invoke it from the update script * It is made public to be able to invoke it from the update script (e.g.
* (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating * 6.6.1-6.6.2). We need separate steps for loading and instantiating
* because update skript requires. * because update skript requires.
* *
* @param workspaceType * @param workspaceType
*/ */
public static void setupDefaultWorkspaceApplicationInstance( public static void setupDefaultWorkspaceApplicationInstance(
ApplicationType workspaceType) { ApplicationType workspaceType) {
// create application instance // create application instance
// Whether a legacy compatible or a legacy free application is // Whether a legacy compatible or a legacy free application is
@ -209,10 +205,10 @@ public class Loader extends PackageLoader {
// old-style package key used as url fragment where to install the instance // old-style package key used as url fragment where to install the instance
s_log.debug("Creating CMS Workspace instance ..."); s_log.debug("Creating CMS Workspace instance ...");
Workspace app = (Workspace) Application.createApplication( Workspace app = (Workspace) Application.createApplication(
Workspace.BASE_DATA_OBJECT_TYPE, // type Workspace.BASE_DATA_OBJECT_TYPE, // type
Workspace.PACKAGE_KEY, // url fragment Workspace.PACKAGE_KEY, // url fragment
Workspace.INSTANCE_NAME, // title Workspace.INSTANCE_NAME, // title
null); // parent null); // parent
app.setDescription("The default CMS workspace instance."); app.setDescription("The default CMS workspace instance.");
app.save(); app.save();
@ -220,44 +216,42 @@ public class Loader extends PackageLoader {
s_log.debug("Done loading CMS Workspace."); s_log.debug("Done loading CMS Workspace.");
} }
/** /**
* CMS Service application is used by the Content Management System as a * CMS Service application is used by the Content Management System as a
* store for global resources and assets. * store for global resources and assets. It is made public to be able to
* It is made public to be able to invoke it from the update script * invoke it from the update script (e.g. 6.6.1-6.6.2).
* (e.g. 6.6.1-6.6.2).
*/ */
public static ApplicationType loadServiceApplicationType() { public static ApplicationType loadServiceApplicationType() {
s_log.debug("Loading CMS Servce Package..."); s_log.debug("Loading CMS Servce Package...");
/* Create new type legacy free application type /*
* NOTE: The wording in the title parameter of ApplicationType * Create new type legacy free application type NOTE: The wording in the
* determines the name of the subdirectory for the XSL stylesheets. * title parameter of ApplicationType determines the name of the
* It gets "urlized", i.e. trimming leading and trailing blanks and * subdirectory for the XSL stylesheets. It gets "urlized", i.e.
* replacing blanks between words and illegal characters with an * trimming leading and trailing blanks and replacing blanks between
* hyphen and converted to lower case. * words and illegal characters with an hyphen and converted to lower
* "CMS Service" will become "cms-service". */ * case. "CMS Service" will become "cms-service".
ApplicationType type = new ApplicationType("CMS Service", */
Service.BASE_DATA_OBJECT_TYPE ); ApplicationType type = new ApplicationType("CMS Service",
Service.BASE_DATA_OBJECT_TYPE);
type.setDescription("Services to store global resources and assets."); type.setDescription("Services to store global resources and assets.");
type.save(); type.save();
return type; return type;
} }
/** /**
* *
* @param serviceType * @param serviceType
*/ */
public static void setupDefaultServiceApplicationInstance( public static void setupDefaultServiceApplicationInstance(
ApplicationType serviceType) { ApplicationType serviceType) {
// create legacy compatible application instance, // create legacy compatible application instance,
// old-style package key used as url fragment where to install the instance // old-style package key used as url fragment where to install the instance
Service app = (Service) Application.createApplication( Service app = (Service) Application.createApplication(
serviceType, // type serviceType, // type
Service.PRIMARY_URL_STUB, // url fragment Service.PRIMARY_URL_STUB, // url fragment
"CMS Service Instance", // title "CMS Service Instance", // title
null); // parent null); // parent
app.setDescription("The default CMS service instance."); app.setDescription("The default CMS service instance.");
app.save(); app.save();
@ -265,40 +259,39 @@ public class Loader extends PackageLoader {
s_log.debug("Done creating CMS Service Package."); s_log.debug("Done creating CMS Service Package.");
} }
/** /**
* Load a content section application type and an initial default * Load a content section application type and an initial default
* content-section instance(s). * content-section instance(s). Some configuration values which are to be
* Some configuration values which are to be considered as unmutable are * considered as unmutable are specified in LoaderConfig. Uses new style
* specified in LoaderConfig. * application in legacy compatible mode.
* Uses new style application in legacy compatible mode.
* *
* NOTE: At ccm-cms load time no content type packages are available because * NOTE: At ccm-cms load time no content type packages are available because
* any content type depends on ccm-cms. Therefore, the loading step can not * any content type depends on ccm-cms. Therefore, the loading step can not
* process content type package assignment! Instead each content type itself * process content type package assignment! Instead each content type itself
* must assign itself to an appropriate content section at it's load time. * must assign itself to an appropriate content section at it's load time.
* Cf. {@link com.arsdigita.cms.contenttype.AbstractContentTypeLoader}. * Cf. {@link com.arsdigita.cms.contenttype.AbstractContentTypeLoader}.
* *
* But the load step has to process the cms internal content types! * But the load step has to process the cms internal content types!
*/ */
private void loadContentSection(String[] sectionNames) { private void loadContentSection(String[] sectionNames) {
// Step 1: Create content section application type // Step 1: Create content section application type
// prerequisite for concrete content-section instance creation. // prerequisite for concrete content-section instance creation.
/* Create legacy-free application type /*
* NOTE: The wording in the title parameter of ApplicationType * Create legacy-free application type NOTE: The wording in the title
* determines the name of the subdirectory for the XSL stylesheets. * parameter of ApplicationType determines the name of the subdirectory
* It gets "urlized", i.e. trimming leading and trailing blanks and * for the XSL stylesheets. It gets "urlized", i.e. trimming leading and
* replacing blanks between words and illegal characters with an * trailing blanks and replacing blanks between words and illegal
* hyphen and converted to lower case. * characters with an hyphen and converted to lower case. "Content
* "Content Section" will become "content-section". */ * Section" will become "content-section".
ApplicationType type = new ApplicationType( */
"Content Section", ApplicationType type = new ApplicationType(
ContentSection.BASE_DATA_OBJECT_TYPE ); "Content Section",
ContentSection.BASE_DATA_OBJECT_TYPE);
type.setDescription("The CMS Content Section application."); type.setDescription("The CMS Content Section application.");
type.save(); type.save();
// Step 2: Load CMS specific privileges into central (core) privilege // Step 2: Load CMS specific privileges into central (core) privilege
// system. // system.
createPrivileges(); createPrivileges();
@ -306,73 +299,27 @@ public class Loader extends PackageLoader {
// Step 3: Create the installation default content section(s). // Step 3: Create the installation default content section(s).
// ContentSection.create creates a section with several default values // ContentSection.create creates a section with several default values
// which have to be adopted for a concrete installation. // which have to be adopted for a concrete installation.
for (int i = 0 ; i < sectionNames.length ; i++) { for (int i = 0; i < sectionNames.length; i++) {
final String sectionName = sectionNames[i]; final String sectionName = sectionNames[i];
s_log.debug("Creating content section on /" + sectionName); s_log.debug("Creating content section on /" + sectionName);
// Step 1: Validate name for section // Step 1: Validate name for section
Util.validateURLParameter("name", sectionName); Util.validateURLParameter("name", sectionName);
ContentSectionConfig conf = new ContentSectionConfig();
conf.load();
// Step 2: Create a section using default values ContentSectionSetup.setupContentSectionAppInstance(sectionName,
ContentSection section = ContentSection.create(sectionName); conf.getDefaultRoles(),
conf.getDefaultWorkflows(),
// Step 3: Adopt the created section to site specific requirements s_conf.isPubliclyViewable(),
// ContentSectionSetup is a convenient class to adopt a s_conf.getItemResolverClass(),
// section created by ContentSection.create() s_conf.getTemplateResolverClass(),
ContentSectionSetup setup = new ContentSectionSetup(section); m_content_type_list,
s_conf.getUseSectionCategories(),
// Step 3a: Roles (staff group) used in this content section. s_conf.getCategoryFileList());
// Register roles using a complete set of default roles
// defined in ContentSectionSetup
setup.registerRoles(s_conf.getStuffGroup());
// ViewerGroup populated in ContentSection, public access is determined
// by parameter (affecting characteristics of the viewer group)
setup.registerViewers(s_conf.isPubliclyViewable());
// Page resolver class, set autonomously by ContentSection.create()
// Item resolver class, configurable, defaults in place.
// Template resolver class, configurable, defaults in place.
// We should not overwrite the default in the initial default configuration
// register a predefined one-phase lifecycle for items.
setup.registerPublicationCycles();
// registers predefined "Authoring", "Approval", "Publishing' steps
setup.registerWorkflowTemplates();
setup.registerResolvers(s_conf.getItemResolverClass(),
s_conf.getTemplateResolverClass());
// XML generator class, set autonomously by ContentSection.create()
/* Register internal base content types. Paramter is a list of
* class names created by internal content type load method.
* @see loadContentTypeDefinitions(List)
* External content types (provided by additional packages) are
* not available at CMS load time and can not processed by Loader.
* Registration of those content types are dealt with in the
* respective Loader or in the CMS workspace GUI.
* For each created section the base types get registered. */
setup.registerContentTypes(m_content_type_list);
// Section specific categories, usually not used.
// During initial load at install time nor used at all!
// default value is false so no categories get loaded.
if (s_conf.getUseSectionCategories()) {
Iterator files = ((List) s_conf.getCategoryFileList()).iterator();
while (files.hasNext()) {
setup.registerCategories((String) files.next());
}
}
// registers a predefined standard recipient for alerts
setup.registerAlerts();
// Load a list of cms tasks and associated alert events
// Currently no functionality to persist them. Not a loader task yet
// setup.loadTaskAlerts(s_conf.getTaskAlerts());
section.save(); //persists any changes in the database (DomainObject)
//i.e. creates an object (instance)
} }
} }
@ -381,13 +328,13 @@ public class Loader extends PackageLoader {
* Parses XML file definition of (internal) base content types and loads * Parses XML file definition of (internal) base content types and loads
* them into database. It fulfills a task similiar to the Loader of external * them into database. It fulfills a task similiar to the Loader of external
* content type packages. * content type packages.
* *
* The XML config looks like the example below, the "parentType" and "name" * The XML config looks like the example below, the "parentType" and "name"
* attributes are optional, and only required for creating * attributes are optional, and only required for creating User Defined
* User Defined ContentTypes. Label corresponds to ContentType's label and * ContentTypes. Label corresponds to ContentType's label and can be
* can be multiple words, and "name" to DynamicObject's name property, * multiple words, and "name" to DynamicObject's name property, and must be
* and must be a single word. The objectType attribute is ignored for * a single word. The objectType attribute is ignored for UDCTs, as it gets
* UDCTs, as it gets dynamically generated. * dynamically generated.
* *
* <b>UDCT Copyright</b> * <b>UDCT Copyright</b>
* <pre> * <pre>
@ -404,7 +351,7 @@ public class Loader extends PackageLoader {
* &lt;/ccm:authoring-kit&gt; * &lt;/ccm:authoring-kit&gt;
* &lt;/ccm:content-type&gt; * &lt;/ccm:content-type&gt;
* &lt;/ccm:content-types&gt; * &lt;/ccm:content-types&gt;
*</pre> * </pre>
* *
* @see XMLContentTypeHandler * @see XMLContentTypeHandler
*/ */

View File

@ -15,8 +15,6 @@
* with this library; if not, write to the Free Software Foundation, Inc., * with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
package com.arsdigita.cms; package com.arsdigita.cms;
import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.runtime.AbstractConfig;
@ -24,11 +22,8 @@ import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.Parameter; import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.StringArrayParameter; import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter; import com.arsdigita.util.parameter.StringParameter;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
// IMPLEMENTATION NOTE // IMPLEMENTATION NOTE
@ -36,45 +31,47 @@ import org.apache.log4j.Logger;
// initialization process and not yet completed. Functionality is // initialization process and not yet completed. Functionality is
// basically OK so far, but code urgently needs cleaning up and a // basically OK so far, but code urgently needs cleaning up and a
// check for useful bits. // check for useful bits.
/** /**
* Container for various configuration parameters for ccm-cms package loader. * Container for various configuration parameters for ccm-cms package loader.
* *
* The parameters are basically immutable for users and administrators and only * The parameters are basically immutable for users and administrators and only
* accessible to developers and require recompilation. Specifying any of these * accessible to developers and require recompilation. Specifying any of these
* parameters during installation takes no effect at all! Parameters which have * parameters during installation takes no effect at all! Parameters which have
* to be modifiable must be included in Loader class itself! * to be modifiable must be included in Loader class itself!
* *
* @author pb * @author pb
* @version $Id: LoaderConfig.java $ * @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
* @version $Id: LoaderConfig.java $
*/ */
public final class LoaderConfig extends AbstractConfig { public final class LoaderConfig extends AbstractConfig {
/** Local logger instance fpr debug support */ /**
* Local logger instance fpr debug support
*/
private static final Logger s_log = Logger.getLogger(LoaderConfig.class); private static final Logger s_log = Logger.getLogger(LoaderConfig.class);
/**
/** Private Object to hold one's own instance to return to users. */ * Private Object to hold one's own instance to return to users.
*/
private static LoaderConfig s_conf; private static LoaderConfig s_conf;
/** /**
* Returns the singleton configuration record for Loader configuration. * Returns the singleton configuration record for Loader configuration.
* *
* @return The <code>ContentSectionConfig</code> record; it cannot be null * @return The
* <code>ContentSectionConfig</code> record; it cannot be null
*/ */
public static synchronized LoaderConfig getInstance() { public static synchronized LoaderConfig getInstance() {
if (s_conf == null) { if (s_conf == null) {
s_conf = new LoaderConfig(); s_conf = new LoaderConfig();
/* Parameters are not stored in registry nor modified by installation /*
* specification. It is not possible to process a config object at * Parameters are not stored in registry nor modified by
* Load time! * installation specification. It is not possible to process a
* s_conf.load(); * config object at Load time! s_conf.load();
*/ */
} }
return s_conf; return s_conf;
} }
// /** // /**
// * The name of the workspace package instance, i.e. URL of the workspace, // * The name of the workspace package instance, i.e. URL of the workspace,
// * where authors, editors and publishers are working and from which they // * where authors, editors and publishers are working and from which they
@ -91,7 +88,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.workspace_url", // "com.arsdigita.cms.loader.workspace_url",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// "content-center"); // "content-center");
// /** // /**
// * XML Mapping of the content center tabs to URLs, see // * XML Mapping of the content center tabs to URLs, see
// * {@link ContentCenterDispatcher} // * {@link ContentCenterDispatcher}
@ -105,7 +101,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.content_center_map", // "com.arsdigita.cms.loader.content_center_map",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// "/WEB-INF/resources/content-center-map.xml"); // "/WEB-INF/resources/content-center-map.xml");
// Update master object if upgrading from old versioning // Update master object if upgrading from old versioning
// XXX: shouldn't we just gut this section (and // XXX: shouldn't we just gut this section (and
// VersioningUpgrader)? It is an upgrade fix from 5.1 or // VersioningUpgrader)? It is an upgrade fix from 5.1 or
@ -118,7 +113,6 @@ public final class LoaderConfig extends AbstractConfig {
// if (updateMaster) { // if (updateMaster) {
// VersioningUpgrader.updateMasterObject(); // VersioningUpgrader.updateMasterObject();
// } // }
// XXX: ItemDispatcher is no longer used. Is the following // XXX: ItemDispatcher is no longer used. Is the following
// still a valid enterprise.init parameter? Do we need to // still a valid enterprise.init parameter? Do we need to
// set ContentSectionServlet.s_cacheItems instead of the // set ContentSectionServlet.s_cacheItems instead of the
@ -128,39 +122,33 @@ public final class LoaderConfig extends AbstractConfig {
// ((Boolean)m_conf.getParameter(CACHE_ITEMS)).booleanValue(); // ((Boolean)m_conf.getParameter(CACHE_ITEMS)).booleanValue();
// s_log.debug("Set cache items to " + cacheItems); // s_log.debug("Set cache items to " + cacheItems);
// ItemDispatcher.setCacheItems(cacheItems); // ItemDispatcher.setCacheItems(cacheItems);
/** /**
* Comma separated list of XML definition files for internal content types * Comma separated list of XML definition files for internal content types
* (base types). * (base types).
* *
* Each internal content type (see package com/arsdigita/cms/contenttypes) * Each internal content type (see package com/arsdigita/cms/contenttypes)
* requires an entry in this list in order to get CMS Loader to load it * requires an entry in this list in order to get CMS Loader to load it into
* into permanent storage (equivalent to the Loader of each external * permanent storage (equivalent to the Loader of each external content type
* content type package). * package).
* *
* Each definition file name has to be fully qualified relative to * Each definition file name has to be fully qualified relative to
* application (context) root. * application (context) root. Example: contentTypeDefinitions = {
* Example: * "/WEB-INF/content-types/Template.xml" };
* contentTypeDefinitions = { "/WEB-INF/content-types/Template.xml" }; *
*
* This parameter should be altered only by developers! * This parameter should be altered only by developers!
*/ */
private final Parameter m_ctDefFiles = private final Parameter m_ctDefFiles =
new StringArrayParameter( new StringArrayParameter(
"com.arsdigita.cms.loader.internal_cts", "com.arsdigita.cms.loader.internal_cts",
Parameter.REQUIRED, Parameter.REQUIRED,
// Generic*.xml added by Quasi in enterprise.init for // Generic*.xml added by Quasi in enterprise.init for
// new generic Basetypes in addition to article // new generic Basetypes in addition to article
new String[] {"/WEB-INF/content-types/GenericAddress.xml", new String[]{"/WEB-INF/content-types/GenericAddress.xml",
"/WEB-INF/content-types/GenericArticle.xml", "/WEB-INF/content-types/GenericArticle.xml",
"/WEB-INF/content-types/GenericContact.xml", "/WEB-INF/content-types/GenericContact.xml",
"/WEB-INF/content-types/GenericOrganizationalUnit.xml", "/WEB-INF/content-types/GenericOrganizationalUnit.xml",
"/WEB-INF/content-types/GenericPerson.xml", "/WEB-INF/content-types/GenericPerson.xml",
"/WEB-INF/content-types/Template.xml"} "/WEB-INF/content-types/Template.xml"});
);
// /////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////
// //
// Parameters for creating a default content section at installation time. // Parameters for creating a default content section at installation time.
@ -168,50 +156,38 @@ public final class LoaderConfig extends AbstractConfig {
// We list all information here, the code needs to create a section. // We list all information here, the code needs to create a section.
// //
// /////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////
// Section Name, configured by Loader parameter // Section Name, configured by Loader parameter
// Root Folder, set autonomously by ContentSection.create() method // Root Folder, set autonomously by ContentSection.create() method
// Template Folder, set autonomously by ContentSection.create() method // Template Folder, set autonomously by ContentSection.create() method
/** /**
* Staff Group * Staff Group Contains roles and associated privileges. In loading step a
* Contains roles and associated privileges. In loading step a complete * complete default configuration is persisted in database, immutable at
* default configuration is persisted in database, immutable at this point. * this point. See contentsection.ContentSectionSetup.registerRoles() In
* See contentsection.ContentSectionSetup.registerRoles() * enterprise.init: name roles, List of roles to create.
* In enterprise.init: name roles, List of roles to create. *
*
* Not implemented yet! We need a new parameter type "list" which must have * Not implemented yet! We need a new parameter type "list" which must have
* multidimensional capabilities. * multidimensional capabilities.
*/ */
/* /*
private final Parameter * private final Parameter m_staffGroup = new StringParameter(
m_staffGroup = new StringParameter( * "com.arsdigita.cms.loader.section_staff_group", Parameter.REQUIRED,
"com.arsdigita.cms.loader.section_staff_group", * null);
Parameter.REQUIRED,
null);
*/ */
private List m_staffGroup; private List m_defaultRoles;
// Viewer group, set autonomously by ContentSection.create() method. We can // Viewer group, set autonomously by ContentSection.create() method. We can
// here specify, whether the first ( probalby only) content section should // here specify, whether the first ( probalby only) content section should
// have a public viewer, i.e. without registration and login. // have a public viewer, i.e. without registration and login.
/** /**
* Whether to make content viewable to 'The Public', ie non-registered users. * Whether to make content viewable to 'The Public', ie non-registered
* users.
* *
* Parameter name in the old initializer code: PUBLIC. Default true. * Parameter name in the old initializer code: PUBLIC. Default true.
*/ */
private final BooleanParameter private final BooleanParameter m_isPublic = new BooleanParameter(
m_isPublic = new BooleanParameter( "com.arsdigita.cms.loader.section_is_public",
"com.arsdigita.cms.loader.section_is_public", Parameter.REQUIRED,
Parameter.REQUIRED, true);
true);
// Page Resolver Class, set autonomously by ContentSection.create() method. // Page Resolver Class, set autonomously by ContentSection.create() method.
// Item Resolver Class, configurable. // Item Resolver Class, configurable.
/** /**
* Name of the item resolver class to use for the section (defaults to * Name of the item resolver class to use for the section (defaults to
@ -220,192 +196,174 @@ public final class LoaderConfig extends AbstractConfig {
* Default value (site-wide) is handled via the parameter * Default value (site-wide) is handled via the parameter
* <pre>com.arsdigita.cms.default_item_resolver_class</pre>. * <pre>com.arsdigita.cms.default_item_resolver_class</pre>.
* Section-specific override can be added here. Only do so if you are * Section-specific override can be added here. Only do so if you are
* changing from the default for a specific content section. The class * changing from the default for a specific content section. The class must
* must implement <pre>com.arsdigita.cms.dispatcher.ItemResolver</pre>. * implement
* <pre>com.arsdigita.cms.dispatcher.ItemResolver</pre>.
* *
* Parameter name ITEM_RESOLVER_CLASS in the old initializer system. * Parameter name ITEM_RESOLVER_CLASS in the old initializer system.
* Description: The ItemResolver class to use for the section * Description: The ItemResolver class to use for the section (defaults to
* (defaults to MultilingualItemResolver) * MultilingualItemResolver)
*/ */
private final Parameter private final Parameter m_itemResolverClass = new StringParameter(
m_itemResolverClass = new StringParameter( "com.arsdigita.cms.loader.item_resolver_class",
"com.arsdigita.cms.loader.item_resolver_class", Parameter.OPTIONAL, null);
Parameter.OPTIONAL, null ); // , "com.arsdigita.cms.dispatcher.MultilingualItemResolver"
// , "com.arsdigita.cms.dispatcher.MultilingualItemResolver"
// Template Resolver Class, configurable. // Template Resolver Class, configurable.
/** /**
* Name of the template resolver class to use for the section * Name of the template resolver class to use for the section (defaults to
* (defaults to <pre>com.arsdigita.cms.dispatcher.DefaultTemplateResolver</pre>) * <pre>com.arsdigita.cms.dispatcher.DefaultTemplateResolver</pre>)
* *
* Default value (site-wide) is handled via the parameter * Default value (site-wide) is handled via the parameter
* <pre>com.arsdigita.cms.default_template_resolver_class</pre>. * <pre>com.arsdigita.cms.default_template_resolver_class</pre>.
* Section-specific override can be added here. Only do so if you are * Section-specific override can be added here. Only do so if you are
* changing from the default for a specific content section. The class * changing from the default for a specific content section. The class must
* must implement <pre>com.arsdigita.cms.dispatcher.TemplateResolver</pre>. * implement
* <pre>com.arsdigita.cms.dispatcher.TemplateResolver</pre>.
* *
* Parameter name TEMPLATE_RESOLVER_CLASS in the old initializer system. * Parameter name TEMPLATE_RESOLVER_CLASS in the old initializer system.
*/ */
private final Parameter private final Parameter m_templateResolverClass = new StringParameter(
m_templateResolverClass = new StringParameter( "com.arsdigita.cms.loader.template_resolver_class",
"com.arsdigita.cms.loader.template_resolver_class", Parameter.OPTIONAL,
Parameter.OPTIONAL, null);
null ); // "com.arsdigita.cms.dispatcher.DefaultTemplateResolver" );
// "com.arsdigita.cms.dispatcher.DefaultTemplateResolver" );
// XML Generator Class, set autonomously by ContentSection.create() method. // XML Generator Class, set autonomously by ContentSection.create() method.
/** /**
* Determins weather to use section specific category tree(s). Defaults to * Determins weather to use section specific category tree(s). Defaults to
* false, so standard navigation is used. * false, so standard navigation is used. If set to true loader loads the
* If set to true loader loads the categories from file(s) specified in the * categories from file(s) specified in the next parameter (
* next parameter ( m_categoryFileList ) * m_categoryFileList )
*/ */
private final Parameter private final Parameter m_useSectionCategories = new BooleanParameter("com.arsdigita.cms.loader.use_section_categories",
m_useSectionCategories = new BooleanParameter Parameter.REQUIRED, new Boolean(false));
("com.arsdigita.cms.loader.use_section_categories",
Parameter.REQUIRED, new Boolean(false));
/** /**
* XML file containing the category tree to load for this content section. * XML file containing the category tree to load for this content section.
* Usually not loaded {@see m_useSectionCategories). The files listed as * Usually not loaded {
* default values are demo material and must be replaced in a production *
* environment. * @see m_useSectionCategories). The files listed as default values are demo
* material and must be replaced in a production environment.
*/ */
private final Parameter private final Parameter m_categoryFileList = new StringArrayParameter(
m_categoryFileList = new StringArrayParameter( "com.arsdigita.cms.loader.section_categories_toload",
"com.arsdigita.cms.loader.section_categories_toload", Parameter.REQUIRED,
Parameter.REQUIRED, new String[]{"/WEB-INF/resources/article-categories.xml",
new String[] {"/WEB-INF/resources/article-categories.xml", "/WEB-INF/resources/navigation-categories.xml"});
"/WEB-INF/resources/navigation-categories.xml"} );
// private final Parameter // private final Parameter
// m_widgetTypes = new StringArrayParameter( // m_widgetTypes = new StringArrayParameter(
// "com.arsdigita.cms.loader.widget_types", // "com.arsdigita.cms.loader.widget_types",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// new String[] {"/WEB-INF/resources/article-categories.xml", // new String[] {"/WEB-INF/resources/article-categories.xml",
// "/WEB-INF/resources/navigation-categories.xml"} ); // "/WEB-INF/resources/navigation-categories.xml"} );
/**
/** List of widgets used in applications forms. Each widget is described by * List of widgets used in applications forms. Each widget is described by
application indicator, widget name (singular & plural), model class name * application indicator, widget name (singular & plural), model class name
and model ui class name. These are really not user or administrator * and model ui class name. These are really not user or administrator
configurabel and therefore not implemented as ccm parameter. */ * configurabel and therefore not implemented as ccm parameter.
*/
private static List widgetTypes = Arrays.asList( private static List widgetTypes = Arrays.asList(
Arrays.asList("forms-cms", "Checkbox group", "Checkbox groups", Arrays.asList("forms-cms", "Checkbox group", "Checkbox groups",
"com.arsdigita.formbuilder.PersistentCheckboxGroup", "com.arsdigita.formbuilder.PersistentCheckboxGroup",
"com.arsdigita.formbuilder.ui.editors.CheckboxGroupEditor"), "com.arsdigita.formbuilder.ui.editors.CheckboxGroupEditor"),
Arrays.asList("forms-cms", "Date field", "Date fields", Arrays.asList("forms-cms", "Date field", "Date fields",
"com.arsdigita.formbuilder.PersistentDate", "com.arsdigita.formbuilder.PersistentDate",
"com.arsdigita.formbuilder.ui.editors.DateForm"), "com.arsdigita.formbuilder.ui.editors.DateForm"),
Arrays.asList("forms-cms", "Hidden field", "Hidden fields", Arrays.asList("forms-cms", "Hidden field", "Hidden fields",
"com.arsdigita.formbuilder.PersistentHidden", "com.arsdigita.formbuilder.PersistentHidden",
"com.arsdigita.formbuilder.ui.editors.HiddenForm"), "com.arsdigita.formbuilder.ui.editors.HiddenForm"),
Arrays.asList( "forms-cms", "Hidden ID Generator field", Arrays.asList("forms-cms", "Hidden ID Generator field",
"Hidden ID Generator fields", "Hidden ID Generator fields",
"com.arsdigita.formbuilder.HiddenIDGenerator", "com.arsdigita.formbuilder.HiddenIDGenerator",
"com.arsdigita.formbuilder.ui.editors.HiddenIDGeneratorForm"), "com.arsdigita.formbuilder.ui.editors.HiddenIDGeneratorForm"),
Arrays.asList("forms-cms", "Multiple select box", Arrays.asList("forms-cms", "Multiple select box",
"Multiple select boxes", "Multiple select boxes",
"com.arsdigita.formbuilder.PersistentMultipleSelect", "com.arsdigita.formbuilder.PersistentMultipleSelect",
"com.arsdigita.formbuilder.ui.editors.MultipleSelectEditor"), "com.arsdigita.formbuilder.ui.editors.MultipleSelectEditor"),
Arrays.asList("forms-cms", "Password field", "Password fields", Arrays.asList("forms-cms", "Password field", "Password fields",
"com.arsdigita.formbuilder.PersistentPassword", "com.arsdigita.formbuilder.PersistentPassword",
"com.arsdigita.formbuilder.ui.editors.PasswordForm"), "com.arsdigita.formbuilder.ui.editors.PasswordForm"),
Arrays.asList("forms-cms", "Radio group", "Radio groups", Arrays.asList("forms-cms", "Radio group", "Radio groups",
"com.arsdigita.formbuilder.PersistentRadioGroup", "com.arsdigita.formbuilder.PersistentRadioGroup",
"com.arsdigita.formbuilder.ui.editors.RadioGroupEditor"), "com.arsdigita.formbuilder.ui.editors.RadioGroupEditor"),
Arrays.asList("forms-cms", "Single select box", Arrays.asList("forms-cms", "Single select box",
"Single select boxes", "Single select boxes",
"com.arsdigita.formbuilder.PersistentSingleSelect", "com.arsdigita.formbuilder.PersistentSingleSelect",
"com.arsdigita.formbuilder.ui.editors.SingleSelectEditor"), "com.arsdigita.formbuilder.ui.editors.SingleSelectEditor"),
Arrays.asList("forms-cms", "Submit button", "Submit buttons", Arrays.asList("forms-cms", "Submit button", "Submit buttons",
"com.arsdigita.formbuilder.PersistentSubmit", "com.arsdigita.formbuilder.PersistentSubmit",
"com.arsdigita.formbuilder.ui.editors.SubmitForm"), "com.arsdigita.formbuilder.ui.editors.SubmitForm"),
Arrays.asList("forms-cms", "Text area", "Text areas", Arrays.asList("forms-cms", "Text area", "Text areas",
"com.arsdigita.formbuilder.PersistentTextArea", "com.arsdigita.formbuilder.PersistentTextArea",
"com.arsdigita.formbuilder.ui.editors.TextAreaForm"), "com.arsdigita.formbuilder.ui.editors.TextAreaForm"),
Arrays.asList("forms-cms", "Text field", "Text fields", Arrays.asList("forms-cms", "Text field", "Text fields",
"com.arsdigita.formbuilder.PersistentTextField", "com.arsdigita.formbuilder.PersistentTextField",
"com.arsdigita.formbuilder.ui.editors.TextFieldForm"), "com.arsdigita.formbuilder.ui.editors.TextFieldForm"),
Arrays.asList("forms-cms", "Data Driven Select Box", Arrays.asList("forms-cms", "Data Driven Select Box",
"Data Driven Select Boxes", "Data Driven Select Boxes",
"com.arsdigita.formbuilder.DataDrivenSelect", "com.arsdigita.formbuilder.DataDrivenSelect",
"com.arsdigita.formbuilder.ui.editors.DataDrivenSelectForm"), "com.arsdigita.formbuilder.ui.editors.DataDrivenSelectForm"),
Arrays.asList("forms-cms", "Text Description","Text Descriptions", Arrays.asList("forms-cms", "Text Description", "Text Descriptions",
"com.arsdigita.formbuilder.PersistentText", "com.arsdigita.formbuilder.PersistentText",
"com.arsdigita.formbuilder.ui.editors.TextForm"), "com.arsdigita.formbuilder.ui.editors.TextForm"),
Arrays.asList("forms-cms", "Text Heading", "Text Headings", Arrays.asList("forms-cms", "Text Heading", "Text Headings",
"com.arsdigita.formbuilder.PersistentHeading", "com.arsdigita.formbuilder.PersistentHeading",
"com.arsdigita.formbuilder.ui.editors.HeadingForm"), "com.arsdigita.formbuilder.ui.editors.HeadingForm"),
Arrays.asList("forms-cms", "Section Break", "Section Break", Arrays.asList("forms-cms", "Section Break", "Section Break",
"com.arsdigita.formbuilder.PersistentHorizontalRule", "com.arsdigita.formbuilder.PersistentHorizontalRule",
"com.arsdigita.formbuilder.ui.editors.HorizontalRuleForm"), "com.arsdigita.formbuilder.ui.editors.HorizontalRuleForm"),
Arrays.asList("forms-cms", "User Email Field","User Email Fields", Arrays.asList("forms-cms", "User Email Field", "User Email Fields",
"com.arsdigita.formbuilder.PersistentEmailField", "com.arsdigita.formbuilder.PersistentEmailField",
"com.arsdigita.formbuilder.ui.editors.EmailFieldForm") "com.arsdigita.formbuilder.ui.editors.EmailFieldForm"));
); /**
* List of process listeners used in applications forms. Each listener is
/** List of process listeners used in applications forms. Each listener is * described by application indicator, process name (singular & plural),
described by application indicator, process name (singular & plural), * action class name and action ui class name. These are really not user or
action class name and action ui class name. These are really not user * administrator configurabel and therefore not implemented as ccm
or administrator configurabel and therefore not implemented as ccm * parameter.
parameter. */ */
private static List processListenerTypes = Arrays.asList( private static List processListenerTypes = Arrays.asList(
Arrays.asList("forms-cms", "Confirmation email", Arrays.asList("forms-cms", "Confirmation email",
"Confirmation emails", "Confirmation emails",
"com.arsdigita.formbuilder.actions.ConfirmEmailListener", "com.arsdigita.formbuilder.actions.ConfirmEmailListener",
"com.arsdigita.formbuilder.ui.editors.ConfirmEmailForm"), "com.arsdigita.formbuilder.ui.editors.ConfirmEmailForm"),
Arrays.asList("forms-cms", "URL redirect", "URL redirects", Arrays.asList("forms-cms", "URL redirect", "URL redirects",
"com.arsdigita.formbuilder.actions.ConfirmRedirectListener", "com.arsdigita.formbuilder.actions.ConfirmRedirectListener",
"com.arsdigita.formbuilder.ui.editors.ConfirmRedirectForm"), "com.arsdigita.formbuilder.ui.editors.ConfirmRedirectForm"),
Arrays.asList("forms-cms", "Simple email", "Simple emails", Arrays.asList("forms-cms", "Simple email", "Simple emails",
"com.arsdigita.formbuilder.actions.SimpleEmailListener", "com.arsdigita.formbuilder.actions.SimpleEmailListener",
"com.arsdigita.formbuilder.ui.editors.SimpleEmailForm"), "com.arsdigita.formbuilder.ui.editors.SimpleEmailForm"),
Arrays.asList("forms-cms", "Templated email", "Templated emails", Arrays.asList("forms-cms", "Templated email", "Templated emails",
"com.arsdigita.formbuilder.actions.TemplateEmailListener", "com.arsdigita.formbuilder.actions.TemplateEmailListener",
"com.arsdigita.formbuilder.ui.editors.TemplateEmailForm"), "com.arsdigita.formbuilder.ui.editors.TemplateEmailForm"),
Arrays.asList( "forms-cms", "Remote Server POST", Arrays.asList("forms-cms", "Remote Server POST",
"Remote Server POSTs", "Remote Server POSTs",
"com.arsdigita.formbuilder.actions.RemoteServerPostListener", "com.arsdigita.formbuilder.actions.RemoteServerPostListener",
"com.arsdigita.formbuilder.ui.editors.RemoteServerPostForm" ), "com.arsdigita.formbuilder.ui.editors.RemoteServerPostForm"),
Arrays.asList( "forms-cms", "XML email", "XML emails", Arrays.asList("forms-cms", "XML email", "XML emails",
"com.arsdigita.formbuilder.actions.XMLEmailListener", "com.arsdigita.formbuilder.actions.XMLEmailListener",
"com.arsdigita.formbuilder.ui.editors.XMLEmailForm" ) "com.arsdigita.formbuilder.ui.editors.XMLEmailForm"));
); private static List dataQueries = Arrays.asList(
Arrays.asList("forms-cms",
"com.arsdigita.formbuilder.DataQueryUsers",
private static List dataQueries = Arrays.asList( "List of all registered users"),
Arrays.asList("forms-cms", Arrays.asList("forms-cms",
"com.arsdigita.formbuilder.DataQueryUsers", "com.arsdigita.formbuilder.DataQueryPackages",
"List of all registered users"), "List of all installed packages"));
Arrays.asList("forms-cms",
"com.arsdigita.formbuilder.DataQueryPackages",
"List of all installed packages")
);
// Currently not a Loader task. There is no way to persist tasks preferences // Currently not a Loader task. There is no way to persist tasks preferences
// on a per section base. // on a per section base.
/** /**
* When to generate email alerts: by default, generate email alerts * When to generate email alerts: by default, generate email alerts on
* on enable, finish, and rollback (happens on rejection) changes. * enable, finish, and rollback (happens on rejection) changes. There are
* There are four action types for each task type: enable, * four action types for each task type: enable, disable, finish, and
* disable, finish, and rollback. Note that the values below are * rollback. Note that the values below are based on the task labels, and as
* based on the task labels, and as such are not globalized. * such are not globalized.
*/ */
/* /*
private final Parameter * private final Parameter m_taskAlerts = new StringArrayParameter(
m_taskAlerts = new StringArrayParameter( * "com.arsdigita.cms.task_alerts", Parameter.REQUIRED, new String[] {
"com.arsdigita.cms.task_alerts", * "Authoring:enable:finish:rollback", "Approval:enable:finish:rollback",
Parameter.REQUIRED, new String[] { * "Deploy:enable:finish:rollback" } );
"Authoring:enable:finish:rollback",
"Approval:enable:finish:rollback",
"Deploy:enable:finish:rollback" } );
*/ */
// /////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////
// //
// Parameters controlling Overdue Task alerts: // Parameters controlling Overdue Task alerts:
@ -414,8 +372,6 @@ public final class LoaderConfig extends AbstractConfig {
// per section base of to store them in the database at all. So it is // per section base of to store them in the database at all. So it is
// currently not a loader task and commented out here. // currently not a loader task and commented out here.
// /////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////
// /** // /**
// * sendOverdueAlerts: Should we send alerts about overdue tasks at all? // * sendOverdueAlerts: Should we send alerts about overdue tasks at all?
// */ // */
@ -424,7 +380,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.send_overdue_alerts", // "com.arsdigita.cms.loader.send_overdue_alerts",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// new Boolean(false) ); // new Boolean(false) );
// /** // /**
// * taskDuration: The time between when a task is enabled (it is made // * taskDuration: The time between when a task is enabled (it is made
// * available for completion) and when it is // * available for completion) and when it is
@ -435,7 +390,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.task_duration", // "com.arsdigita.cms.loader.task_duration",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// new Integer(96) ); // new Integer(96) );
// /** // /**
// * alertInterval: The time to wait between sending successive alerts on // * alertInterval: The time to wait between sending successive alerts on
// * the same overdue task (in HOURS) // * the same overdue task (in HOURS)
@ -445,7 +399,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.overdue_alert_interval", // "com.arsdigita.cms.loader.overdue_alert_interval",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// new Integer(24) ); // new Integer(24) );
// /** // /**
// * maxAlerts: The maximum number of alerts to send about any one // * maxAlerts: The maximum number of alerts to send about any one
// * overdue task // * overdue task
@ -455,35 +408,34 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.mas_alerts", // "com.arsdigita.cms.loader.mas_alerts",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// new Integer(5) ); // new Integer(5) );
/** /**
* Standard Constructor. * Standard Constructor.
*/ */
public LoaderConfig() { public LoaderConfig() {
// register(m_workspaceURL); // register(m_workspaceURL);
// register(m_contentCenterMap); // register(m_contentCenterMap);
register(m_ctDefFiles); register(m_ctDefFiles);
// Parameters for creating a content section // Parameters for creating a content section
register(m_isPublic); register(m_isPublic);
register(m_itemResolverClass); register(m_itemResolverClass);
register(m_templateResolverClass); register(m_templateResolverClass);
register(m_useSectionCategories); register(m_useSectionCategories);
register(m_categoryFileList); register(m_categoryFileList);
// (Currently not a loader task) // (Currently not a loader task)
// register(m_taskAlerts); // register(m_taskAlerts);
// Parameters controlling Overdue Task alerts: // Parameters controlling Overdue Task alerts:
// (Currently not a loader task) // (Currently not a loader task)
// register(m_sendOverdueAlerts); // register(m_sendOverdueAlerts);
// register(m_taskDuration); // register(m_taskDuration);
// register(m_overdueAlertInterval); // register(m_overdueAlertInterval);
// register(m_maxAlerts); // register(m_maxAlerts);
// Does not work at load time! // Does not work at load time!
// loadInfo(); // loadInfo();
} }
@ -492,7 +444,6 @@ public final class LoaderConfig extends AbstractConfig {
// Getter Methods // Getter Methods
// //
// ////////////////////////// // //////////////////////////
// Not used as long as we use old style application (seee above) // Not used as long as we use old style application (seee above)
// /** // /**
// * Fetch name (URL) of the workspace package instance, e.g. content-center // * Fetch name (URL) of the workspace package instance, e.g. content-center
@ -501,7 +452,6 @@ public final class LoaderConfig extends AbstractConfig {
// public String getWorkspaceURL() { // public String getWorkspaceURL() {
// return (String) get(m_workspaceURL); // return (String) get(m_workspaceURL);
// } // }
// Moved to CMSConfig as long as it is not a Loader task. (see above) // Moved to CMSConfig as long as it is not a Loader task. (see above)
// /** // /**
// * Fetch the file name contaning XML Mapping of the content center tabs // * Fetch the file name contaning XML Mapping of the content center tabs
@ -511,101 +461,11 @@ public final class LoaderConfig extends AbstractConfig {
// public String getContentCenterMap() { // public String getContentCenterMap() {
// return (String) get(m_contentCenterMap); // return (String) get(m_contentCenterMap);
// } // }
public List getCTDefFiles() { public List getCTDefFiles() {
String[] ctDefFiles = (String[]) get(m_ctDefFiles); String[] ctDefFiles = (String[]) get(m_ctDefFiles);
return Arrays.asList(ctDefFiles); return Arrays.asList(ctDefFiles);
} }
/**
* Retrieve the STAFF GROUP, i.e. a set of roles (author, editor, publisher,
* manager) and associated privileges for the content section to be created
* (m_contentSectionName).
*
* In loading step a complete default configuration is persisted in database,
* immutable at this point.
* See contentsection.ContentSectionSetup.registerRoles()
* In enterprise.init: name roles, List of roles to create.
*
* Set consists of a set of roles, for each role first field is the role name,
* second is the description, third is a list of privileges, and (optional)
* fourth is the workflow task to assign to.
*
* The set of roles constructed here is a complete set which reflects all
* functions of CMS and forms a necessary base for operations. When the first
* content section is created and loaded into database (during installation)
* this set is created, immutable by installer / administrator. Additional
* content section may be created using a subset. For a very special purpose
* a developer may alter the set.
*
* This method is typically used to construct the initial content section
* during installation.
*
* Not really implemented yet! We need a new parameter type "list" which
* must have multidimensional capabilities.
*
* As a temporary measure a constant list is retrieved. Until now the list
* was burried in enterprise.init and not user available for configuration.
* So it may turn into a permanent solution.
*/
public List getStuffGroup() {
final List<String> AUTH_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item",
"categorize_items");
final List<String> EDIT_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item",
"categorize_items", "delete_item", "approve_item" );
final List<String> PUBL_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item",
"categorize_items", "delete_item", "approve_item",
"publish");
final List<String> MNGR_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item",
"categorize_items", "delete_item", "approve_item",
"publish",
"staff_admin", "content_type_admin", "lifecycle_admin",
"workflow_admin", "category_admin");
m_staffGroup = new ArrayList();
m_staffGroup.add
( new ArrayList() {{ add("Author");
add("Creates new content");
add(AUTH_PRIVS);
add("Authoring");
}}
);
m_staffGroup.add
( new ArrayList() {{ add("Editor");
add("Reviews and approves the author's work");
add(EDIT_PRIVS);
add("Approval");
}}
);
m_staffGroup.add
( new ArrayList() {{ add("Publisher");
add("Deploys the content to the web site");
add(PUBL_PRIVS);
add("Publishing");
}}
);
m_staffGroup.add
( new ArrayList() {{ add("Manager");
add("Manages the overall content section");
add(MNGR_PRIVS);
// NB, manager doesn't have any assigned
// task for workflow - (as usual)
}}
);
return (List) m_staffGroup ;
}
/** /**
* Retrieve whether the content-section is publicly viewable (i.e. without * Retrieve whether the content-section is publicly viewable (i.e. without
* registration and login) * registration and login)
@ -628,10 +488,11 @@ public final class LoaderConfig extends AbstractConfig {
return (String) get(m_templateResolverClass); return (String) get(m_templateResolverClass);
} }
/** /**
* Retrieve weather to use section specific categories. If true they are * Retrieve weather to use section specific categories. If true they are
* loaded using the next parameters file list {@see getUseSectionCategories()} * loaded using the next parameters file list {
*
* @see getUseSectionCategories()}
* *
* Default value is false, so standard navigation is used. * Default value is false, so standard navigation is used.
* @return * @return
@ -641,9 +502,9 @@ public final class LoaderConfig extends AbstractConfig {
} }
/** /**
* Retrieve the list of files containing categories to load. * Retrieve the list of files containing categories to load. In old
* In old Initialiser: Parameter name: CATEGORIES * Initialiser: Parameter name: CATEGORIES Deskr. "XML file containing the
* Deskr. "XML file containing the category tree" * category tree"
*/ */
public List getCategoryFileList() { public List getCategoryFileList() {
String[] catFiles = (String[]) get(m_categoryFileList); String[] catFiles = (String[]) get(m_categoryFileList);
@ -652,14 +513,13 @@ public final class LoaderConfig extends AbstractConfig {
public List getWidgetTypes() { public List getWidgetTypes() {
return widgetTypes; return widgetTypes;
} }
public List getProcessListenerTypes() { public List getProcessListenerTypes() {
return processListenerTypes; return processListenerTypes;
} }
public List getDataQueries() { public List getDataQueries() {
return dataQueries; return dataQueries;
} }
} }

View File

@ -23,14 +23,12 @@ import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter; import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.IntegerParameter; import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.Parameter; import com.arsdigita.util.parameter.Parameter;
//import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.StringArrayParameter; import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter; import com.arsdigita.util.parameter.StringParameter;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@ -39,9 +37,13 @@ import org.apache.log4j.Logger;
* Configures parameter which are not persisted in the database and may be * Configures parameter which are not persisted in the database and may be
* changes during each startup of the system. * changes during each startup of the system.
* @author pb * @author pb
* @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
*/ */
public final class ContentSectionConfig extends AbstractConfig { public final class ContentSectionConfig extends AbstractConfig {
private List m_defaultRoles;
private List m_defaultWorkflows;
/** Private Logger instance for debugging purpose. */ /** Private Logger instance for debugging purpose. */
private static final Logger s_log = private static final Logger s_log =
Logger.getLogger(ContentSectionConfig.class); Logger.getLogger(ContentSectionConfig.class);
@ -216,7 +218,6 @@ public final class ContentSectionConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.section_staff_group", // "com.arsdigita.cms.loader.section_staff_group",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// null); // null);
private List m_staffGroup;
// Viewer group, set autonomously by ContentSection.create() method. We can // Viewer group, set autonomously by ContentSection.create() method. We can
@ -312,7 +313,7 @@ public final class ContentSectionConfig extends AbstractConfig {
private final Parameter private final Parameter
m_useSectionCategories = new BooleanParameter m_useSectionCategories = new BooleanParameter
("com.arsdigita.cms.section.use_section_categories", ("com.arsdigita.cms.section.use_section_categories",
Parameter.REQUIRED, new Boolean(false)); Parameter.REQUIRED, false);
/** /**
* XML file containing the category tree to load for this content section. * XML file containing the category tree to load for this content section.
@ -460,7 +461,12 @@ public final class ContentSectionConfig extends AbstractConfig {
* was burried in enterprise.init and not user available for configuration. * was burried in enterprise.init and not user available for configuration.
* So it may turn into a permanent solution. * So it may turn into a permanent solution.
*/ */
public List getStuffGroup() {
/**
* Changed: The forth field is not used anymore
*
*/
public List getDefaultRoles() {
final List<String> AUTH_PRIVS = Arrays.asList( final List<String> AUTH_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item", "new_item","read_item", "preview_item", "edit_item",
@ -478,43 +484,169 @@ public final class ContentSectionConfig extends AbstractConfig {
"publish", "publish",
"staff_admin", "content_type_admin", "lifecycle_admin", "staff_admin", "content_type_admin", "lifecycle_admin",
"workflow_admin", "category_admin"); "workflow_admin", "category_admin");
final List<String> TRST_PRIVS = Arrays.asList(
"new_item","read_item", "preview_item", "edit_item",
"categorize_items", "delete_item", "approve_item",
"publish", "apply_alternate_workflows");
m_staffGroup = new ArrayList(); m_defaultRoles = new ArrayList();
m_staffGroup.add m_defaultRoles.add
( new ArrayList() {{ add("Author"); ( new ArrayList() {{ add("Author");
add("Creates new content"); add("Creates new content");
add(AUTH_PRIVS); add(AUTH_PRIVS);
add("Authoring");
}} }}
); );
m_staffGroup.add m_defaultRoles.add
( new ArrayList() {{ add("Editor"); ( new ArrayList() {{ add("Editor");
add("Reviews and approves the author's work"); add("Reviews and approves the author's work");
add(EDIT_PRIVS); add(EDIT_PRIVS);
add("Approval");
}} }}
); );
m_staffGroup.add m_defaultRoles.add
( new ArrayList() {{ add("Publisher"); ( new ArrayList() {{ add("Publisher");
add("Deploys the content to the web site"); add("Deploys the content to the web site");
add(PUBL_PRIVS); add(PUBL_PRIVS);
add("Publishing");
}} }}
); );
m_staffGroup.add m_defaultRoles.add
( new ArrayList() {{ add("Manager"); ( new ArrayList() {{ add("Manager");
add("Manages the overall content section"); add("Manages the overall content section");
add(MNGR_PRIVS); add(MNGR_PRIVS);
// NB, manager doesn't have any assigned }}
// task for workflow - (as usual) );
m_defaultRoles.add
( new ArrayList() {{ add("Trusted User");
add("A trusted user is allowed to create and publish items without review");
add(TRST_PRIVS);
}} }}
); );
return (List) m_staffGroup ; return (List) m_defaultRoles ;
} }
public List getDefaultWorkflows() {
if(m_defaultWorkflows == null) {
m_defaultWorkflows = new ArrayList();
// Prodcution Workflow
m_defaultWorkflows.add(
new HashMap<String, Object>() {{ put("name", "Redigierte Veröffentlichung");
put("description", "A process that involves creating and approving content.");
put("isDefault", "true");
put("tasks",
new ArrayList() {{ add(
new HashMap<String, Object>() {{ put("name", "Verfassen");
put("description", "Create content.");
put("type", "Author");
put("role",
new ArrayList<String>() {{ add("Author");
}}
);
}}
);
add(
new HashMap<String, Object>() {{ put("name", "Überprüfen");
put("description", "Approve content.");
put("type", "Edit");
put("role",
new ArrayList<String>() {{ add("Editor");
}}
);
put("dependOn",
new ArrayList<String>() {{ add("Verfassen");
}}
);
}}
);
add(
new HashMap<String, Object>() {{ put("name", "Veröffentlichen");
put("description", "Deploy content.");
put("type", "Deploy");
put("role",
new ArrayList<String>() {{ add("Publisher");
}}
);
put("dependOn",
new ArrayList<String>() {{ add("Überprüfen");
}}
);
}}
);
}}
);
}}
);
// TrustedUser Workflow
m_defaultWorkflows.add(
new HashMap<String, Object>() {{ put("name", "Direkte Veröffentlichung");
put("description", "Create and publish content without review");
put("isDefault", "false");
put("tasks",
new ArrayList() {{ add(
new HashMap<String, Object>() {{ put("name", "Verfassen");
put("description", "Create content.");
put("type", "Author");
put("role",
new ArrayList<String>() {{ add("Author");
add("Trusted User");
}}
);
}}
);
add(
new HashMap<String, Object>() {{ put("name", "Veröffentlichen");
put("description", "Deploy content.");
put("type", "Deploy");
put("role",
new ArrayList<String>() {{ add("Publisher");
add("Trusted User");
}}
);
put("dependOn",
new ArrayList<String>() {{ add("Verfassen");
}}
);
}}
);
}}
);
}}
);
/*
// Addiditonal Workflows
m_defaultWorkflows.add(
new HashMap<String, Object>() {{ put("name", "");
put("description", "");
put("tasks",
new ArrayList() {{ add(
new HashMap<String, Object>() {{ put("name", "");
put("description", "");
put("type", "");
put("role",
new ArrayList<String>() {{ add("");
}}
);
put("dependOn",
new ArrayList<String>() {{ add("");
}}
);
}}
);
}}
);
}}
);
*/
}
return m_defaultWorkflows;
}
/** /**
* Retrieve whether the content-section is publicly viewable (i.e. without * Retrieve whether the content-section is publicly viewable (i.e. without
* registration and login) * registration and login)

View File

@ -43,7 +43,6 @@ import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.workflow.simple.WorkflowTemplate; import com.arsdigita.workflow.simple.WorkflowTemplate;
import com.arsdigita.xml.XML; import com.arsdigita.xml.XML;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -54,7 +53,6 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Stack; import java.util.Stack;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
@ -65,20 +63,21 @@ import org.xml.sax.helpers.DefaultHandler;
* into the database. * into the database.
* *
* @author Peter Boy (pboy@barkhof.uni-bremen.de) * @author Peter Boy (pboy@barkhof.uni-bremen.de)
* @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
* @author Jon Orris (jorris@redhat.com) * @author Jon Orris (jorris@redhat.com)
* @version $Id: $ * @version $Id: $
*/ */
public final class ContentSectionSetup { public final class ContentSectionSetup {
private static Logger s_log = Logger.getLogger(ContentSectionSetup.class); private static Logger s_log = Logger.getLogger(ContentSectionSetup.class);
private HashMap m_tasks = new HashMap(); private HashMap<String, Role> m_roles = new HashMap<String, Role>();
private LifecycleDefinition m_lcd; private LifecycleDefinition m_lcd;
private WorkflowTemplate m_wf; private WorkflowTemplate m_wf;
final ContentSection m_section; final ContentSection m_section;
/** /**
* Constructor. Using this constructor the content section has to be * Constructor. Using this constructor the content section has to be already
* already created using ContentSection.create(name) * created using ContentSection.create(name)
* *
* @param section name of a content section previously created by * @param section name of a content section previously created by
* ContentSection.create * ContentSection.create
@ -89,21 +88,22 @@ public final class ContentSectionSetup {
} }
/** /**
* Wrapper class to create and configure a content section instance * Wrapper class to create and configure a content section instance in one
* in one step. * step.
* *
* Method needs a transaction to proceed successfully. * Method needs a transaction to proceed successfully.
* {@link com.arsdigita.cms.contentsection.Initializer#checkForNewContentSection() } * {@link com.arsdigita.cms.contentsection.Initializer#checkForNewContentSection()
* }
*/ */
public static void setupContentSectionAppInstance( public static ContentSection setupContentSectionAppInstance(String name,
String name, List defaultRoles,
List staffGroup, List defaultWorkflows,
Boolean isPubliclyViewable, Boolean isPubliclyViewable,
String itemResolverClassName, String itemResolverClassName,
String templateResolverClassName, String templateResolverClassName,
List sectionContentTypes, List sectionContentTypes,
Boolean useSectionCategories, Boolean useSectionCategories,
List categoryFileList) { List categoryFileList) {
s_log.info("Creating content section on /" + name); s_log.info("Creating content section on /" + name);
@ -111,10 +111,10 @@ public final class ContentSectionSetup {
ContentSectionSetup setup = new ContentSectionSetup(section); ContentSectionSetup setup = new ContentSectionSetup(section);
// Setup the access controls // Setup the access controls
setup.registerRoles(staffGroup); setup.registerRoles(defaultRoles);
setup.registerWorkflows(defaultWorkflows);
setup.registerViewers(isPubliclyViewable); setup.registerViewers(isPubliclyViewable);
setup.registerPublicationCycles(); setup.registerPublicationCycles();
setup.registerWorkflowTemplates();
setup.registerResolvers(itemResolverClassName, templateResolverClassName); setup.registerResolvers(itemResolverClassName, templateResolverClassName);
// setup.registerContentTypes((List)m_conf.getParameter(TYPES)); // setup.registerContentTypes((List)m_conf.getParameter(TYPES));
@ -131,17 +131,17 @@ public final class ContentSectionSetup {
section.save(); section.save();
// return section; return section;
} }
/** /**
* Steps through a list of roles which are part of a staff group and * Steps through a list of roles which are part of a staff group and
* delegates processing of each role. * delegates processing of each role.
* *
* @param roles * @param roles
*/ */
public void registerRoles(List roles) { public void registerRoles(List<List> roles) {
Iterator i = roles.iterator(); Iterator i = roles.iterator();
while (i.hasNext()) { while (i.hasNext()) {
@ -150,21 +150,13 @@ public final class ContentSectionSetup {
String name = (String) role.get(0); String name = (String) role.get(0);
String desc = (String) role.get(1); String desc = (String) role.get(1);
List privileges = (List) role.get(2); List privileges = (List) role.get(2);
String task = (role.size() > 3 ? (String) role.get(3) : null);
s_log.info("Creating role " + name); s_log.info("Creating role " + name);
Role newRole = registerRole(name, desc, privileges);
m_roles.put(name, newRole);
Role group = registerRole(
name,
desc,
privileges);
if (task != null) {
m_tasks.put(task, group);
}
} }
} }
/** /**
@ -204,6 +196,15 @@ public final class ContentSectionSetup {
} }
} }
// Add site-wide administrator group by default to all roles
PartyCollection partyColl = Party.retrieveAllParties();
// FIXME: String for Site-wide Admininistrators is hardcoded because
// this group in inserted via sql-command during setup
partyColl.filter("Site-wide Administrators");
if(partyColl.next()) {
role.add(partyColl.getParty());
}
return role; return role;
} }
@ -259,9 +260,9 @@ public final class ContentSectionSetup {
/** /**
* Checks for specific item resolver and template resolver classes probably * Checks for specific item resolver and template resolver classes probably
* specified in parameters, otherwise uses system wide default parameters * specified in parameters, otherwise uses system wide default parameters
* specified in CMS global configuration file. Delegates persistence task * specified in CMS global configuration file. Delegates persistence task to
* to ContentSection. * ContentSection.
* *
* @param itemResolverClassName * @param itemResolverClassName
* @param templateResolverClassName * @param templateResolverClassName
*/ */
@ -269,24 +270,22 @@ public final class ContentSectionSetup {
String templateResolverClassName) { String templateResolverClassName) {
if (itemResolverClassName != null if (itemResolverClassName != null
&& itemResolverClassName.length() > 0) { && itemResolverClassName.length() > 0) {
m_section.setItemResolverClass(itemResolverClassName); m_section.setItemResolverClass(itemResolverClassName);
s_log.info("Registering " + itemResolverClassName s_log.info("Registering " + itemResolverClassName
+ " as the item resolver class"); + " as the item resolver class");
} else { } else {
m_section.setItemResolverClass(ContentSection.getConfig() m_section.setItemResolverClass(ContentSection.getConfig().getDefaultItemResolverClass().getName());
.getDefaultItemResolverClass().getName());
s_log.info("Registering " + itemResolverClassName s_log.info("Registering " + itemResolverClassName
+ " as the item resolver class"); + " as the item resolver class");
} }
if (templateResolverClassName != null if (templateResolverClassName != null
&& templateResolverClassName.length() > 0) { && templateResolverClassName.length() > 0) {
m_section.setTemplateResolverClass(templateResolverClassName); m_section.setTemplateResolverClass(templateResolverClassName);
s_log.info("Registering " + templateResolverClassName s_log.info("Registering " + templateResolverClassName
+ " as the template resolver class"); + " as the template resolver class");
} else { } else {
m_section.setTemplateResolverClass(ContentSection.getConfig() m_section.setTemplateResolverClass(ContentSection.getConfig().getDefaultTemplateResolverClass().getName());
.getDefaultTemplateResolverClass().getName());
s_log.info("Registering " + templateResolverClassName s_log.info("Registering " + templateResolverClassName
+ " as the template resolver class"); + " as the template resolver class");
} }
@ -295,9 +294,9 @@ public final class ContentSectionSetup {
} }
/** /**
* Create a (default) publication cycle and store it in the datavbase * Create a (default) publication cycle and store it in the datavbase
* (delegated to package com.arsdigita.cms.lifecycle) * (delegated to package com.arsdigita.cms.lifecycle)
* *
* @throws InitializationException * @throws InitializationException
*/ */
public void registerPublicationCycles() public void registerPublicationCycles()
@ -323,86 +322,110 @@ public final class ContentSectionSetup {
m_section.save(); m_section.save();
} }
/** private void registerWorkflows(List workflows) {
Iterator workflowsIter = workflows.iterator();
while (workflowsIter.hasNext()) {
HashMap<String, CMSTask> newTasks = new HashMap<String, CMSTask>();
HashMap<String, Object> workflow = (HashMap) workflowsIter.next();
// Create a new WorkflowTemplate
WorkflowTemplate wf = new WorkflowTemplate();
wf.setLabel((String) workflow.get("name"));
wf.setDescription((String) workflow.get("description"));
wf.save();
// Add tasks to workflow
Iterator tasksIter = ((List) workflow.get("tasks")).iterator();
while (tasksIter.hasNext()) {
HashMap<String, Object> task = (HashMap) tasksIter.next();
// Setup new task
CMSTask newTask = new CMSTask();
newTask.setLabel((String) task.get("name"));
newTask.setDescription((String) task.get("description"));
newTask.setTaskType(CMSTaskType.retrieveByName((String) task.get("type")));
// Add roles to task
if (task.containsKey("role")) {
Iterator<String> roleIter = ((List<String>) task.get("role")).iterator();
while (roleIter.hasNext()) {
Role role = m_roles.get(roleIter.next());
if (role != null) {
newTask.assignGroup(role.getGroup());
}
}
}
// Save task
newTask.save();
// Save task to HashMap for fast access in the next loop
newTasks.put((String) task.get("name"), newTask);
}
// Setup task dependencies (easier to do it after creating all task)
tasksIter = ((List) workflow.get("tasks")).iterator();
while (tasksIter.hasNext()) {
HashMap<String, Object> task = (HashMap) tasksIter.next();
CMSTask newTask = newTasks.get((String) task.get("name"));
if (task.containsKey("dependOn")) {
Iterator<String> dependOnIter = ((List<String>) task.get("dependOn")).iterator();
while (dependOnIter.hasNext()) {
CMSTask dependOn = newTasks.get(dependOnIter.next());
if (dependOn != null) {
newTask.addDependency(dependOn);
}
}
}
newTask.save();
}
// Add tasks to the workflow
for (CMSTask newTask : newTasks.values()) {
wf.addTask(newTask);
}
// Save workflow
wf.save();
// Add Workflow to current section
m_section.addWorkflowTemplate(wf);
m_section.save();
// If this workflow should be the default or is the first one
// save it for easy access in registerContentType
if(m_wf == null || (workflow.containsKey("isDefault") && workflow.get("isDefault").equals("true"))) {
m_wf = wf;
}
}
}
/**
* Defines a (default for section) workflow which gets persisted in tne * Defines a (default for section) workflow which gets persisted in tne
* database. * database.
*
* This one is probably deprecated.
* *
* @throws InitializationException * @throws InitializationException
*/ */
public void registerWorkflowTemplates() public void registerWorkflowTemplates() throws ConfigError {
throws ConfigError {
// The 3-step production workflow. ContentSectionConfig config = new ContentSectionConfig();
WorkflowTemplate wf = new WorkflowTemplate(); config.load();
wf.setLabel((String) GlobalizationUtil.globalize( registerWorkflows(config.getDefaultWorkflows());
"cms.installer.production_workflow").localize());
wf.setDescription("A process that involves creating and approving content.");
wf.save();
CMSTask authoring = new CMSTask();
authoring.setLabel((String) GlobalizationUtil.globalize(
"cms.installer.authoring").localize());
authoring.setDescription("Create content.");
authoring.save();
Role author = (Role) m_tasks.get("Authoring");
if (author != null) {
authoring.assignGroup(author.getGroup());
}
authoring.setTaskType(CMSTaskType.retrieve(CMSTaskType.AUTHOR));
authoring.save();
CMSTask approval = new CMSTask();
approval.setLabel((String) GlobalizationUtil.globalize(
"cms.installer.approval").localize());
approval.setDescription("Approve content.");
approval.save();
approval.addDependency(authoring);
approval.save();
Role approver = (Role) m_tasks.get("Approval");
if (approver != null) {
approval.assignGroup(approver.getGroup());
}
approval.setTaskType(CMSTaskType.retrieve(CMSTaskType.EDIT));
approval.save();
CMSTask deploy = new CMSTask();
deploy.setLabel((String) GlobalizationUtil.globalize(
"cms.installer.deploy").localize());
deploy.setDescription("Deploy content.");
deploy.save();
deploy.addDependency(approval);
deploy.save();
Role publisher = (Role) m_tasks.get("Publishing");
if (publisher != null) {
deploy.assignGroup(publisher.getGroup());
}
deploy.setTaskType(CMSTaskType.retrieve(CMSTaskType.DEPLOY));
deploy.save();
wf.addTask(authoring);
wf.addTask(approval);
wf.addTask(deploy);
wf.save();
m_section.addWorkflowTemplate(wf);
m_section.save();
m_wf = wf;
} }
/** /**
* Steps through a list of content types to be available for this content * Steps through a list of content types to be available for this content
* section and delegates processing of each type. * section and delegates processing of each type.
* *
* @param types list of content types to be available for this content section * @param types list of content types to be available for this content
* section
*/ */
public void registerContentTypes(List types) { public void registerContentTypes(List types) {
@ -424,8 +447,9 @@ public final class ContentSectionSetup {
} }
/** /**
* Process one content type and registers it with the current content section. * Process one content type and registers it with the current content
* * section.
*
* @param name * @param name
* @return * @return
*/ */
@ -456,9 +480,9 @@ public final class ContentSectionSetup {
} }
/** /**
* *
* @param type * @param type
* @param filename * @param filename
*/ */
void registerTemplate(ContentType type, String filename) { void registerTemplate(ContentType type, String filename) {
// Use the base of the file name (ie without path & extension) // Use the base of the file name (ie without path & extension)
@ -487,7 +511,7 @@ public final class ContentSectionSetup {
if (stream == null) { if (stream == null) {
throw new IllegalStateException((String) GlobalizationUtil.globalize( throw new IllegalStateException((String) GlobalizationUtil.globalize(
"cms.installer.cannot_find_file").localize() + filename); "cms.installer.cannot_find_file").localize() + filename);
} }
final BufferedReader input = new BufferedReader(new InputStreamReader(stream)); final BufferedReader input = new BufferedReader(new InputStreamReader(stream));
@ -514,8 +538,7 @@ public final class ContentSectionSetup {
temp.save(); temp.save();
TemplateManagerFactory.getInstance() TemplateManagerFactory.getInstance().addTemplate(m_section, type, temp, "public");
.addTemplate(m_section, type, temp, "public");
temp.publish(m_lcd, new Date()); temp.publish(m_lcd, new Date());
} }
@ -545,6 +568,8 @@ public final class ContentSectionSetup {
alert.setDescription( alert.setDescription(
"Receive alerts regarding expiration of pubished content"); "Receive alerts regarding expiration of pubished content");
alert.save(); alert.save();
} }
// // Currently there is no way to persists alert preferemces, therefore // // Currently there is no way to persists alert preferemces, therefore
@ -602,8 +627,8 @@ public final class ContentSectionSetup {
// } // }
// ///////////////////// Private Class Section //////////////////////////// // ///////////////////// Private Class Section ////////////////////////////
/** /**
* SAX Handler for category lists. Creates the categories as they are * SAX Handler for category lists. Creates the categories as they are
* defined, with structure, in the xml document. * defined, with structure, in the xml document.
*/ */
private class CategoryHandler extends DefaultHandler { private class CategoryHandler extends DefaultHandler {
@ -679,6 +704,4 @@ public final class ContentSectionSetup {
} }
} }
} // END private class CategoryHandler } // END private class CategoryHandler
} }

View File

@ -22,26 +22,23 @@ package com.arsdigita.cms.contentsection;
import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentSectionCollection; import com.arsdigita.cms.ContentSectionCollection;
import com.arsdigita.cms.workflow.CMSTask;
import com.arsdigita.cms.workflow.UnfinishedTaskNotifier; import com.arsdigita.cms.workflow.UnfinishedTaskNotifier;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.TransactionContext;
import com.arsdigita.domain.DomainObject; import com.arsdigita.domain.DomainObject;
import com.arsdigita.kernel.ACSObjectInstantiator; import com.arsdigita.kernel.ACSObjectInstantiator;
import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.TransactionContext;
import com.arsdigita.runtime.CompoundInitializer; import com.arsdigita.runtime.CompoundInitializer;
import com.arsdigita.runtime.ContextInitEvent;
import com.arsdigita.runtime.ContextCloseEvent; import com.arsdigita.runtime.ContextCloseEvent;
// import com.arsdigita.runtime.DataInitEvent; import com.arsdigita.runtime.ContextInitEvent;
import com.arsdigita.runtime.DomainInitEvent; import com.arsdigita.runtime.DomainInitEvent;
import com.arsdigita.web.Application; import com.arsdigita.web.Application;
import com.arsdigita.cms.workflow.CMSTask;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.Timer; import java.util.Timer;
import java.util.Vector; import java.util.Vector;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -188,7 +185,9 @@ public class Initializer extends CompoundInitializer {
for (Enumeration el=s_unfinishedTimers.elements(); for (Enumeration el=s_unfinishedTimers.elements();
el.hasMoreElements(); ) { el.hasMoreElements(); ) {
unfinishedTimer = (Timer) el.nextElement(); unfinishedTimer = (Timer) el.nextElement();
if(unfinishedTimer != null) unfinishedTimer.cancel(); if(unfinishedTimer != null) {
unfinishedTimer.cancel();
}
unfinishedTimer = null; unfinishedTimer = null;
// s_unfinishedTimer = null; // s_unfinishedTimer = null;
} }
@ -221,7 +220,8 @@ public class Initializer extends CompoundInitializer {
txn.beginTxn(); txn.beginTxn();
ContentSectionSetup.setupContentSectionAppInstance ContentSectionSetup.setupContentSectionAppInstance
(newSectionName, (newSectionName,
s_conf.getStuffGroup(), s_conf.getDefaultRoles(),
s_conf.getDefaultWorkflows(),
s_conf.isPubliclyViewable(), s_conf.isPubliclyViewable(),
s_conf.getItemResolverClass(), s_conf.getItemResolverClass(),
s_conf.getTemplateResolverClass(), s_conf.getTemplateResolverClass(),

View File

@ -19,215 +19,206 @@
package com.arsdigita.cms.workflow; package com.arsdigita.cms.workflow;
import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType; import com.arsdigita.cms.ContentType;
import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObject; import com.arsdigita.domain.DomainObject;
import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.Group;
import com.arsdigita.kernel.KernelHelper;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.User;
import com.arsdigita.kernel.UserCollection;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor; import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.messaging.Message;
import com.arsdigita.notification.Notification;
import com.arsdigita.persistence.DataAssociation; import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataAssociationCursor; import com.arsdigita.persistence.DataAssociationCursor;
import com.arsdigita.persistence.DataCollection; import com.arsdigita.persistence.DataCollection;
import com.arsdigita.persistence.DataObject; import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.DataOperation;
import com.arsdigita.persistence.DataQuery;
import com.arsdigita.persistence.Filter;
import com.arsdigita.persistence.OID; import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.Session;
import com.arsdigita.persistence.SessionManager; import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.versioning.TagCollection;
import com.arsdigita.versioning.Transaction;
import com.arsdigita.versioning.TransactionCollection;
import com.arsdigita.versioning.Versions;
import com.arsdigita.web.URL;
import com.arsdigita.workflow.simple.TaskComment;
import com.arsdigita.workflow.simple.TaskException;
import com.arsdigita.workflow.simple.UserTask;
import org.apache.log4j.Logger;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import org.apache.log4j.Logger;
/** /**
* This class represents a task type in the CMS system. The task type has attributes that impact on * This class represents a task type in the CMS system. The task type has
* the behaviour of tasks of that type * attributes that impact on the behaviour of tasks of that type
* *
* *
* @author chris.gilbert at westsussex.gov.uk * @author chris.gilbert at westsussex.gov.uk
* @version $Id: $ * @version $Id: $
*/ */
public class CMSTaskType extends DomainObject { public class CMSTaskType extends DomainObject {
public static final String BASE_DATA_OBJECT_TYPE = public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.cms.workflow.CMSTaskType"; "com.arsdigita.cms.workflow.CMSTaskType";
private static Map s_taskURLGeneratorCache = new HashMap();
private static Map s_taskURLGeneratorCache = new HashMap();
// pdl attribute names // pdl attribute names
public static final String ID = "taskTypeID"; public static final String ID = "taskTypeID";
public static final String NAME = "name"; public static final String NAME = "name";
public static final String DEFAULT_URL_GENERATOR_CLASS = public static final String DEFAULT_URL_GENERATOR_CLASS =
"defaultUrlGeneratorClass"; "defaultUrlGeneratorClass";
public static final String PRIVILEGE = "privilege"; public static final String PRIVILEGE = "privilege";
public static final String URL_GENERATORS = "generators"; public static final String URL_GENERATORS = "generators";
private static final Logger s_log = Logger.getLogger(CMSTaskType.class);
// known task types
public static final Integer AUTHOR = new Integer(1);
public static final Integer EDIT = new Integer(2);
public static final Integer DEPLOY = new Integer(3);
// cache task type domain objects to save unnecessary db lookups
public static Map<Integer, CMSTaskType> s_taskTypes = new HashMap<Integer, CMSTaskType>();
private static Map<String, Integer> s_taskNameMap = new HashMap<String, Integer>();
private static final Logger s_log = Logger.getLogger(CMSTaskType.class); static {
s_taskNameMap.put("Author", AUTHOR);
s_taskNameMap.put("Edit", EDIT);
s_taskNameMap.put("Deploy",DEPLOY);
}
public static CMSTaskType retrieve(Integer id) {
// known task types if (id == null) {
throw new IllegalArgumentException("Parameter id must not be null");
public static final Integer AUTHOR = new Integer(1); }
public static final Integer EDIT = new Integer(2);
public static final Integer DEPLOY = new Integer(3);
// cache task type domain objects to save unnecessary db lookups CMSTaskType type = s_taskTypes.get(id);
public static Map s_taskTypes = new HashMap(); if (type == null) {
type = new CMSTaskType(id);
s_taskTypes.put(id, type);
}
return type;
public static CMSTaskType retrieve (Integer id) { }
CMSTaskType type = (CMSTaskType)s_taskTypes.get(id);
if (type == null) {
type = new CMSTaskType(id);
s_taskTypes.put(id, type);
}
return type;
}
private CMSTaskType(Integer id) {
super(new OID(BASE_DATA_OBJECT_TYPE, id));
}
public CMSTaskType(DataObject obj) { public static CMSTaskType retrieveByName(String name) {
super(obj);
}
/** if (name == null || name.isEmpty()) {
* create a message object and associate it with the current application instance throw new IllegalArgumentException("Parameter name must not be null or empty");
* }
*/
public CMSTaskType() {
super(BASE_DATA_OBJECT_TYPE);
setID();
}
public Integer getID(){
return ((Integer)get(ID));
}
/**
* allocate a unique integer to the message
*
*/
private void setID() {
DataCollection allTypes =
SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
allTypes.addOrder(ID + " desc");
Integer id = new Integer(1);
if (allTypes.next()) {
CMSTaskType taskType =
(CMSTaskType) DomainObjectFactory.newInstance(
allTypes.getDataObject());
int currentMaxID = taskType.getID().intValue();
id = new Integer(currentMaxID + 1);
allTypes.close();
}
set(ID, id);
}
public String getName() {
return (String)get(NAME);
}
public PrivilegeDescriptor getPrivilege () {
return PrivilegeDescriptor.get((String)get(PRIVILEGE));
}
private TaskURLGenerator getDefaultTaskURLGenerator () throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String generatorClassName = (String)get(DEFAULT_URL_GENERATOR_CLASS);
Class URLGenerator = Class.forName(generatorClassName);
return (TaskURLGenerator)URLGenerator.newInstance();
}
public TaskURLGenerator getURLGenerator(String event, ContentItem item) {
String key = getID() + " " + event + " " + item.getContentType().getID();
s_log.debug("looking up url generator for key " + key);
TaskURLGenerator generator = (TaskURLGenerator)
s_taskURLGeneratorCache.get(key);
if (generator == null) {
s_log.debug("no generator found in cache");
DataAssociationCursor generators = ((DataAssociation)get(URL_GENERATORS)).cursor();
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE + "." + ContentType.ID, item.getContentType().getID());
try {
while (generators.next()) {
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for content type " + item.getContentType().getLabel());
// generator class available for this specific event and this specific content type
generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
generators.close();
}
if (generator == null) {
generators.reset();
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE, null);
while (generators.next()) {
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for any content type");
// generator class available for this specific event
generator = ((TaskEventURLGenerator)DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
generators.close();
}
}
if (generator == null) {
s_log.debug("no specific generator for " + event + " event on task type " + getName()+ ". Revert to default");
// fall back on default
generator = getDefaultTaskURLGenerator();
}
s_taskURLGeneratorCache.put(key, generator);
} catch(Exception e) {
throw new UncheckedWrapperException("Unable to retrieve a URL generator for event " + event + " on task type " + getID() + " ", e);
}
}
return generator;
}
/**
*
* Should be used when UI is implemented for managing task types. If a specific TaskURLGenerator
* is added or removed for an event, then the cached TaskURLGenerator needs to be removed
* @param event
*/
public void clearCachedEntry(String event) {
String key = getID() + " " + event;
s_taskURLGeneratorCache.remove(key);
}
Integer id = s_taskNameMap.get(name);
if (id == null) {
for (CMSTaskType type : s_taskTypes.values()) {
if (!s_taskNameMap.containsKey(type.getName())) {
s_taskNameMap.put(type.getName(), type.getID());
}
if (name.equals(type.getName())) {
id = type.getID();
}
}
}
return retrieve(id);
}
private CMSTaskType(Integer id) {
super(new OID(BASE_DATA_OBJECT_TYPE, id));
}
public CMSTaskType(DataObject obj) {
super(obj);
}
/**
* create a message object and associate it with the current application
* instance
*
*/
public CMSTaskType() {
super(BASE_DATA_OBJECT_TYPE);
setID();
}
public Integer getID() {
return ((Integer) get(ID));
}
/**
* allocate a unique integer to the message
*
*/
private void setID() {
DataCollection allTypes =
SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE);
allTypes.addOrder(ID + " desc");
Integer id = new Integer(1);
if (allTypes.next()) {
CMSTaskType taskType =
(CMSTaskType) DomainObjectFactory.newInstance(
allTypes.getDataObject());
int currentMaxID = taskType.getID().intValue();
id = new Integer(currentMaxID + 1);
allTypes.close();
}
set(ID, id);
}
public String getName() {
return (String) get(NAME);
}
public PrivilegeDescriptor getPrivilege() {
return PrivilegeDescriptor.get((String) get(PRIVILEGE));
}
private TaskURLGenerator getDefaultTaskURLGenerator() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String generatorClassName = (String) get(DEFAULT_URL_GENERATOR_CLASS);
Class URLGenerator = Class.forName(generatorClassName);
return (TaskURLGenerator) URLGenerator.newInstance();
}
public TaskURLGenerator getURLGenerator(String event, ContentItem item) {
String key = getID() + " " + event + " " + item.getContentType().getID();
s_log.debug("looking up url generator for key " + key);
TaskURLGenerator generator = (TaskURLGenerator) s_taskURLGeneratorCache.get(key);
if (generator == null) {
s_log.debug("no generator found in cache");
DataAssociationCursor generators = ((DataAssociation) get(URL_GENERATORS)).cursor();
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE + "." + ContentType.ID, item.getContentType().getID());
try {
while (generators.next()) {
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for content type " + item.getContentType().getLabel());
// generator class available for this specific event and this specific content type
generator = ((TaskEventURLGenerator) DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
generators.close();
}
if (generator == null) {
generators.reset();
generators.addEqualsFilter(TaskEventURLGenerator.EVENT, event);
generators.addEqualsFilter(TaskEventURLGenerator.CONTENT_TYPE, null);
while (generators.next()) {
s_log.debug("specific generator found for " + event + " event on task type " + getName() + " for any content type");
// generator class available for this specific event
generator = ((TaskEventURLGenerator) DomainObjectFactory.newInstance(generators.getDataObject())).getGenerator();
generators.close();
}
}
if (generator == null) {
s_log.debug("no specific generator for " + event + " event on task type " + getName() + ". Revert to default");
// fall back on default
generator = getDefaultTaskURLGenerator();
}
s_taskURLGeneratorCache.put(key, generator);
} catch (Exception e) {
throw new UncheckedWrapperException("Unable to retrieve a URL generator for event " + event + " on task type " + getID() + " ", e);
}
}
return generator;
}
/**
*
* Should be used when UI is implemented for managing task types. If a
* specific TaskURLGenerator is added or removed for an event, then the
* cached TaskURLGenerator needs to be removed
*
* @param event
*/
public void clearCachedEntry(String event) {
String key = getID() + " " + event;
s_taskURLGeneratorCache.remove(key);
}
} }