Removed creation of new content sections via the initializer (Ticket #2029)

git-svn-id: https://svn.libreccm.org/ccm/trunk@2530 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2014-02-19 13:18:12 +00:00
parent 8aa2a7ea21
commit 3d25fc7630
3 changed files with 480 additions and 532 deletions

View File

@ -16,11 +16,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
package com.arsdigita.cms.contentsection; package com.arsdigita.cms.contentsection;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.runtime.AbstractConfig; import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.*; import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.Parameter;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -30,8 +34,9 @@ import org.apache.log4j.Logger;
/** /**
* Configuration parameter to configure a content section during startup. * Configuration parameter to configure a content section during startup.
* *
* 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
* changes during each startup of the system. * startup of the system.
*
* @author pb * @author pb
* @author Sören Bernstein <quasi@quasiweb.de> * @author Sören Bernstein <quasi@quasiweb.de>
*/ */
@ -40,16 +45,18 @@ public final class ContentSectionConfig extends AbstractConfig {
private List m_defaultRoles; private List m_defaultRoles;
private List m_defaultWorkflows; private List m_defaultWorkflows;
/** Private Logger instance for debugging purpose. */ /**
private static final Logger s_log = * Private Logger instance for debugging purpose.
Logger.getLogger(ContentSectionConfig.class); */
private static final Logger s_log = Logger.getLogger(ContentSectionConfig.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 ContentSectionConfig s_config; private static ContentSectionConfig s_config;
/** /**
* Returns the singleton configuration record for the content section * Returns the singleton configuration record for the content section environment.
* environment.
* *
* @return The <code>ContentSectionConfig</code> record; it cannot be null * @return The <code>ContentSectionConfig</code> record; it cannot be null
*/ */
@ -62,7 +69,6 @@ public final class ContentSectionConfig extends AbstractConfig {
return s_config; return s_config;
} }
// ///////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
// //
// Set of parameters controlling Overdue Task alerts: // Set of parameters controlling Overdue Task alerts:
@ -71,18 +77,13 @@ public final class ContentSectionConfig extends AbstractConfig {
// configuration applied to every content section. // configuration applied to every content section.
// //
// ///////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////
/** /**
* A list of workflow tasks, and the associated events for which alerts * A list of workflow tasks, and the associated events for which alerts have to be sent.
* have to be sent. * Parameter name TASK_ALERTS in the old initializer system / enterprise.init Specifies when to
* Parameter name TASK_ALERTS in the old initializer system / enterprise.init * generate email alerts: by default, generate email alerts on enable, finish, and rollback
* Specifies when to generate email alerts: by default, generate email alerts * (happens on rejection) changes. There are four action types for each task type: enable,
* on enable, finish, and rollback (happens on rejection) changes. * disable, finish, and rollback. Example: (Note that the values below are based on the task
* There are four action types for each task type: enable, disable, finish, * labels, and as such are not globalized.)
* and rollback.
* Example:
* (Note that the values below are based on the task labels, and as such are
* not globalized.)
* <pre> * <pre>
* taskAlerts = { * taskAlerts = {
* { "Authoring", * { "Authoring",
@ -97,21 +98,16 @@ public final class ContentSectionConfig extends AbstractConfig {
* }; * };
* </pre> * </pre>
* *
* In the new Initializer system we use a specifically formatted String Array * In the new Initializer system we use a specifically formatted String Array because we have no
* because we have no List parameter. Format: * List parameter. Format: - A string for each task to handle, possible values: Authoring,
* - A string for each task to handle, possible values: Authoring, Approval, * Approval, Deploy - Each Task String: [taskName]:[alert_1]:...:[alert_n] The specially
* Deploy * formatted string is not handled by StringArray parameter, but forwarded untouched to the
* - Each Task String: [taskName]:[alert_1]:...:[alert_n] * initializer which has the duty to process it!
* The specially formatted string is not handled by StringArray parameter,
* but forwarded untouched to the initializer which has the duty to process
* it!
* *
* Currently there is no way to persist taskAlerts section specific. So all * Currently there is no way to persist taskAlerts section specific. So all sections have to
* sections have to treated equally. * treated equally. Default values are provided here.
* Default values are provided here.
*/ */
private final Parameter private final Parameter m_taskAlerts = new StringArrayParameter(
m_taskAlerts = new StringArrayParameter(
"com.arsdigita.cms.section.task_alerts", "com.arsdigita.cms.section.task_alerts",
Parameter.REQUIRED, new String[]{ Parameter.REQUIRED, new String[]{
"Authoring:enable:finish:rollback", "Authoring:enable:finish:rollback",
@ -120,21 +116,18 @@ public final class ContentSectionConfig extends AbstractConfig {
); );
/** /**
* Should we send alerts about overdue tasks at all? * Should we send alerts about overdue tasks at all? Send alerts when a task is overdue (has
* Send alerts when a task is overdue (has remained in the \"enabled\" state * remained in the \"enabled\" state for a long time) Parameter SEND_OVERDUE_ALERTS in the old
* for a long time) * initializer system, default false
* Parameter SEND_OVERDUE_ALERTS in the old initializer system, default false
*/ */
private final Parameter private final Parameter m_sendOverdueAlerts = new BooleanParameter(
m_sendOverdueAlerts = new BooleanParameter(
"com.arsdigita.cms.section.send_overdue_alerts", "com.arsdigita.cms.section.send_overdue_alerts",
Parameter.REQUIRED, Parameter.REQUIRED,
false); false);
/** /**
* The time between when a task is enabled (i.e. it is made available for * The time between when a task is enabled (i.e. it is made available for completion) and when
* completion) and when it is considered overdue (in HOURS). * it is considered overdue (in HOURS).
*/ */
// XXX Once the Duration of a Task can actually be maintained (in the UI, // XXX Once the Duration of a Task can actually be maintained (in the UI,
// or initialization parameters), we should use the value in the DB, and // or initialization parameters), we should use the value in the DB, and
@ -142,41 +135,31 @@ public final class ContentSectionConfig extends AbstractConfig {
// Parameter name TASK_DURATION in the old initializer system. // Parameter name TASK_DURATION in the old initializer system.
// Description: How long a task can remain \"enabled\" before it is // Description: How long a task can remain \"enabled\" before it is
// considered overdue (in hours) // considered overdue (in hours)
private final Parameter private final Parameter m_taskDuration = new IntegerParameter(
m_taskDuration = new IntegerParameter(
"com.arsdigita.cms.section.task_duration", "com.arsdigita.cms.section.task_duration",
Parameter.REQUIRED, Parameter.REQUIRED,
new Integer(96)); new Integer(96));
/** /**
* The time to wait between sending successive alerts on the same * The time to wait between sending successive alerts on the same overdue task (in HOURS).
* overdue task (in HOURS). * Parameter name OVERDUE_ALERT_INTERVAL in old initializer system Description: Time to wait
* Parameter name OVERDUE_ALERT_INTERVAL in old initializer system * between sending overdue notifications on the same task (in hours)
* Description: Time to wait between sending overdue notifications on the
* same task (in hours)
*/ */
private final Parameter private final Parameter m_alertInterval = new IntegerParameter(
m_alertInterval = new IntegerParameter(
"com.arsdigita.cms.section.alert_interval", "com.arsdigita.cms.section.alert_interval",
Parameter.REQUIRED, Parameter.REQUIRED,
new Integer(24)); new Integer(24));
/** /**
* The maximum number of alerts to send about any one overdue task. * The maximum number of alerts to send about any one overdue task. Parameter name MAX_ALERTS in
* Parameter name MAX_ALERTS in old initializer system. * old initializer system. Description: The maximum number of alerts to send that a single task
* Description: The maximum number of alerts to send that a single task is * is overdue
* overdue
*/ */
private final Parameter private final Parameter m_maxAlerts = new IntegerParameter(
m_maxAlerts = new IntegerParameter(
"com.arsdigita.cms.section.max_alerts", "com.arsdigita.cms.section.max_alerts",
Parameter.REQUIRED, Parameter.REQUIRED,
new Integer(5)); new Integer(5));
// /////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////
// //
// Set of parameters which specify a new content section // Set of parameters which specify a new content section
@ -185,37 +168,20 @@ public final class ContentSectionConfig extends AbstractConfig {
// startups) parameters are ignored and not processed. // startups) parameters are ignored and not processed.
// //
// /////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////
/** /**
* The name of a new content section to be create during next boot of the * Staff Group Contains roles and associated privileges. In loading step a complete default
* system. During subsequent startups, when the section to be created * configuration is persisted in database, immutable at this point. See
* already exists, the parameter is ignored and processing skipped. * contentsection.ContentSectionSetup.registerRoles() In enterprise.init: name roles, List of
* roles to create.
* *
* Empty by default so no processing will take place. * ** Not implemented yet! ** We need a new parameter type "list" which must have
*/ * multidimensional capabilities.
private final Parameter
m_newContentSectionName = new StringParameter(
"com.arsdigita.cms.section.new_section_name",
Parameter.OPTIONAL,
null);
/**
* Staff Group
* Contains roles and associated privileges. 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.
*
* ** Not implemented yet! **
* We need a new parameter type "list" which must have multidimensional
* capabilities.
*/ */
// private final StringParameter // private final StringParameter
// m_staffGroup = new StringParameter( // m_staffGroup = new StringParameter(
// "com.arsdigita.cms.loader.section_staff_group", // "com.arsdigita.cms.loader.section_staff_group",
// Parameter.REQUIRED, // Parameter.REQUIRED,
// null); // null);
// 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.
@ -224,8 +190,7 @@ public final class ContentSectionConfig extends AbstractConfig {
* *
* 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.section.is_public", "com.arsdigita.cms.section.is_public",
Parameter.REQUIRED, Parameter.REQUIRED,
true); true);
@ -233,92 +198,75 @@ public final class ContentSectionConfig extends AbstractConfig {
/** /**
* List of content types to register in the given content-section. * List of content types to register in the given content-section.
* *
* Example: * Example: { "com.arsdigita.cms.contenttypes.Address",
* { * "com.arsdigita.cms.contenttypes.Article", "com.arsdigita.cms.contenttypes.Contact" }
* "com.arsdigita.cms.contenttypes.Address",
* "com.arsdigita.cms.contenttypes.Article",
* "com.arsdigita.cms.contenttypes.Contact"
* }
* *
* Parameter name "TYPES" in the old initializer code, empty by default in * Parameter name "TYPES" in the old initializer code, empty by default in the former
* the former enterprise.init file. * enterprise.init file. When the list is empty and the first default content section is
* When the list is empty and the first default content section is created, * created, all installed content types will get registered. This behaviour should not be
* all installed content types will get registered. This behaviour should * altered without very good reasons.
* not be altered without very good reasons.
*/ */
private final Parameter private final Parameter m_contentTypeList = new StringArrayParameter(
m_contentTypeList = new StringArrayParameter(
"com.arsdigita.cms.section.ctypes_list", "com.arsdigita.cms.section.ctypes_list",
Parameter.REQUIRED, Parameter.REQUIRED,
new String[]{}); new String[]{});
// 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
* <pre>com.arsdigita.cms.dispatcher.MultilingualItemResolver</pre>). * <pre>com.arsdigita.cms.dispatcher.MultilingualItemResolver</pre>).
* *
* 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
* Section-specific override can be added here. Only do so if you are * added here. Only do so if you are changing from the default for a specific content section.
* changing from the default for a specific content section. The class * The class must implement
* must implement <pre>com.arsdigita.cms.dispatcher.ItemResolver</pre>. * <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
* Description: The ItemResolver class to use for the section * ItemResolver class to use for the section (defaults to MultilingualItemResolver)
* (defaults to MultilingualItemResolver)
*/ */
private final Parameter private final Parameter m_itemResolverClass = new StringParameter(
m_itemResolverClass = new StringParameter(
"com.arsdigita.cms.section.item_resolver_class", "com.arsdigita.cms.section.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
* Section-specific override can be added here. Only do so if you are * be added here. Only do so if you are changing from the default for a specific content
* changing from the default for a specific content section. The class * section. The class must implement
* must implement <pre>com.arsdigita.cms.dispatcher.TemplateResolver</pre>. * <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.section.template_resolver_class", "com.arsdigita.cms.section.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
* false, so standard navigation is used. * navigation is used. If set to true loader loads the categories from file(s) specified in the
* If set to true loader loads the categories from file(s) specified in the
* next parameter ( m_categoryFileList ) * next parameter ( m_categoryFileList )
*/ */
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, 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. Usually not loaded {
* Usually not loaded {@see m_useSectionCategories). The files listed as *
* default values are demo material and must be replaced in a production * @see m_useSectionCategories). The files listed as default values are demo material and must
* environment. * be replaced in a production environment.
*/ */
private final Parameter private final Parameter m_categoryFileList = new StringArrayParameter(
m_categoryFileList = new StringArrayParameter(
"com.arsdigita.cms.section.categories_toload", "com.arsdigita.cms.section.categories_toload",
Parameter.REQUIRED, Parameter.REQUIRED,
new String[]{"/WEB-INF/resources/article-categories.xml", new String[]{"/WEB-INF/resources/article-categories.xml",
@ -331,7 +279,6 @@ public final class ContentSectionConfig extends AbstractConfig {
// List.class, // List.class,
// Collections.EMPTY_LIST); // Collections.EMPTY_LIST);
/** /**
* Constructor, do not instantiate this class directly! * Constructor, do not instantiate this class directly!
* *
@ -346,8 +293,6 @@ public final class ContentSectionConfig extends AbstractConfig {
register(m_alertInterval); register(m_alertInterval);
register(m_maxAlerts); register(m_maxAlerts);
// parameters for creation of a new (additional) content section
register(m_newContentSectionName);
// register(m_staffGroup); NOT IMPLEMENTED yet // register(m_staffGroup); NOT IMPLEMENTED yet
register(m_isPublic); register(m_isPublic);
register(m_itemResolverClass); register(m_itemResolverClass);
@ -358,22 +303,19 @@ public final class ContentSectionConfig extends AbstractConfig {
} }
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// //
// Processing of parameters which handle overdue notification // Processing of parameters which handle overdue notification
// //
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
/** /**
* Retrieve the list of workflow tasks and events for each tasks which * Retrieve the list of workflow tasks and events for each tasks which should receive overdue
* should receive overdue notification alerts * notification alerts
*/ */
public final String[] getTaskAlerts() { public final String[] getTaskAlerts() {
return (String[]) get(m_taskAlerts); return (String[]) get(m_taskAlerts);
} }
/** /**
* Retrieve whether to send overdue information for unfinished tasks. * Retrieve whether to send overdue information for unfinished tasks.
*/ */
@ -382,31 +324,27 @@ public final class ContentSectionConfig extends AbstractConfig {
} }
/** /**
* Retrieve time between when a task is enabled and when it is considered * Retrieve time between when a task is enabled and when it is considered overdue.
* overdue.
*/ */
public Integer getTaskDuration() { public Integer getTaskDuration() {
return ((Integer) get(m_taskDuration)).intValue(); return ((Integer) get(m_taskDuration)).intValue();
} }
/** /**
* Retrieve the time to wait between sending successive alerts on the same * Retrieve the time to wait between sending successive alerts on the same overdue task (in
* overdue task (in HOURS). * HOURS).
*/ */
public Integer getAlertInterval() { public Integer getAlertInterval() {
return (Integer) get(m_alertInterval); return (Integer) get(m_alertInterval);
} }
/** /**
* Retrieve the maximum number of alerts to send that a single task is * Retrieve the maximum number of alerts to send that a single task is overdue
* overdue
*/ */
public Integer getMaxAlerts() { public Integer getMaxAlerts() {
return (Integer) get(m_maxAlerts); return (Integer) get(m_maxAlerts);
} }
// /////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////
// //
// Processing of parameters which specify a new content // Processing of parameters which specify a new content
@ -415,49 +353,33 @@ public final class ContentSectionConfig extends AbstractConfig {
// exists and skip processing. // exists and skip processing.
// //
// /////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////
/** /**
* Retrieve the name of a new content-section to create. * 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).
* *
* The initializer has to check if it already exists and skip processing. * 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 String getNewContentSectionName() {
return (String) get(m_newContentSectionName);
}
/**
* 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.
*/
/** /**
* Changed: The forth field is not used anymore * Changed: The forth field is not used anymore
* *
@ -487,35 +409,50 @@ public final class ContentSectionConfig extends AbstractConfig {
m_defaultRoles = new ArrayList(); m_defaultRoles = new ArrayList();
m_defaultRoles.add m_defaultRoles.add(new ArrayList() {
( new ArrayList() {{ add("Author"); {
add("Author");
add("Creates new content"); add("Creates new content");
add(AUTH_PRIVS); add(AUTH_PRIVS);
}} }
}
); );
m_defaultRoles.add m_defaultRoles.add(new ArrayList() {
( new ArrayList() {{ add("Editor"); {
add("Editor");
add("Reviews and approves the author's work"); add("Reviews and approves the author's work");
add(EDIT_PRIVS); add(EDIT_PRIVS);
}} }
}
); );
m_defaultRoles.add m_defaultRoles.add(new ArrayList() {
( new ArrayList() {{ add("Publisher"); {
add("Publisher");
add("Deploys the content to the web site"); add("Deploys the content to the web site");
add(PUBL_PRIVS); add(PUBL_PRIVS);
}} }
}
); );
m_defaultRoles.add m_defaultRoles.add(new ArrayList() {
( new ArrayList() {{ add("Manager"); {
add("Manager");
add("Manages the overall content section"); add("Manages the overall content section");
add(MNGR_PRIVS); add(MNGR_PRIVS);
}} }
}
); );
m_defaultRoles.add m_defaultRoles.add(new ArrayList() {
( new ArrayList() {{ add("Trusted User"); {
add("Trusted User");
add("A trusted user is allowed to create and publish items without review"); add("A trusted user is allowed to create and publish items without review");
add(TRST_PRIVS); add(TRST_PRIVS);
}} }
}
); );
return (List) m_defaultRoles; return (List) m_defaultRoles;
@ -530,88 +467,156 @@ public final class ContentSectionConfig extends AbstractConfig {
// Prodcution Workflow // Prodcution Workflow
m_defaultWorkflows.add( m_defaultWorkflows.add(
new HashMap<String, Object>() {{ put("name", "Redigierte Veröffentlichung"); new HashMap<String, Object>() {
{
put("name", "Redigierte Veröffentlichung");
put("description", "A process that involves creating and approving content."); put("description", "A process that involves creating and approving content.");
put("isDefault", "true"); put("isDefault", "true");
put("tasks", put("tasks",
new ArrayList() {{ add( new ArrayList() {
new HashMap<String, Object>() {{ put("name", "Verfassen"); {
add(
new HashMap<String, Object>() {
{
put("name", "Verfassen");
put("description", "Create content."); put("description", "Create content.");
put("type", "Author"); put("type", "Author");
put("role", put("role",
new ArrayList<String>() {{ add("Author"); new ArrayList<String>() {
}} {
add("Author");
}
}
); );
}} }
}
); );
add( add(
new HashMap<String, Object>() {{ put("name", "Überprüfen"); new HashMap<String, Object>() {
{
put("name", "Überprüfen");
put("description", "Approve content."); put("description", "Approve content.");
put("type", "Edit"); put("type", "Edit");
put("role", put("role",
new ArrayList<String>() {{ add("Editor"); new ArrayList<String>() {
}} {
add("Editor");
}
}
); );
put("dependOn", put("dependOn",
new ArrayList<String>() {{ add("Verfassen"); new ArrayList<String>() {
}} {
add("Verfassen");
}
}
); );
}} }
}
); );
add( add(
new HashMap<String, Object>() {{ put("name", "Veröffentlichen"); new HashMap<String, Object>() {
{
put("name", "Veröffentlichen");
put("description", "Deploy content."); put("description", "Deploy content.");
put("type", "Deploy"); put("type", "Deploy");
put("role", put("role",
new ArrayList<String>() {{ add("Publisher"); new ArrayList<String>() {
}} {
add("Publisher");
}
}
); );
put("dependOn", put("dependOn",
new ArrayList<String>() {{ add("Überprüfen"); new ArrayList<String>() {
}} {
add("Überprüfen");
}
}
); );
}} }
}
); );
}} }
}
); );
}} }
}
); );
// TrustedUser Workflow // TrustedUser Workflow
m_defaultWorkflows.add( m_defaultWorkflows.add(
new HashMap<String, Object>() {{ put("name", "Direkte Veröffentlichung"); new HashMap<String, Object>() {
{
put("name", "Direkte Veröffentlichung");
put("description", "Create and publish content without review"); put("description", "Create and publish content without review");
put("isDefault", "false"); put("isDefault", "false");
put("tasks", put("tasks",
new ArrayList() {{ add( new ArrayList() {
new HashMap<String, Object>() {{ put("name", "Verfassen"); {
add(
new HashMap<String, Object>() {
{
put("name", "Verfassen");
put("description", "Create content."); put("description", "Create content.");
put("type", "Author"); put("type", "Author");
put("role", put("role",
new ArrayList<String>() {{ add("Author"); new ArrayList<String>() {
{
add("Author");
add("Trusted User"); add("Trusted User");
}} }
}
); );
}} }
}
); );
add( add(
new HashMap<String, Object>() {{ put("name", "Veröffentlichen"); new HashMap<String, Object>() {
{
put("name", "Veröffentlichen");
put("description", "Deploy content."); put("description", "Deploy content.");
put("type", "Deploy"); put("type", "Deploy");
put("role", put("role",
new ArrayList<String>() {{ add("Publisher"); new ArrayList<String>() {
{
add("Publisher");
add("Trusted User"); add("Trusted User");
}} }
}
); );
put("dependOn", put("dependOn",
new ArrayList<String>() {{ add("Verfassen"); new ArrayList<String>() {
}} {
add("Verfassen");
}
}
); );
}} }
}
); );
}} }
}
); );
}} }
}
); );
/* /*
// Addiditonal Workflows // Addiditonal Workflows
@ -644,8 +649,8 @@ public final class ContentSectionConfig extends AbstractConfig {
} }
/** /**
* Retrieve whether the content-section is publicly viewable (i.e. without * Retrieve whether the content-section is publicly viewable (i.e. without registration and
* registration and login) * login)
*/ */
public Boolean isPubliclyViewable() { public Boolean isPubliclyViewable() {
return ((Boolean) get(m_isPublic)).booleanValue(); return ((Boolean) get(m_isPublic)).booleanValue();
@ -665,10 +670,11 @@ public final class ContentSectionConfig extends AbstractConfig {
return (String) get(m_templateResolverClass); return (String) get(m_templateResolverClass);
} }
/** /**
* Retrieve whether to use section specific categories. If true they are * Retrieve whether to use section specific categories. If true they are loaded using the next
* loaded using the next parameters file list {@see getUseSectionCategories()} * 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
@ -678,9 +684,8 @@ public final class ContentSectionConfig extends AbstractConfig {
} }
/** /**
* Retrieve the list of files containing categories to load. * Retrieve the list of files containing categories to load. In old Initialiser: Parameter name:
* In old Initialiser: Parameter name: CATEGORIES * CATEGORIES Deskr. "XML file containing the category tree"
* Deskr. "XML file containing the category tree"
*/ */
public List getCategoryFileList() { public List getCategoryFileList() {
String[] catFiles = (String[]) get(m_categoryFileList); String[] catFiles = (String[]) get(m_categoryFileList);
@ -695,6 +700,4 @@ public final class ContentSectionConfig extends AbstractConfig {
return Arrays.asList(taskAlerts); return Arrays.asList(taskAlerts);
} }
} }

View File

@ -1,8 +1,3 @@
com.arsdigita.cms.contentsection.new_section_name.title=Name of a new content section to be created during next ccm startup.
com.arsdigita.cms.contentsection.new_section_name.purpose=Name of a new content section to be created during next ccm startup. Will be ignored if it already exists.
com.arsdigita.cms.contentsection.new_section_name.example=content
com.arsdigita.cms.contentsection.new_section_name.format=[string]
com.arsdigita.cms.contentsection.xxx.title= com.arsdigita.cms.contentsection.xxx.title=
com.arsdigita.cms.contentsection.xxx.purpose= com.arsdigita.cms.contentsection.xxx.purpose=
com.arsdigita.cms.contentsection.xxx.example=/default/item.jsp com.arsdigita.cms.contentsection.xxx.example=/default/item.jsp

View File

@ -16,8 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
package com.arsdigita.cms.contentsection; package com.arsdigita.cms.contentsection;
import com.arsdigita.cms.ContentSection; import com.arsdigita.cms.ContentSection;
@ -41,19 +39,15 @@ import java.util.Timer;
import java.util.Vector; import java.util.Vector;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* Initializes the content section sub-package of the CMS package (module). * Initializes the content section sub-package of the CMS package (module).
* *
* XXX Reformulate according to the code development! * XXX Reformulate according to the code development! This initializer performs: - check whether to
* This initializer performs: * create an additional content sections during restart - initializes alert preferences for each
* - check whether to create an additional content sections during restart * content section - initializes overdue alerts for each content section
* - initializes alert preferences for each content section
* - initializes overdue alerts for each content section
* *
* In the (hopefully) near future: * In the (hopefully) near future: Content section specific tasks of cms.Initializer will be moved
* Content section specific tasks of cms.Initializer will be moved into this * into this Initializer.
* Initializer.
* *
* *
* @author Daniel Berrange (berrange@redhat.com) * @author Daniel Berrange (berrange@redhat.com)
@ -63,19 +57,23 @@ import org.apache.log4j.Logger;
*/ */
public class Initializer extends CompoundInitializer { public class Initializer extends CompoundInitializer {
/**
/** Creates a s_logging category with name = to the full name of class */ * Creates a s_logging category with name = to the full name of class
*/
private static Logger s_log = Logger.getLogger(Initializer.class); private static Logger s_log = Logger.getLogger(Initializer.class);
/** Configuration object ContentSectionConfig containing parameters /**
which may be changed each system startup. */ * Configuration object ContentSectionConfig containing parameters which may be changed each
* system startup.
*/
private static final ContentSectionConfig s_conf = ContentSectionConfig private static final ContentSectionConfig s_conf = ContentSectionConfig
.getInstance(); .getInstance();
/** The Timer used to send Unfinished notifications */ /**
* The Timer used to send Unfinished notifications
*/
private static Vector s_unfinishedTimers = new Vector(); private static Vector s_unfinishedTimers = new Vector();
public Initializer() { public Initializer() {
//final String url = RuntimeConfig.getConfig().getJDBCURL(); //final String url = RuntimeConfig.getConfig().getJDBCURL();
//final int database = DbHelper.getDatabaseFromURL(url); //final int database = DbHelper.getDatabaseFromURL(url);
@ -89,10 +87,9 @@ public class Initializer extends CompoundInitializer {
// */ // */
// public void init(DataInitEvent evt) { // public void init(DataInitEvent evt) {
// } // }
/** /**
* Initializes domain-coupling machinery, usually consisting of * Initializes domain-coupling machinery, usually consisting of registering object instantiators
* registering object instantiators and observers. * and observers.
* *
* Here additionally checks whether to create a new content section. * Here additionally checks whether to create a new content section.
*/ */
@ -105,32 +102,27 @@ public class Initializer extends CompoundInitializer {
super.init(evt); super.init(evt);
/* Register object instantiator for ContentSection */ /* Register object instantiator for ContentSection */
evt.getFactory().registerInstantiator evt.getFactory().registerInstantiator(
(ContentSection.BASE_DATA_OBJECT_TYPE, ContentSection.BASE_DATA_OBJECT_TYPE,
new ACSObjectInstantiator() { new ACSObjectInstantiator() {
@Override @Override
public DomainObject doNewInstance(DataObject dobj) { public DomainObject doNewInstance(DataObject dobj) {
return new ContentSection(dobj); return new ContentSection(dobj);
} }
} );
// whether we have to create an additional (new) content section });
// specified in config file.
checkForNewContentSection();
s_log.debug("contentsection.Initializer.init(DomainInitEvent) completed"); s_log.debug("contentsection.Initializer.init(DomainInitEvent) completed");
} }
/** /**
* Implementation of the {@link Initializer#init(ContextInitEvent)} * Implementation of the {@link Initializer#init(ContextInitEvent)} method.
* method.
* *
* Steps through all installed content sections and for each section * Steps through all installed content sections and for each section - initializes the alert
* - initializes the alert preferences * preferences - initializes the scheduler background thread to fire all alert events.
* - initializes the scheduler background thread to fire all alert events.
* *
* A delay value of 0 inhibits start of processing. * A delay value of 0 inhibits start of processing.
*
* @param evt The context init event. * @param evt The context init event.
*/ */
@Override @Override
@ -171,8 +163,7 @@ public class Initializer extends CompoundInitializer {
} }
/** /**
* Implementation of the {@link Initializer#init(ContextCloseEvent)} * Implementation of the {@link Initializer#init(ContextCloseEvent)} method.
* method.
* *
* Stops various background threads started during startup process. * Stops various background threads started during startup process.
*/ */
@ -196,52 +187,12 @@ public class Initializer extends CompoundInitializer {
s_log.debug("content section ContextCloseEvent completed"); s_log.debug("content section ContextCloseEvent completed");
} }
private void checkForNewContentSection() {
// Check here weather a new content section has to be created.
String newSectionName = s_conf.getNewContentSectionName();
if (newSectionName != null && !newSectionName.isEmpty() ) {
ContentSectionCollection sections=ContentSection.getAllSections();
sections.addEqualsFilter( Application.PRIMARY_URL,
"/" + newSectionName + "/" );
ContentSection section;
if( sections.next() ) {
// Section with the configured name already exists
s_log.warn( "Content section " + newSectionName +
" already exists, skipping creation task.\n" +
"You may delete the entry from configuration file.");
section = sections.getContentSection();
sections.close();
} else {
s_log.info( "Content section " + newSectionName + " in " +
" doesn't exist, creating it." );
TransactionContext txn = SessionManager.getSession()
.getTransactionContext();
txn.beginTxn();
ContentSectionSetup.setupContentSectionAppInstance
(newSectionName,
s_conf.getDefaultRoles(),
s_conf.getDefaultWorkflows(),
s_conf.isPubliclyViewable(),
s_conf.getItemResolverClass(),
s_conf.getTemplateResolverClass(),
s_conf.getContentSectionsContentTypes(),
s_conf.getUseSectionCategories(),
s_conf.getCategoryFileList()
);
txn.commitTxn();
}
}
}
/** /**
* Steps through a string array of tasks and associated alert events * Steps through a string array of tasks and associated alert events creating section specific
* creating section specific CMStasks from configuration file. * CMStasks from configuration file.
* *
* Note: Tasks are created on a per section base, but we have currently no * Note: Tasks are created on a per section base, but we have currently no way to store
* way to store different values for each section. So all sections are * different values for each section. So all sections are configured equal.
* configured equal.
* *
* @param section A section object * @param section A section object
* @param taskAlerts An array of tasks and associated events * @param taskAlerts An array of tasks and associated events
@ -266,13 +217,13 @@ public class Initializer extends CompoundInitializer {
} }
/** /**
* @param section content section for which notifier should be started * @param section content section for which notifier should be started
* @param sendOverdue * @param sendOverdue
* @param duration * @param duration
* @param alertInterval * @param alertInterval
* @param max * @param max
*
* @return * @return
*/ */
private Timer startNotifierTask(ContentSection section, private Timer startNotifierTask(ContentSection section,
@ -284,8 +235,8 @@ public class Initializer extends CompoundInitializer {
Timer unfinished = null; Timer unfinished = null;
if (sendOverdue.booleanValue()) { if (sendOverdue.booleanValue()) {
if (duration == null || alertInterval == null || max == null) { if (duration == null || alertInterval == null || max == null) {
s_log.info("Not sending overdue task alerts, " + s_log.info("Not sending overdue task alerts, "
"required initialization parameters were not specified"); + "required initialization parameters were not specified");
return null; return null;
} }
// start the Timer as a daemon, so it doesn't keep the JVM from exiting // start the Timer as a daemon, so it doesn't keep the JVM from exiting
@ -297,8 +248,7 @@ public class Initializer extends CompoundInitializer {
max.intValue()); max.intValue());
// schedule the Task to start in 5 minutes, at 1 hour intervals // schedule the Task to start in 5 minutes, at 1 hour intervals
unfinished.schedule(notifier, 5L * 60 * 1000, 60L * 60 * 1000); unfinished.schedule(notifier, 5L * 60 * 1000, 60L * 60 * 1000);
s_log.info("Sending overdue alerts for tasks greater than " + s_log.info("Sending overdue alerts for tasks greater than " + duration + " hours old");
duration + " hours old");
} else { } else {
s_log.info("Not sending overdue task alerts"); s_log.info("Not sending overdue task alerts");
} }