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;
import com.arsdigita.cms.contentsection.ContentSectionConfig;
import com.arsdigita.cms.contentsection.ContentSectionSetup;
import com.arsdigita.cms.util.Util;
import com.arsdigita.cms.contenttypes.XMLContentTypeHandler;
import com.arsdigita.cms.portlet.ContentDirectoryPortlet;
import com.arsdigita.cms.portlet.ContentItemPortlet;
import com.arsdigita.cms.portlet.ContentSectionsPortlet;
import com.arsdigita.cms.portlet.TaskPortlet;
import com.arsdigita.cms.util.Util;
import com.arsdigita.formbuilder.util.FormbuilderSetup;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion;
@ -38,35 +39,31 @@ import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.web.Application;
import com.arsdigita.web.ApplicationType;
import com.arsdigita.xml.XML;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
/**
* <p>Executes nonrecurring at install time and loads (installs and initializes)
* the Content Management System module,including the Content Center, CMS Service
* applications, and CMS Mime Types service persistently into database.</p>
* the Content Management System module,including the Content Center, CMS
* Service applications, and CMS Mime Types service persistently into
* database.</p>
*
* <p>This class also optionally initializes user-defined content types. </p>
* <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>
* <ol>
* <li>create CMS package type(content-section)</li>
* <li>create Workspace package type and instance</li>
* <li>create CMS Service package type and instance</li>
* <li>create CMS package (content-section) instance</li>
* </ol>
* <p>The tasks to perform are:</p> <ol> <li>create CMS package
* type(content-section)</li> <li>create Workspace package type and
* instance</li> <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,
* otherwise hardcoded default values take effect. After processing, the
* installation values can not be modified anymore without a fresh installation
* of the whole system.</p>
* <p>Configuration can be modified by configuration parameters before
* processing, otherwise hardcoded default values take effect. After processing,
* the installation values can not be modified anymore without a fresh
* installation of the whole system.</p>
*
* @author Peter Boy &lt;pboy@barkhof.uni-bremen.de&gt;
* @since ccm-cms version 6.6.0
@ -74,21 +71,21 @@ import org.apache.log4j.Logger;
*/
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);
/** Loader configuration object, singleton design pattern
* NOTE: LoaderConfig only supplies unmutable hard coded defaults! It is
* not possible to alter any of the contained values by specifiying an
* configuration parameter during load step. If a configuration value
* has to be configurable at load time, the parameter must be relocated
* into this Loader class! */
/**
* Loader configuration object, singleton design pattern NOTE: LoaderConfig
* only supplies unmutable hard coded defaults! It is not possible to alter
* any of the contained values by specifiying an configuration parameter
* during load step. If a configuration value has to be configurable at load
* time, the parameter must be relocated into this Loader class!
*/
private static final LoaderConfig s_conf = LoaderConfig.getInstance();
// ///////////////////////////////////////////////////////////////////
// Configurable parameters during load step.
// ///////////////////////////////////////////////////////////////////
/**
* 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
@ -98,15 +95,14 @@ public class Loader extends PackageLoader {
private final Parameter m_contentSectionNames = new StringArrayParameter(
"com.arsdigita.cms.loader.section_names",
Parameter.REQUIRED,
new String[] {"content"}
);
/** List of classnames of internal base content types (needed in every
new String[]{"content"});
/**
* List of classnames of internal base content types (needed in every
* 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();
/**
* Standard constructor.
*/
@ -165,22 +161,22 @@ public class Loader extends PackageLoader {
/**
* Loads the Workspace subpackage (content-center) into the database.
*
* It is made public to be able to invoke it from the update script
* (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating
* It is made public to be able to invoke it from the update script (e.g.
* 6.6.1-6.6.2). We need separate steps for loading and instantiating
* because update skript requires.
*/
public static ApplicationType loadWorkspaceApplicationType() {
s_log.debug("Creating CMS Workspace...");
/* Create new type legacy free application type
* NOTE: The wording in the title parameter of ApplicationType
* determines the name of the subdirectory for the XSL stylesheets.
* It gets "urlized", i.e. trimming leading and trailing blanks and
* replacing blanks between words and illegal characters with an
* hyphen and converted to lower case.
* "Content Center" will become "content-center". */
ApplicationType type = new
ApplicationType(Workspace.INSTANCE_NAME,
/*
* Create new type legacy free application type NOTE: The wording in the
* title parameter of ApplicationType determines the name of the
* subdirectory for the XSL stylesheets. It gets "urlized", i.e.
* trimming leading and trailing blanks and replacing blanks between
* words and illegal characters with an hyphen and converted to lower
* case. "Content Center" will become "content-center".
*/
ApplicationType type = new ApplicationType(Workspace.INSTANCE_NAME,
Workspace.BASE_DATA_OBJECT_TYPE);
type.setDescription("The content center workspace for content creators.");
@ -193,8 +189,8 @@ public class Loader extends PackageLoader {
/**
* Instantiates the Workspace subpackage (content-center) (in the database).
*
* It is made public to be able to invoke it from the update script
* (e.g. 6.6.1-6.6.2). We need separate steps for loading and instantiating
* It is made public to be able to invoke it from the update script (e.g.
* 6.6.1-6.6.2). We need separate steps for loading and instantiating
* because update skript requires.
*
* @param workspaceType
@ -220,23 +216,22 @@ public class Loader extends PackageLoader {
s_log.debug("Done loading CMS Workspace.");
}
/**
* CMS Service application is used by the Content Management System as a
* store for global resources and assets.
* It is made public to be able to invoke it from the update script
* (e.g. 6.6.1-6.6.2).
* store for global resources and assets. It is made public to be able to
* invoke it from the update script (e.g. 6.6.1-6.6.2).
*/
public static ApplicationType loadServiceApplicationType() {
s_log.debug("Loading CMS Servce Package...");
/* Create new type legacy free application type
* NOTE: The wording in the title parameter of ApplicationType
* determines the name of the subdirectory for the XSL stylesheets.
* It gets "urlized", i.e. trimming leading and trailing blanks and
* replacing blanks between words and illegal characters with an
* hyphen and converted to lower case.
* "CMS Service" will become "cms-service". */
/*
* Create new type legacy free application type NOTE: The wording in the
* title parameter of ApplicationType determines the name of the
* subdirectory for the XSL stylesheets. It gets "urlized", i.e.
* trimming leading and trailing blanks and replacing blanks between
* words and illegal characters with an hyphen and converted to lower
* case. "CMS Service" will become "cms-service".
*/
ApplicationType type = new ApplicationType("CMS Service",
Service.BASE_DATA_OBJECT_TYPE);
type.setDescription("Services to store global resources and assets.");
@ -245,7 +240,6 @@ public class Loader extends PackageLoader {
return type;
}
/**
*
* @param serviceType
@ -265,13 +259,11 @@ public class Loader extends PackageLoader {
s_log.debug("Done creating CMS Service Package.");
}
/**
* Load a content section application type and an initial default
* content-section instance(s).
* Some configuration values which are to be considered as unmutable are
* specified in LoaderConfig.
* Uses new style application in legacy compatible mode.
* content-section instance(s). Some configuration values which are to be
* considered as unmutable are specified in LoaderConfig. Uses new style
* application in legacy compatible mode.
*
* 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
@ -286,13 +278,14 @@ public class Loader extends PackageLoader {
// Step 1: Create content section application type
// prerequisite for concrete content-section instance creation.
/* Create legacy-free application type
* NOTE: The wording in the title parameter of ApplicationType
* determines the name of the subdirectory for the XSL stylesheets.
* It gets "urlized", i.e. trimming leading and trailing blanks and
* replacing blanks between words and illegal characters with an
* hyphen and converted to lower case.
* "Content Section" will become "content-section". */
/*
* Create legacy-free application type NOTE: The wording in the title
* parameter of ApplicationType determines the name of the subdirectory
* for the XSL stylesheets. It gets "urlized", i.e. trimming leading and
* trailing blanks and replacing blanks between words and illegal
* characters with an hyphen and converted to lower case. "Content
* Section" will become "content-section".
*/
ApplicationType type = new ApplicationType(
"Content Section",
ContentSection.BASE_DATA_OBJECT_TYPE);
@ -314,65 +307,19 @@ public class Loader extends PackageLoader {
// Step 1: Validate name for section
Util.validateURLParameter("name", sectionName);
// Step 2: Create a section using default values
ContentSection section = ContentSection.create(sectionName);
ContentSectionConfig conf = new ContentSectionConfig();
conf.load();
// Step 3: Adopt the created section to site specific requirements
// ContentSectionSetup is a convenient class to adopt a
// section created by ContentSection.create()
ContentSectionSetup setup = new ContentSectionSetup(section);
ContentSectionSetup.setupContentSectionAppInstance(sectionName,
conf.getDefaultRoles(),
conf.getDefaultWorkflows(),
s_conf.isPubliclyViewable(),
s_conf.getItemResolverClass(),
s_conf.getTemplateResolverClass(),
m_content_type_list,
s_conf.getUseSectionCategories(),
s_conf.getCategoryFileList());
// Step 3a: Roles (staff group) used in this content section.
// 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)
}
}
@ -383,11 +330,11 @@ public class Loader extends PackageLoader {
* content type packages.
*
* The XML config looks like the example below, the "parentType" and "name"
* attributes are optional, and only required for creating
* User Defined ContentTypes. Label corresponds to ContentType's label and
* can be multiple words, and "name" to DynamicObject's name property,
* and must be a single word. The objectType attribute is ignored for
* UDCTs, as it gets dynamically generated.
* attributes are optional, and only required for creating User Defined
* ContentTypes. Label corresponds to ContentType's label and can be
* multiple words, and "name" to DynamicObject's name property, and must be
* a single word. The objectType attribute is ignored for UDCTs, as it gets
* dynamically generated.
*
* <b>UDCT Copyright</b>
* <pre>

View File

@ -15,8 +15,6 @@
* with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.arsdigita.cms;
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.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import org.apache.log4j.Logger;
// IMPLEMENTATION NOTE
@ -36,8 +31,6 @@ import org.apache.log4j.Logger;
// initialization process and not yet completed. Functionality is
// basically OK so far, but code urgently needs cleaning up and a
// check for useful bits.
/**
* Container for various configuration parameters for ccm-cms package loader.
*
@ -47,34 +40,38 @@ import org.apache.log4j.Logger;
* to be modifiable must be included in Loader class itself!
*
* @author pb
* @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
* @version $Id: LoaderConfig.java $
*/
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 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;
/**
* 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() {
if (s_conf == null) {
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
* Load time!
* s_conf.load();
/*
* Parameters are not stored in registry nor modified by
* installation specification. It is not possible to process a
* config object at Load time! s_conf.load();
*/
}
return s_conf;
}
// /**
// * The name of the workspace package instance, i.e. URL of the workspace,
// * 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",
// Parameter.REQUIRED,
// "content-center");
// /**
// * XML Mapping of the content center tabs to URLs, see
// * {@link ContentCenterDispatcher}
@ -105,7 +101,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.content_center_map",
// Parameter.REQUIRED,
// "/WEB-INF/resources/content-center-map.xml");
// Update master object if upgrading from old versioning
// XXX: shouldn't we just gut this section (and
// VersioningUpgrader)? It is an upgrade fix from 5.1 or
@ -118,7 +113,6 @@ public final class LoaderConfig extends AbstractConfig {
// if (updateMaster) {
// VersioningUpgrader.updateMasterObject();
// }
// XXX: ItemDispatcher is no longer used. Is the following
// still a valid enterprise.init parameter? Do we need to
// set ContentSectionServlet.s_cacheItems instead of the
@ -128,21 +122,18 @@ public final class LoaderConfig extends AbstractConfig {
// ((Boolean)m_conf.getParameter(CACHE_ITEMS)).booleanValue();
// s_log.debug("Set cache items to " + cacheItems);
// ItemDispatcher.setCacheItems(cacheItems);
/**
* Comma separated list of XML definition files for internal content types
* (base types).
*
* 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
* into permanent storage (equivalent to the Loader of each external
* content type package).
* requires an entry in this list in order to get CMS Loader to load it into
* permanent storage (equivalent to the Loader of each external content type
* package).
*
* Each definition file name has to be fully qualified relative to
* application (context) root.
* Example:
* contentTypeDefinitions = { "/WEB-INF/content-types/Template.xml" };
* application (context) root. Example: contentTypeDefinitions = {
* "/WEB-INF/content-types/Template.xml" };
*
* This parameter should be altered only by developers!
*/
@ -157,10 +148,7 @@ public final class LoaderConfig extends AbstractConfig {
"/WEB-INF/content-types/GenericContact.xml",
"/WEB-INF/content-types/GenericOrganizationalUnit.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.
@ -168,50 +156,38 @@ public final class LoaderConfig extends AbstractConfig {
// We list all information here, the code needs to create a section.
//
// ///////////////////////////////////////////////////////////////////////
// Section Name, configured by Loader parameter
// Root Folder, set autonomously by ContentSection.create() method
// Template Folder, set autonomously by ContentSection.create() method
/**
* 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.
* 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 Parameter
m_staffGroup = new StringParameter(
"com.arsdigita.cms.loader.section_staff_group",
Parameter.REQUIRED,
null);
* private final Parameter m_staffGroup = new StringParameter(
* "com.arsdigita.cms.loader.section_staff_group", Parameter.REQUIRED,
* null);
*/
private List m_staffGroup;
private List m_defaultRoles;
// Viewer group, set autonomously by ContentSection.create() method. We can
// here specify, whether the first ( probalby only) content section should
// 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.
*/
private final BooleanParameter
m_isPublic = new BooleanParameter(
private final BooleanParameter m_isPublic = new BooleanParameter(
"com.arsdigita.cms.loader.section_is_public",
Parameter.REQUIRED,
true);
// Page Resolver Class, set autonomously by ContentSection.create() method.
// Item Resolver Class, configurable.
/**
* Name of the item resolver class to use for the section (defaults to
@ -220,79 +196,70 @@ public final class LoaderConfig extends AbstractConfig {
* Default value (site-wide) is handled via the parameter
* <pre>com.arsdigita.cms.default_item_resolver_class</pre>.
* Section-specific override can be added here. Only do so if you are
* changing from the default for a specific content section. The class
* must implement <pre>com.arsdigita.cms.dispatcher.ItemResolver</pre>.
* changing from the default for a specific content section. The class must
* implement
* <pre>com.arsdigita.cms.dispatcher.ItemResolver</pre>.
*
* Parameter name ITEM_RESOLVER_CLASS in the old initializer system.
* Description: The ItemResolver class to use for the section
* (defaults to MultilingualItemResolver)
* Description: The ItemResolver class to use for the section (defaults to
* MultilingualItemResolver)
*/
private final Parameter
m_itemResolverClass = new StringParameter(
private final Parameter m_itemResolverClass = new StringParameter(
"com.arsdigita.cms.loader.item_resolver_class",
Parameter.OPTIONAL, null);
// , "com.arsdigita.cms.dispatcher.MultilingualItemResolver"
// Template Resolver Class, configurable.
/**
* Name of the template resolver class to use for the section
* (defaults to <pre>com.arsdigita.cms.dispatcher.DefaultTemplateResolver</pre>)
* Name of the template resolver class to use for the section (defaults to
* <pre>com.arsdigita.cms.dispatcher.DefaultTemplateResolver</pre>)
*
* Default value (site-wide) is handled via the parameter
* <pre>com.arsdigita.cms.default_template_resolver_class</pre>.
* Section-specific override can be added here. Only do so if you are
* changing from the default for a specific content section. The class
* must implement <pre>com.arsdigita.cms.dispatcher.TemplateResolver</pre>.
* changing from the default for a specific content section. The class must
* implement
* <pre>com.arsdigita.cms.dispatcher.TemplateResolver</pre>.
*
* Parameter name TEMPLATE_RESOLVER_CLASS in the old initializer system.
*/
private final Parameter
m_templateResolverClass = new StringParameter(
private final Parameter m_templateResolverClass = new StringParameter(
"com.arsdigita.cms.loader.template_resolver_class",
Parameter.OPTIONAL,
null);
// "com.arsdigita.cms.dispatcher.DefaultTemplateResolver" );
// XML Generator Class, set autonomously by ContentSection.create() method.
/**
* Determins weather to use section specific category tree(s). Defaults to
* false, so standard navigation is used.
* If set to true loader loads the categories from file(s) specified in the
* next parameter ( m_categoryFileList )
* false, so standard navigation is used. If set to true loader loads the
* categories from file(s) specified in the next parameter (
* m_categoryFileList )
*/
private final Parameter
m_useSectionCategories = new BooleanParameter
("com.arsdigita.cms.loader.use_section_categories",
private final Parameter m_useSectionCategories = new BooleanParameter("com.arsdigita.cms.loader.use_section_categories",
Parameter.REQUIRED, new Boolean(false));
/**
* XML file containing the category tree to load for this content section.
* Usually not loaded {@see m_useSectionCategories). The files listed as
* default values are demo material and must be replaced in a production
* environment.
* Usually not loaded {
*
* @see m_useSectionCategories). The files listed as default values are demo
* material and must be replaced in a production environment.
*/
private final Parameter
m_categoryFileList = new StringArrayParameter(
private final Parameter m_categoryFileList = new StringArrayParameter(
"com.arsdigita.cms.loader.section_categories_toload",
Parameter.REQUIRED,
new String[]{"/WEB-INF/resources/article-categories.xml",
"/WEB-INF/resources/navigation-categories.xml"});
// private final Parameter
// m_widgetTypes = new StringArrayParameter(
// "com.arsdigita.cms.loader.widget_types",
// Parameter.REQUIRED,
// new String[] {"/WEB-INF/resources/article-categories.xml",
// "/WEB-INF/resources/navigation-categories.xml"} );
/** List of widgets used in applications forms. Each widget is described by
application indicator, widget name (singular & plural), model class name
and model ui class name. These are really not user or administrator
configurabel and therefore not implemented as ccm parameter. */
/**
* List of widgets used in applications forms. Each widget is described by
* application indicator, widget name (singular & plural), model class name
* and model ui class name. These are really not user or administrator
* configurabel and therefore not implemented as ccm parameter.
*/
private static List widgetTypes = Arrays.asList(
Arrays.asList("forms-cms", "Checkbox group", "Checkbox groups",
"com.arsdigita.formbuilder.PersistentCheckboxGroup",
@ -345,14 +312,14 @@ public final class LoaderConfig extends AbstractConfig {
"com.arsdigita.formbuilder.ui.editors.HorizontalRuleForm"),
Arrays.asList("forms-cms", "User Email Field", "User Email Fields",
"com.arsdigita.formbuilder.PersistentEmailField",
"com.arsdigita.formbuilder.ui.editors.EmailFieldForm")
);
/** List of process listeners used in applications forms. Each listener is
described by application indicator, process name (singular & plural),
action class name and action ui class name. These are really not user
or administrator configurabel and therefore not implemented as ccm
parameter. */
"com.arsdigita.formbuilder.ui.editors.EmailFieldForm"));
/**
* List of process listeners used in applications forms. Each listener is
* described by application indicator, process name (singular & plural),
* action class name and action ui class name. These are really not user or
* administrator configurabel and therefore not implemented as ccm
* parameter.
*/
private static List processListenerTypes = Arrays.asList(
Arrays.asList("forms-cms", "Confirmation email",
"Confirmation emails",
@ -373,39 +340,30 @@ public final class LoaderConfig extends AbstractConfig {
"com.arsdigita.formbuilder.ui.editors.RemoteServerPostForm"),
Arrays.asList("forms-cms", "XML email", "XML emails",
"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",
"List of all registered users"),
Arrays.asList("forms-cms",
"com.arsdigita.formbuilder.DataQueryPackages",
"List of all installed packages")
);
"List of all installed packages"));
// Currently not a Loader task. There is no way to persist tasks preferences
// on a per section base.
/**
* When to generate email alerts: by default, generate email alerts
* on enable, finish, and rollback (happens on rejection) changes.
* There are four action types for each task type: enable,
* disable, finish, and rollback. Note that the values below are
* based on the task labels, and as such are not globalized.
* When to generate email alerts: by default, generate email alerts on
* enable, finish, and rollback (happens on rejection) changes. There are
* four action types for each task type: enable, disable, finish, and
* rollback. Note that the values below are based on the task labels, and as
* such are not globalized.
*/
/*
private final Parameter
m_taskAlerts = new StringArrayParameter(
"com.arsdigita.cms.task_alerts",
Parameter.REQUIRED, new String[] {
"Authoring:enable:finish:rollback",
"Approval:enable:finish:rollback",
"Deploy:enable:finish:rollback" } );
* private final Parameter m_taskAlerts = new StringArrayParameter(
* "com.arsdigita.cms.task_alerts", Parameter.REQUIRED, new String[] {
* "Authoring:enable:finish:rollback", "Approval:enable:finish:rollback",
* "Deploy:enable:finish:rollback" } );
*/
// ///////////////////////////////////////////////////////////////////////
//
// 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
// currently not a loader task and commented out here.
// ///////////////////////////////////////////////////////////////////////
// /**
// * 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",
// Parameter.REQUIRED,
// new Boolean(false) );
// /**
// * taskDuration: The time between when a task is enabled (it is made
// * available for completion) and when it is
@ -435,7 +390,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.task_duration",
// Parameter.REQUIRED,
// new Integer(96) );
// /**
// * alertInterval: The time to wait between sending successive alerts on
// * the same overdue task (in HOURS)
@ -445,7 +399,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.overdue_alert_interval",
// Parameter.REQUIRED,
// new Integer(24) );
// /**
// * maxAlerts: The maximum number of alerts to send about any one
// * overdue task
@ -455,7 +408,6 @@ public final class LoaderConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.mas_alerts",
// Parameter.REQUIRED,
// new Integer(5) );
/**
* Standard Constructor.
*/
@ -492,7 +444,6 @@ public final class LoaderConfig extends AbstractConfig {
// Getter Methods
//
// //////////////////////////
// Not used as long as we use old style application (seee above)
// /**
// * 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() {
// return (String) get(m_workspaceURL);
// }
// 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
@ -511,101 +461,11 @@ public final class LoaderConfig extends AbstractConfig {
// public String getContentCenterMap() {
// return (String) get(m_contentCenterMap);
// }
public List getCTDefFiles() {
String[] ctDefFiles = (String[]) get(m_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
* registration and login)
@ -628,10 +488,11 @@ public final class LoaderConfig extends AbstractConfig {
return (String) get(m_templateResolverClass);
}
/**
* 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.
* @return
@ -641,9 +502,9 @@ public final class LoaderConfig extends AbstractConfig {
}
/**
* Retrieve the list of files containing categories to load.
* In old Initialiser: Parameter name: CATEGORIES
* Deskr. "XML file containing the category tree"
* Retrieve the list of files containing categories to load. In old
* Initialiser: Parameter name: CATEGORIES Deskr. "XML file containing the
* category tree"
*/
public List getCategoryFileList() {
String[] catFiles = (String[]) get(m_categoryFileList);
@ -661,5 +522,4 @@ public final class LoaderConfig extends AbstractConfig {
public List getDataQueries() {
return dataQueries;
}
}

View File

@ -23,14 +23,12 @@ import com.arsdigita.runtime.AbstractConfig;
import com.arsdigita.util.parameter.BooleanParameter;
import com.arsdigita.util.parameter.IntegerParameter;
import com.arsdigita.util.parameter.Parameter;
//import com.arsdigita.util.parameter.ParameterError;
import com.arsdigita.util.parameter.StringArrayParameter;
import com.arsdigita.util.parameter.StringParameter;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
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
* changes during each startup of the system.
* @author pb
* @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
*/
public final class ContentSectionConfig extends AbstractConfig {
private List m_defaultRoles;
private List m_defaultWorkflows;
/** Private Logger instance for debugging purpose. */
private static final Logger s_log =
Logger.getLogger(ContentSectionConfig.class);
@ -216,7 +218,6 @@ public final class ContentSectionConfig extends AbstractConfig {
// "com.arsdigita.cms.loader.section_staff_group",
// Parameter.REQUIRED,
// null);
private List m_staffGroup;
// Viewer group, set autonomously by ContentSection.create() method. We can
@ -312,7 +313,7 @@ public final class ContentSectionConfig extends AbstractConfig {
private final Parameter
m_useSectionCategories = new BooleanParameter
("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.
@ -460,7 +461,12 @@ public final class ContentSectionConfig extends AbstractConfig {
* was burried in enterprise.init and not user available for configuration.
* 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(
"new_item","read_item", "preview_item", "edit_item",
@ -478,43 +484,169 @@ public final class ContentSectionConfig extends AbstractConfig {
"publish",
"staff_admin", "content_type_admin", "lifecycle_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");
add("Creates new content");
add(AUTH_PRIVS);
add("Authoring");
}}
);
m_staffGroup.add
m_defaultRoles.add
( new ArrayList() {{ add("Editor");
add("Reviews and approves the author's work");
add(EDIT_PRIVS);
add("Approval");
}}
);
m_staffGroup.add
m_defaultRoles.add
( new ArrayList() {{ add("Publisher");
add("Deploys the content to the web site");
add(PUBL_PRIVS);
add("Publishing");
}}
);
m_staffGroup.add
m_defaultRoles.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)
}}
);
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
* registration and login)

View File

@ -43,7 +43,6 @@ import com.arsdigita.util.Assert;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.workflow.simple.WorkflowTemplate;
import com.arsdigita.xml.XML;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -54,7 +53,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
@ -65,20 +63,21 @@ import org.xml.sax.helpers.DefaultHandler;
* into the database.
*
* @author Peter Boy (pboy@barkhof.uni-bremen.de)
* @author Sören Bernstein (quasi@barkhof.uni-bremen.de)
* @author Jon Orris (jorris@redhat.com)
* @version $Id: $
*/
public final class ContentSectionSetup {
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 WorkflowTemplate m_wf;
final ContentSection m_section;
/**
* Constructor. Using this constructor the content section has to be
* already created using ContentSection.create(name)
* Constructor. Using this constructor the content section has to be already
* created using ContentSection.create(name)
*
* @param section name of a content section previously created by
* ContentSection.create
@ -89,15 +88,16 @@ public final class ContentSectionSetup {
}
/**
* Wrapper class to create and configure a content section instance
* in one step.
* Wrapper class to create and configure a content section instance in one
* step.
*
* 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(
String name,
List staffGroup,
public static ContentSection setupContentSectionAppInstance(String name,
List defaultRoles,
List defaultWorkflows,
Boolean isPubliclyViewable,
String itemResolverClassName,
String templateResolverClassName,
@ -111,10 +111,10 @@ public final class ContentSectionSetup {
ContentSectionSetup setup = new ContentSectionSetup(section);
// Setup the access controls
setup.registerRoles(staffGroup);
setup.registerRoles(defaultRoles);
setup.registerWorkflows(defaultWorkflows);
setup.registerViewers(isPubliclyViewable);
setup.registerPublicationCycles();
setup.registerWorkflowTemplates();
setup.registerResolvers(itemResolverClassName, templateResolverClassName);
// setup.registerContentTypes((List)m_conf.getParameter(TYPES));
@ -131,7 +131,7 @@ public final class ContentSectionSetup {
section.save();
// return section;
return section;
}
@ -141,7 +141,7 @@ public final class ContentSectionSetup {
*
* @param roles
*/
public void registerRoles(List roles) {
public void registerRoles(List<List> roles) {
Iterator i = roles.iterator();
while (i.hasNext()) {
@ -150,23 +150,15 @@ public final class ContentSectionSetup {
String name = (String) role.get(0);
String desc = (String) role.get(1);
List privileges = (List) role.get(2);
String task = (role.size() > 3 ? (String) role.get(3) : null);
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);
}
}
}
/**
* Takes the characteristics of a role and persists them in the database.
*
@ -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;
}
@ -259,8 +260,8 @@ public final class ContentSectionSetup {
/**
* Checks for specific item resolver and template resolver classes probably
* specified in parameters, otherwise uses system wide default parameters
* specified in CMS global configuration file. Delegates persistence task
* to ContentSection.
* specified in CMS global configuration file. Delegates persistence task to
* ContentSection.
*
* @param itemResolverClassName
* @param templateResolverClassName
@ -274,8 +275,7 @@ public final class ContentSectionSetup {
s_log.info("Registering " + itemResolverClassName
+ " as the item resolver class");
} else {
m_section.setItemResolverClass(ContentSection.getConfig()
.getDefaultItemResolverClass().getName());
m_section.setItemResolverClass(ContentSection.getConfig().getDefaultItemResolverClass().getName());
s_log.info("Registering " + itemResolverClassName
+ " as the item resolver class");
}
@ -285,8 +285,7 @@ public final class ContentSectionSetup {
s_log.info("Registering " + templateResolverClassName
+ " as the template resolver class");
} else {
m_section.setTemplateResolverClass(ContentSection.getConfig()
.getDefaultTemplateResolverClass().getName());
m_section.setTemplateResolverClass(ContentSection.getConfig().getDefaultTemplateResolverClass().getName());
s_log.info("Registering " + templateResolverClassName
+ " as the template resolver class");
}
@ -323,86 +322,110 @@ public final class ContentSectionSetup {
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
* database.
*
* This one is probably deprecated.
*
* @throws InitializationException
*/
public void registerWorkflowTemplates()
throws ConfigError {
public void registerWorkflowTemplates() throws ConfigError {
// The 3-step production workflow.
WorkflowTemplate wf = new WorkflowTemplate();
wf.setLabel((String) GlobalizationUtil.globalize(
"cms.installer.production_workflow").localize());
wf.setDescription("A process that involves creating and approving content.");
wf.save();
ContentSectionConfig config = new ContentSectionConfig();
config.load();
registerWorkflows(config.getDefaultWorkflows());
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
* 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) {
@ -424,7 +447,8 @@ 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
* @return
@ -514,8 +538,7 @@ public final class ContentSectionSetup {
temp.save();
TemplateManagerFactory.getInstance()
.addTemplate(m_section, type, temp, "public");
TemplateManagerFactory.getInstance().addTemplate(m_section, type, temp, "public");
temp.publish(m_lcd, new Date());
}
@ -545,6 +568,8 @@ public final class ContentSectionSetup {
alert.setDescription(
"Receive alerts regarding expiration of pubished content");
alert.save();
}
// // Currently there is no way to persists alert preferemces, therefore
@ -679,6 +704,4 @@ public final class ContentSectionSetup {
}
}
} // END private class CategoryHandler
}

View File

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

View File

@ -19,56 +19,24 @@
package com.arsdigita.cms.workflow;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
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.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.messaging.Message;
import com.arsdigita.notification.Notification;
import com.arsdigita.persistence.DataAssociation;
import com.arsdigita.persistence.DataAssociationCursor;
import com.arsdigita.persistence.DataCollection;
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.Session;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.metadata.ObjectType;
import com.arsdigita.util.Assert;
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.HashSet;
import java.util.Iterator;
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
* the behaviour of tasks of that type
* This class represents a task type in the CMS system. The task type has
* attributes that impact on the behaviour of tasks of that type
*
*
* @author chris.gilbert at westsussex.gov.uk
@ -78,10 +46,7 @@ public class CMSTaskType extends DomainObject {
public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.cms.workflow.CMSTaskType";
private static Map s_taskURLGeneratorCache = new HashMap();
// pdl attribute names
public static final String ID = "taskTypeID";
public static final String NAME = "name";
@ -89,20 +54,28 @@ public class CMSTaskType extends DomainObject {
"defaultUrlGeneratorClass";
public static final String PRIVILEGE = "privilege";
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 s_taskTypes = new HashMap();
public static Map<Integer, CMSTaskType> s_taskTypes = new HashMap<Integer, CMSTaskType>();
private static Map<String, Integer> s_taskNameMap = new HashMap<String, Integer>();
static {
s_taskNameMap.put("Author", AUTHOR);
s_taskNameMap.put("Edit", EDIT);
s_taskNameMap.put("Deploy",DEPLOY);
}
public static CMSTaskType retrieve(Integer id) {
CMSTaskType type = (CMSTaskType)s_taskTypes.get(id);
if (id == null) {
throw new IllegalArgumentException("Parameter id must not be null");
}
CMSTaskType type = s_taskTypes.get(id);
if (type == null) {
type = new CMSTaskType(id);
s_taskTypes.put(id, type);
@ -110,6 +83,28 @@ public class CMSTaskType extends DomainObject {
return type;
}
public static CMSTaskType retrieveByName(String name) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Parameter name must not be null or empty");
}
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));
}
@ -119,7 +114,8 @@ public class CMSTaskType extends DomainObject {
}
/**
* create a message object and associate it with the current application instance
* create a message object and associate it with the current application
* instance
*
*/
public CMSTaskType() {
@ -170,8 +166,7 @@ public class CMSTaskType extends DomainObject {
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);
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();
@ -213,11 +208,12 @@ public class CMSTaskType extends DomainObject {
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
* 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) {
@ -225,9 +221,4 @@ public class CMSTaskType extends DomainObject {
s_taskURLGeneratorCache.remove(key);
}
}