From b396010920ce3e050becc6e740093d0470b05e8c Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 7 Mar 2014 06:52:42 +0000 Subject: [PATCH] Changed the column type for the abstract and misc properties of Publications from varchar(4096) to text. It also now possible to enable the HTML editor for the abstract and misc fields of publications. The default is still no HTML editor. git-svn-id: https://svn.libreccm.org/ccm/trunk@2558 8810af33-2d31-482b-a856-94f89814c4df --- .../cms/ui/authoring/GenericArticleBody.java | 81 +- ccm-core/src/ccm-core.config | 2 + ccm-core/src/com/arsdigita/bebop/Page.java | 2365 ++++++++--------- .../src/com/arsdigita/core/Initializer.java | 20 +- .../kernel/KernelConfig_parameter.properties | 10 +- .../com/arsdigita/util/SystemInformation.java | 146 +- ccm-sci-publications/application.xml | 2 +- .../arsdigita/content-types/Publication.pdl | 4 +- .../upgrade/6.6.6-6.6.7/abstract_to_text.sql | 3 + .../upgrade/postgres-6.6.6-6.6.7.sql | 8 + .../src/ccm-sci-publications.upgrade | 3 + .../cms/contenttypes/PublicationsConfig.java | 296 ++- .../PublicationsConfig_parameter.properties | 12 +- .../ui/PublicationPropertiesStep.java | 4 +- .../ui/PublicationPropertyForm.java | 63 +- 15 files changed, 1557 insertions(+), 1462 deletions(-) create mode 100644 ccm-sci-publications/sql/ccm-sci-publications/default/upgrade/6.6.6-6.6.7/abstract_to_text.sql create mode 100644 ccm-sci-publications/sql/ccm-sci-publications/upgrade/postgres-6.6.6-6.6.7.sql diff --git a/ccm-cms/src/com/arsdigita/cms/ui/authoring/GenericArticleBody.java b/ccm-cms/src/com/arsdigita/cms/ui/authoring/GenericArticleBody.java index f9619d686..ef075f410 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/authoring/GenericArticleBody.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/authoring/GenericArticleBody.java @@ -18,7 +18,6 @@ */ package com.arsdigita.cms.ui.authoring; - import com.arsdigita.bebop.Component; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.RequestLocal; @@ -34,14 +33,12 @@ import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.domain.DomainObject; import com.arsdigita.util.Assert; - /** - * Displays the current text body of the article and allows the user - * to edit it, by uploading a file or entering text in a textbox. + * Displays the current text body of the article and allows the user to edit it, by uploading a file + * or entering text in a textbox. * - * The {@link com.arsdigita.bebop.PropertySheet} class is often used - * as the display component in the default authoring kit steps of - * this class. + * The {@link com.arsdigita.bebop.PropertySheet} class is often used as the display component in the + * default authoring kit steps of this class. * * @author Stanislav Freidin (sfreidin@arsdigita.com) * @version $Id: GenericArticleBody.java 1949 2009-06-25 08:30:50Z terry $ @@ -54,12 +51,11 @@ public class GenericArticleBody extends TextAssetBody { /** * Construct a new GenericArticleBody component * - * @param itemModel The {@link ItemSelectionModel} which will - * be responsible for loading the current item + * @param itemModel The {@link ItemSelectionModel} which will be responsible for loading the + * current item * - * @param parent The parent wizard which contains the form. The form - * may use the wizard's methods, such as stepForward and stepBack, - * in its process listener. + * @param parent The parent wizard which contains the form. The form may use the wizard's + * methods, such as stepForward and stepBack, in its process listener. */ public GenericArticleBody(ItemSelectionModel itemModel, AuthoringKitWizard parent) { super(new ItemAssetModel(itemModel)); @@ -69,17 +65,18 @@ public class GenericArticleBody extends TextAssetBody { // Rest the component when it is hidden parent.getList().addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) { - PageState state = e.getPageState(); - reset(state); - } - }); + public void actionPerformed(ActionEvent e) { + PageState state = e.getPageState(); + reset(state); + } + + }); // Set the right component access on the forms Component f = getComponent(FILE_UPLOAD); if (f != null) { - setComponentAccess(FILE_UPLOAD, - new WorkflowLockedComponentAccess(f, itemModel)); + setComponentAccess(FILE_UPLOAD, + new WorkflowLockedComponentAccess(f, itemModel)); } Component t = getComponent(TEXT_ENTRY); setComponentAccess(TEXT_ENTRY, @@ -87,9 +84,10 @@ public class GenericArticleBody extends TextAssetBody { } /** - * Adds the options for the mime type select widget of - * GenericArticleForm and sets the default mime type. - **/ + * Adds the options for the mime type select widget of GenericArticleForm and sets + * the default mime type. + * + */ @Override protected void setMimeTypeOptions(SingleSelect mimeSelect) { mimeSelect.addOption(new Option("text/html", "HTML Text")); @@ -100,6 +98,7 @@ public class GenericArticleBody extends TextAssetBody { * Create a new text asset and associate it with the current item * * @param s the current page state + * * @return a valid TextAsset */ protected TextAsset createTextAsset(PageState s) { @@ -109,7 +108,7 @@ public class GenericArticleBody extends TextAssetBody { final int idLen = item.getID().toString().length(); final int len = nameLen + 6 + idLen; if (len < 200) { - t.setName(item.getName() + "_text_" + item.getID()); + t.setName(item.getName() + "_text_" + item.getID()); } else { t.setName(item.getName().substring(0, 200 - (len - 200)) + "_text_" + item.getID()); } @@ -120,8 +119,8 @@ public class GenericArticleBody extends TextAssetBody { } /** - * Set additional parameters of a brand new text asset, such as the - * parent ID, after the asset has been successfully uploaded + * Set additional parameters of a brand new text asset, such as the parent ID, after the asset + * has been successfully uploaded * * @param s the current page state * @param a the new TextAsset @@ -131,7 +130,7 @@ public class GenericArticleBody extends TextAssetBody { Assert.exists(t); // no need - cg. Text doesn't need a security context, // and ownership of text is recorded in text_pages - + // a.setParent(t); t.setTextAsset(a); a.save(); @@ -142,12 +141,11 @@ public class GenericArticleBody extends TextAssetBody { * Get the current GenericArticle */ protected GenericArticle getGenericArticle(PageState s) { - return (GenericArticle)m_itemModel.getSelectedObject(s); + return (GenericArticle) m_itemModel.getSelectedObject(s); } /** - * An ACSObjectSelectionModel that selects the current text asset for - * the text page + * An ACSObjectSelectionModel that selects the current text asset for the text page */ private static class ItemAssetModel extends ItemSelectionModel { @@ -158,25 +156,26 @@ public class GenericArticleBody extends TextAssetBody { m_asset = new RequestLocal() { @Override - protected Object initialValue(PageState s) { - GenericArticle t = (GenericArticle) - ((ItemSelectionModel)getSingleSelectionModel()) - .getSelectedObject(s); - Assert.exists(t); - return t.getTextAsset(); - } - }; + protected Object initialValue(PageState s) { + GenericArticle t + = (GenericArticle) ((ItemSelectionModel) getSingleSelectionModel()). + getSelectedObject(s); + Assert.exists(t); + return t.getTextAsset(); + } + + }; } @Override public Object getSelectedKey(PageState s) { - TextAsset a = (TextAsset)getSelectedObject(s); + TextAsset a = (TextAsset) getSelectedObject(s); return (a == null) ? null : a.getID(); } @Override public DomainObject getSelectedObject(PageState s) { - return (DomainObject)m_asset.get(s); + return (DomainObject) m_asset.get(s); } @Override @@ -186,13 +185,15 @@ public class GenericArticleBody extends TextAssetBody { @Override public void setSelectedKey(PageState s, Object key) { - throw new UnsupportedOperationException( (String) GlobalizationUtil.globalize("cms.ui.authoring.not_implemented").localize()); + throw new UnsupportedOperationException((String) GlobalizationUtil.globalize( + "cms.ui.authoring.not_implemented").localize()); } @Override public boolean isSelected(PageState s) { return (getSelectedObject(s) != null); } + } } diff --git a/ccm-core/src/ccm-core.config b/ccm-core/src/ccm-core.config index c58377fad..4af189723 100755 --- a/ccm-core/src/ccm-core.config +++ b/ccm-core/src/ccm-core.config @@ -34,6 +34,8 @@ storage="ccm-core/templating.properties"/> + The top-level container for all Bebop components and containers.

+ *

+ * The top-level container for all Bebop components and containers.

* - *
  • Holds references to the components of a page.
  • Provides - * methods for servicing requests and for notifying other components that a - * request for this page has been received through - * {@link ActionListener ActionListeners}.
  • + *
    • Holds references to the components of a page.
    • Provides methods for servicing + * requests and for notifying other components that a request for this page has been received + * through {@link ActionListener ActionListeners}.
    • * - *
    • Tracks request parameters for stateful components, such as tabbed panes - * and sortable tables.

    A typical - * Page may be created as follows: null

    
    + * 
  • Tracks request parameters for stateful components, such as tabbed panes and sortable + * tables.
+ *

+ * A typical Page may be created as follows: null


  * Page p = new Page("Hello World");
  * p.add(new Label("Hello World");
  * p.lock();
@@ -75,624 +76,604 @@ import org.apache.log4j.Logger;
  */
 public class Page extends BlockStylable implements Container {
 
-	/**
-	 * Class specific logger instance.
-	 */
-	private static final Logger s_log = Logger.getLogger(Page.class);
-	/**
-	 * The delimiter character for components naming
-	 */
-	private static final String DELIMITER = ".";
-	/**
-	 * The prefix that gets prepended to all state variables. Components
-	 * must not use variables starting with this prefix. This guarantees
-	 * that the page state and variables individual components wish to pass
-	 * do not interfere with each other.
-	 */
-	private static final String COMPONENT_PREFIX = "bbp" + DELIMITER;
-	private static final String INTERNAL = COMPONENT_PREFIX;
-	/**
-	 * The name of the special parameter that indicates which component has
-	 * been selected.
-	 */
-	static final String SELECTED = INTERNAL + "s";
-	static final String CONTROL_EVENT = INTERNAL + "e";
-	static final String CONTROL_VALUE = INTERNAL + "v";
-	static final Collection CONTROL_EVENT_KEYS;
+    /**
+     * Class specific logger instance.
+     */
+    private static final Logger s_log = Logger.getLogger(Page.class);
+    /**
+     * The delimiter character for components naming
+     */
+    private static final String DELIMITER = ".";
+    /**
+     * The prefix that gets prepended to all state variables. Components must not use variables
+     * starting with this prefix. This guarantees that the page state and variables individual
+     * components wish to pass do not interfere with each other.
+     */
+    private static final String COMPONENT_PREFIX = "bbp" + DELIMITER;
+    private static final String INTERNAL = COMPONENT_PREFIX;
+    /**
+     * The name of the special parameter that indicates which component has been selected.
+     */
+    static final String SELECTED = INTERNAL + "s";
+    static final String CONTROL_EVENT = INTERNAL + "e";
+    static final String CONTROL_VALUE = INTERNAL + "v";
+    static final Collection CONTROL_EVENT_KEYS;
 
-	static {
-		s_log.debug("Static initalizer is starting...");
-		CONTROL_EVENT_KEYS = new ArrayList(3);
-		CONTROL_EVENT_KEYS.add(SELECTED);
-		CONTROL_EVENT_KEYS.add(CONTROL_EVENT);
-		CONTROL_EVENT_KEYS.add(CONTROL_VALUE);
-		s_log.debug("Static initalizer finished.");
-	}
-	/**
-	 * The name of the request parameter used for the visibility state of
-	 * components stored in m_invisible.
-	 */
-	static final String INVISIBLE = INTERNAL + "i";
-	/**
-	 * Map of stateful components (id --> Component) SortedMap used because
-	 * component based hash for page is based on concatenation of component
-	 * ids, and so need to guarantee that they are returned in the same
-	 * order for the same page - cg.
-	 */
-	private SortedMap m_componentMap;
-	private List m_components;
-	/**
-	 * Map of component -> owned parameter collection
-	 */
-	private Map m_componentParameterMap = new HashMap();
-	private FormModel m_stateModel;
-	/**
-	 * Container that renders this
-	 * Page.
-	 */
-	protected Container m_panel;
-	private List m_actionListeners;
-	private List m_requestListeners;
-	/**
-	 * The title of the page to be added in the head of HTML output. The
-	 * title is wrapped in a Label to allow developers to add PrintListeners
-	 * to dynamically change the value of the title.
-	 */
-	private Label m_title;
-	/**
-	 * Stores the actual title for the current request. The title may be
-	 * generated with a PrintListener of the m_title Label.
-	 */
-	private RequestLocal m_currentTitle;
-	/**
-	 * A list of all the client-side stylesheets. The elements of the list
-	 * are of type Page.Stylesheet, defined at the end of this file.
-	 */
-	private List m_clientStylesheets;
-	private StringParameter m_selected;
-	private StringParameter m_controlEvent;
-	private StringParameter m_controlValue;
-	/**
-	 * The default (initial) visibility of components. The encoding is
-	 * identical to that for PageState.m_invisible.
-	 *
-	 * This variable is package-friendly since it needs to be accessed by
-	 * PageState.
-	 */
-	protected BitSet m_invisible;
-	/**
-	 * The PageErrorDisplay component that will display page state
-	 * validation errors on this page
-	 */
-	private Component m_errorDisplay;
-	/**
-	 * Indicates whether finish() has been called on this Page.
-	 */
-	private boolean m_finished = false;
-	/**
-	 * indicates whether pageState.stateAsURL() should export the entire
-	 * state for this page, or whether it should only export the control
-	 * event as a URL and use the HttpSession for the rest of the page
-	 * state.
-	 */
-	private boolean m_useHttpSession = false;
+    static {
+        s_log.debug("Static initalizer is starting...");
+        CONTROL_EVENT_KEYS = new ArrayList(3);
+        CONTROL_EVENT_KEYS.add(SELECTED);
+        CONTROL_EVENT_KEYS.add(CONTROL_EVENT);
+        CONTROL_EVENT_KEYS.add(CONTROL_VALUE);
+        s_log.debug("Static initalizer finished.");
+    }
 
-	/**
-	 * Returns
-	 * true if this page should export state through the
-	 * HttpSession instead of the URL query string. 

If this returns - * true, then PageState.stateAsURL() will only export the - * control event as a URL query string. If this returns - * false, then stateAsURL() will export the entire page - * state. - * - * - * @see PageState#stateAsURL - * - * @return true if this page should export state through - * the HttpSession; false if it should export using the URL - * query string. - */ - public boolean isUsingHttpSession() { - return m_useHttpSession; - } + /** + * The name of the request parameter used for the visibility state of components stored in + * m_invisible. + */ + static final String INVISIBLE = INTERNAL + "i"; + /** + * Map of stateful components (id --> Component) SortedMap used because component based hash for + * page is based on concatenation of component ids, and so need to guarantee that they are + * returned in the same order for the same page - cg. + */ + private SortedMap m_componentMap; + private List m_components; + /** + * Map of component -> owned parameter collection + */ + private Map m_componentParameterMap = new HashMap(); + private FormModel m_stateModel; + /** + * Container that renders this Page. + */ + protected Container m_panel; + private List m_actionListeners; + private List m_requestListeners; + /** + * The title of the page to be added in the head of HTML output. The title is wrapped in a Label + * to allow developers to add PrintListeners to dynamically change the value of the title. + */ + private Label m_title; + /** + * Stores the actual title for the current request. The title may be generated with a + * PrintListener of the m_title Label. + */ + private RequestLocal m_currentTitle; + /** + * A list of all the client-side stylesheets. The elements of the list are of type + * Page.Stylesheet, defined at the end of this file. + */ + private List m_clientStylesheets; + private StringParameter m_selected; + private StringParameter m_controlEvent; + private StringParameter m_controlValue; + /** + * The default (initial) visibility of components. The encoding is identical to that for + * PageState.m_invisible. + * + * This variable is package-friendly since it needs to be accessed by PageState. + */ + protected BitSet m_invisible; + /** + * The PageErrorDisplay component that will display page state validation errors on this page + */ + private Component m_errorDisplay; + /** + * Indicates whether finish() has been called on this Page. + */ + private boolean m_finished = false; + /** + * indicates whether pageState.stateAsURL() should export the entire state for this page, or + * whether it should only export the control event as a URL and use the HttpSession for the rest + * of the page state. + */ + private boolean m_useHttpSession = false; - /** - * Indicates to this page whether it should export its entire state to - * subsequent requests through the URL query string, or if it should use - * the HttpSession instead and only use the URL query string for the - * control event. - * - * @see PageState#stateAsURL - * - * @param b true if PageState.stateAsURL() will export only - * the control event as a URL query string. false if - * stateAsURL() will export the entire page state. - */ - public void setUsingHttpSession(boolean b) { - m_useHttpSession = b; - } + /** + * Returns true if this page should export state through the HttpSession instead of + * the URL query string. + *

+ * If this returns true, then PageState.stateAsURL() will only export the control + * event as a URL query string. If this returns false, then stateAsURL() will + * export the entire page state. + * + * + * @see PageState#stateAsURL + * + * @return true if this page should export state through the HttpSession; + * false if it should export using the URL query string. + */ + public boolean isUsingHttpSession() { + return m_useHttpSession; + } - /** - * Creates an empty page with the specified title and panel. - * - * @param title title for this page - * - * @param panel container for this page - */ - public Page(String title, Container panel) { - this(new Label(title), panel); - } + /** + * Indicates to this page whether it should export its entire state to subsequent requests + * through the URL query string, or if it should use the HttpSession instead and only use the + * URL query string for the control event. + * + * @see PageState#stateAsURL + * + * @param b true if PageState.stateAsURL() will export only the control event as a + * URL query string. false if stateAsURL() will export the entire page + * state. + */ + public void setUsingHttpSession(boolean b) { + m_useHttpSession = b; + } - /** - * Creates an empty page with the specified title and panel. - * - * @param title title for this page - * - * @param panel container for this page - */ - public Page(Label title, Container panel) { - super(); - m_actionListeners = new LinkedList(); - m_requestListeners = new LinkedList(); - m_panel = panel; - m_clientStylesheets = new ArrayList(); - m_components = new ArrayList(); - m_componentMap = new TreeMap(); - setErrorDisplay(new PageErrorDisplay()); - setTitle(title); + /** + * Creates an empty page with the specified title and panel. + * + * @param title title for this page + * + * @param panel container for this page + */ + public Page(String title, Container panel) { + this(new Label(title), panel); + } + + /** + * Creates an empty page with the specified title and panel. + * + * @param title title for this page + * + * @param panel container for this page + */ + public Page(Label title, Container panel) { + super(); + m_actionListeners = new LinkedList(); + m_requestListeners = new LinkedList(); + m_panel = panel; + m_clientStylesheets = new ArrayList(); + m_components = new ArrayList(); + m_componentMap = new TreeMap(); + setErrorDisplay(new PageErrorDisplay()); + setTitle(title); // Initialize the RequestLocal where the title for the current - // request will be kept - m_currentTitle = new RequestLocal() { - @Override - protected Object initialValue(PageState state) { - return m_title.firePrintEvent(state); - } - }; + // request will be kept + m_currentTitle = new RequestLocal() { + @Override + protected Object initialValue(PageState state) { + return m_title.firePrintEvent(state); + } + + }; // Initialize the set of state parameters to hold - // the ones necessary for keeping track of the selected component and - // the name and value of a 'control event' - m_selected = new StringParameter(SELECTED); - m_controlEvent = new StringParameter(CONTROL_EVENT); - m_controlValue = new StringParameter(CONTROL_VALUE); + // the ones necessary for keeping track of the selected component and + // the name and value of a 'control event' + m_selected = new StringParameter(SELECTED); + m_controlEvent = new StringParameter(CONTROL_EVENT); + m_controlValue = new StringParameter(CONTROL_VALUE); - m_stateModel = new FormModel("stateModel", true); - m_stateModel.addFormParam(m_selected); - m_stateModel.addFormParam(m_controlEvent); - m_stateModel.addFormParam(m_controlValue); + m_stateModel = new FormModel("stateModel", true); + m_stateModel.addFormParam(m_selected); + m_stateModel.addFormParam(m_controlEvent); + m_stateModel.addFormParam(m_controlValue); - // Set up the visibility tracking parameters - m_invisible = new BitSet(32); - BitSetParameter p = new BitSetParameter(INVISIBLE, - BitSetParameter.ENCODE_DGAP); - m_stateModel.addFormParam(p); - } + // Set up the visibility tracking parameters + m_invisible = new BitSet(32); + BitSetParameter p = new BitSetParameter(INVISIBLE, + BitSetParameter.ENCODE_DGAP); + m_stateModel.addFormParam(p); + } - /** - * Creates an empty page with default title and implicit BoxPanel - * container. - */ - public Page() { - this(""); - } + /** + * Creates an empty page with default title and implicit BoxPanel container. + */ + public Page() { + this(""); + } - /** - * Creates an empty page with the specified title and implicit BoxPanel - * container. - * - * @param title title for this page - */ - public Page(Label title) { - this(title, new BoxPanel()); - BoxPanel bp = (BoxPanel) m_panel; - bp.setWidth("100%"); - } + /** + * Creates an empty page with the specified title and implicit BoxPanel container. + * + * @param title title for this page + */ + public Page(Label title) { + this(title, new BoxPanel()); + BoxPanel bp = (BoxPanel) m_panel; + bp.setWidth("100%"); + } - /** - * Creates an empty page with the specified title and implicit BoxPanel - * container. - * - * @param title title for this page - */ - public Page(String title) { - this(new Label(title)); - } + /** + * Creates an empty page with the specified title and implicit BoxPanel container. + * + * @param title title for this page + */ + public Page(String title) { + this(new Label(title)); + } - /** - * Adds a component to this container. - * - * @param c component to add to this container - */ - @Override - public void add(Component c) { - m_panel.add(c); + /** + * Adds a component to this container. + * + * @param c component to add to this container + */ + @Override + public void add(Component c) { + m_panel.add(c); - } + } - /** - * Adds a component with the specified layout constraints to this - * container. Layout constraints are defined in each layout container as - * static ints. To specify multiple constraints, use bitwise OR. - * - * @param c component to add to this container - * - * @param constraints layout constraints (a bitwise OR of static ints in - * the particular layout) - */ - @Override - public void add(Component c, int constraints) { - m_panel.add(c, constraints); - } + /** + * Adds a component with the specified layout constraints to this container. Layout constraints + * are defined in each layout container as static ints. To specify multiple constraints, use + * bitwise OR. + * + * @param c component to add to this container + * + * @param constraints layout constraints (a bitwise OR of static ints in the particular layout) + */ + @Override + public void add(Component c, int constraints) { + m_panel.add(c, constraints); + } - /** - * Returns - * true if this list contains the specified element. More - * formally, returns - * true if and only if this list contains at least one - * element e such that (o==null ? e==null : o.equals(e)).

This - * method returns - * true only if the component has been directly added to - * this container. If this container contains another container that - * contains this component, this method returns - * false. - * - * @param o element whose presence in this container is to be tested - * - * @return true if this Container contains the specified - * component directly; false otherwise. - */ - @Override - public boolean contains(Object o) { - return m_panel.contains(o); - } + /** + * Returns true if this list contains the specified element. More formally, returns + * true if and only if this list contains at least one element e such that (o==null + * ? e==null : o.equals(e)). + *

+ * This method returns true only if the component has been directly added to this + * container. If this container contains another container that contains this component, this + * method returns false. + * + * @param o element whose presence in this container is to be tested + * + * @return true if this Container contains the specified component directly; + * false otherwise. + */ + @Override + public boolean contains(Object o) { + return m_panel.contains(o); + } - /** - * Returns the component at the specified position. Each call to the add - * method increments the index. Since the user has no control over the - * index of added components (other than counting each call to add), - * this method should be used in conjunction with indexOf. - * - * @param index the index of the item to be retrieved from this - * Container - * - * @return the component at the specified position in this container. - */ - @Override - public Component get(int index) { - return m_panel.get(index); - } + /** + * Returns the component at the specified position. Each call to the add method increments the + * index. Since the user has no control over the index of added components (other than counting + * each call to add), this method should be used in conjunction with indexOf. + * + * @param index the index of the item to be retrieved from this Container + * + * @return the component at the specified position in this container. + */ + @Override + public Component get(int index) { + return m_panel.get(index); + } - /** - * Gets the index of a component. - * - * @param c component to search for - * - * @return the index in this list of the first occurrence of the - * specified element, or -1 if this list does not contain this element. - * - * @pre c != null - * @post contains(c) implies (return >= 0) && (return < size()) - * @post !contains(c) implies return == -1 - */ - @Override - public int indexOf(Component c) { - return m_panel.indexOf(c); - } + /** + * Gets the index of a component. + * + * @param c component to search for + * + * @return the index in this list of the first occurrence of the specified element, or -1 if + * this list does not contain this element. + * + * @pre c != null + * @post contains(c) implies (return >= 0) && (return < size()) + * @pos + * t !contains(c) implies return == -1 + */ + @Override + public int indexOf(Component c) { + return m_panel.indexOf(c); + } - /** - * Returns - * true if the container contains no components. - * - * @return true if this container contains no * * - * components; false otherwise. - */ - @Override - public boolean isEmpty() { - return m_panel.isEmpty(); - } + /** + * Returns true if the container contains no components. + * + * @return true if this container contains no * * components; false + * otherwise. + */ + @Override + public boolean isEmpty() { + return m_panel.isEmpty(); + } - /** - * Returns the number of elements in this container. This does not - * recursively count the components that are indirectly contained in - * this container. - * - * @return the number of components directly in this container. - */ - @Override - public int size() { - return m_panel.size(); - } + /** + * Returns the number of elements in this container. This does not recursively count the + * components that are indirectly contained in this container. + * + * @return the number of components directly in this container. + */ + @Override + public int size() { + return m_panel.size(); + } - @Override - public Iterator children() { - return Collections.singletonList(m_panel).iterator(); - } + @Override + public Iterator children() { + return Collections.singletonList(m_panel).iterator(); + } - /** - * Returns the panel that the - * Page uses for rendering its components. - * - * @return the panel. - */ - public final Container getPanel() { - return m_panel; - } + /** + * Returns the panel that the Page uses for rendering its components. + * + * @return the panel. + */ + public final Container getPanel() { + return m_panel; + } - /** - * Set the Container used for rendering components on this page. Caution - * should be used with this function, as the existing container is - * simply overwritten. - * - * @author Matthew Booth (mbooth@redhat.com) - */ - public void setPanel(Container c) { - m_panel = c; - } + /** + * Set the Container used for rendering components on this page. Caution should be used with + * this function, as the existing container is simply overwritten. + * + * @author Matthew Booth (mbooth@redhat.com) + */ + public void setPanel(Container c) { + m_panel = c; + } - /** - *

Retrieves the title of this page.

- * - * @return the static title of this page. - */ - public final Label getTitle() { - return m_title; - } + /** + *

+ * Retrieves the title of this page.

+ * + * @return the static title of this page. + */ + public final Label getTitle() { + return m_title; + } - /** - * Retrieves the title of this page as a Bebop label component. - * - * @param state the state of the current request - * @return the title of the page for the current request. - */ - public final Label getTitle(PageState state) { - return (Label) m_currentTitle.get(state); - } + /** + * Retrieves the title of this page as a Bebop label component. + * + * @param state the state of the current request + * + * @return the title of the page for the current request. + */ + public final Label getTitle(PageState state) { + return (Label) m_currentTitle.get(state); + } - /** - * Sets the title for this page from the passed in string. - * - * @param title title for this page - */ - public void setTitle(String title) { - Assert.isUnlocked(this); - setTitle(new Label(title)); - } + /** + * Sets the title for this page from the passed in string. + * + * @param title title for this page + */ + public void setTitle(String title) { + Assert.isUnlocked(this); + setTitle(new Label(title)); + } - /** - * Set the title for this page from the passed in label. - * - * @param title title for this page - */ - public void setTitle(Label title) { - Assert.isUnlocked(this); - m_title = title; - } + /** + * Set the title for this page from the passed in label. + * + * @param title title for this page + */ + public void setTitle(Label title) { + Assert.isUnlocked(this); + m_title = title; + } - /** - * Sets the {@link Component} that will display the validation errors in - * the current {@link PageState}. Any validation error in the - * PageState will cause the - * Page to completely ignore all other components and - * render only the error display component.

By default, a - * {@link PageErrorDisplay} component is used to display the validation - * errors. - * - * @param c the component that will display the validation errors in the - * current PageState - */ - public final void setErrorDisplay(Component c) { - Assert.isUnlocked(this); - m_errorDisplay = c; - } + /** + * Sets the {@link Component} that will display the validation errors in the current + * {@link PageState}. Any validation error in the PageState will cause the + * Page to completely ignore all other components and render only the error display + * component. + *

+ * By default, a {@link PageErrorDisplay} component is used to display the validation errors. + * + * @param c the component that will display the validation errors in the current + * PageState + */ + public final void setErrorDisplay(Component c) { + Assert.isUnlocked(this); + m_errorDisplay = c; + } - /** - * Gets the {@link Component} that will display the validation errors in - * the current {@link PageState}. Any validation error in the - * PageState will cause the - * Page to completely ignore all other components and - * render only the error display component.

By default, a - * {@link PageErrorDisplay} component is used to display the validation - * errors. - * - * @return the component that will display the validation errors in the - * current PageState. - */ - public final Component getErrorDisplay() { - return m_errorDisplay; - } + /** + * Gets the {@link Component} that will display the validation errors in the current + * {@link PageState}. Any validation error in the PageState will cause the + * Page to completely ignore all other components and render only the error display + * component. + *

+ * By default, a {@link PageErrorDisplay} component is used to display the validation errors. + * + * @return the component that will display the validation errors in the current + * PageState. + */ + public final Component getErrorDisplay() { + return m_errorDisplay; + } - /** - * Adds a client-side stylesheet that should be used in HTML output. - * Arbitrarily many client-side stylesheets can be added with this - * method. To use a CSS stylesheet, call something like - * setStyleSheet("style.css", "text/css"). - * - *

These values will ultimately wind up in a <link> - * tag in the head of the HTML page. - * - *

Note that the stylesheet set with this call has nothing to do - * with the XSLT stylesheet (transformer) that is applied to the XML - * generated from this page! - * - * @param styleSheetURI the location of the stylesheet - * @param mimeType the MIME type of the stylesheet, usually - * text/css - * @pre ! isLocked() - */ - public void addClientStylesheet(String styleSheetURI, String mimeType) { - m_clientStylesheets.add(new Stylesheet(styleSheetURI, mimeType)); - } + /** + * Adds a client-side stylesheet that should be used in HTML output. Arbitrarily many + * client-side stylesheets can be added with this method. To use a CSS stylesheet, call + * something like setStyleSheet("style.css", "text/css"). + * + *

+ * These values will ultimately wind up in a <link> + * tag in the head of the HTML page. + * + *

+ * Note that the stylesheet set with this call has nothing to do with the XSLT stylesheet + * (transformer) that is applied to the XML generated from this page! + * + * @param styleSheetURI the location of the stylesheet + * @param mimeType the MIME type of the stylesheet, usually + * text/css + * + * @pre ! isLocked() + */ + public void addClientStylesheet(String styleSheetURI, String mimeType) { + m_clientStylesheets.add(new Stylesheet(styleSheetURI, mimeType)); + } - /** - * Adds a global state parameter to this page. Global parameters are - * values that need to be preserved between requests, but that have no - * special connection to any of the components on the page. For a page - * that displays details about an item, a global parameter would be used - * to identify the item. - * - *

If the parameter was previously added as a component state - * parameter, its name is unmangled and stays unmangled. - * - * @param p the global parameter to add - * - * @see #addComponentStateParam - * - * @pre ! isLocked() - * @pre parameter != null - */ - public void addGlobalStateParam(ParameterModel p) { - Assert.isUnlocked(this); - p.setName(unmangle(p.getName())); - m_stateModel.addFormParam(p); - } + /** + * Adds a global state parameter to this page. Global parameters are values that need to be + * preserved between requests, but that have no special connection to any of the components on + * the page. For a page that displays details about an item, a global parameter would be used to + * identify the item. + * + *

+ * If the parameter was previously added as a component state parameter, its name is unmangled + * and stays unmangled. + * + * @param p the global parameter to add + * + * @see #addComponentStateParam + * + * @pre ! isLocked() + * @pre parameter != null + */ + public void addGlobalStateParam(ParameterModel p) { + Assert.isUnlocked(this); + p.setName(unmangle(p.getName())); + m_stateModel.addFormParam(p); + } - /** - * Constructs the top nodes of the DOM or JDOM tree. Used by - * generateXML(PageState, Document) below.

Generates DOM fragment: - *

-	 * <bebop:page>
-	 *   <bebop:title> ... value set with setTitle ... </bebop:title>
-	 *   <bebop:stylesheet href='styleSheetURI' type='mimeType'>
-	 *   ... page content gnerated by children ...
-	 * </bebop:page>
The content of the <title> - * element can be set by calling {@link #setTitle setTitle}. The - * <stylesheet> element will only be present if a - * stylesheet has been set with {@link - * #setStyleSheet setStyleSheet}. - * - * @param ps the page state for the current page - * @param parent the DOM node for the whole Document - * - * @pre isLocked() - */ - protected Element generateXMLHelper(PageState ps, Document parent) { - Assert.isLocked(this); + /** + * Constructs the top nodes of the DOM or JDOM tree. Used by generateXML(PageState, Document) + * below. + *

+ * Generates DOM fragment: + *

+     * <bebop:page>
+     *   <bebop:title> ... value set with setTitle ... </bebop:title>
+     *   <bebop:stylesheet href='styleSheetURI' type='mimeType'>
+     *   ... page content gnerated by children ...
+     * </bebop:page>
The content of the <title> + * element can be set by calling {@link #setTitle setTitle}. The + * <stylesheet> element will only be present if a stylesheet has been set with {@link + * #setStyleSheet setStyleSheet}. + * + * @param ps the page state for the current page + * @param parent the DOM node for the whole Document + * + * @pre isLocked() + */ + protected Element generateXMLHelper(PageState ps, Document parent) { + Assert.isLocked(this); - Element page = parent.createRootElement("bebop:page", BEBOP_XML_NS); - exportAttributes(page); + Element page = parent.createRootElement("bebop:page", BEBOP_XML_NS); + exportAttributes(page); - /* Generator information */ - exportSystemInformation(page); + /* Generator information */ + exportSystemInformation(page); - Element title = page.newChildElement("bebop:title", BEBOP_XML_NS); - title.setText(getTitle(ps).getLabel(ps)); + Element title = page.newChildElement("bebop:title", BEBOP_XML_NS); + title.setText(getTitle(ps).getLabel(ps)); - for (Iterator i = m_clientStylesheets.iterator(); i.hasNext();) { - ((Stylesheet) i.next()).generateXML(page); - } + for (Iterator i = m_clientStylesheets.iterator(); i.hasNext();) { + ((Stylesheet) i.next()).generateXML(page); + } - return page; - } + return page; + } - /** - * Constructs a DOM or JDOM tree with all components on the page. The - * tree represents the page that results from the - * {@link javax.servlet.http.HttpServletRequest} kept in the - * state. - * - * @param state the page state produced by {@link #process} - * @param parent the DOM node for the whole Document - * @see #process process - * @pre isLocked() - * @pre state != null - */ - public void generateXML(PageState state, Document parent) { - // always export page state as HTTP session - if (m_useHttpSession) { - state.stateAsHttpSession(); - } + /** + * Constructs a DOM or JDOM tree with all components on the page. The tree represents the page + * that results from the {@link javax.servlet.http.HttpServletRequest} kept in the + * state. + * + * @param state the page state produced by {@link #process} + * @param parent the DOM node for the whole Document + * + * @see #process process + * @pre isLocked() + * @pre state != null + */ + public void generateXML(PageState state, Document parent) { + // always export page state as HTTP session + if (m_useHttpSession) { + state.stateAsHttpSession(); + } - Element page = generateXMLHelper(state, parent); + Element page = generateXMLHelper(state, parent); // If the page state has errors, ignore all the components and - // render only the error display component - if (state.getErrors().hasNext()) { - m_errorDisplay.generateXML(state, page); - } else { - m_panel.generateXML(state, page); - } + // render only the error display component + if (state.getErrors().hasNext()) { + m_errorDisplay.generateXML(state, page); + } else { + m_panel.generateXML(state, page); + } - if (Kernel.getConfig().isDebugEnabled() && debugStructure(state. - getRequest())) { + if (Kernel.getConfig().isDebugEnabled() && debugStructure(state. + getRequest())) { - Element structure = - page.newChildElement("bebop:structure", BEBOP_XML_NS); + Element structure = page.newChildElement("bebop:structure", BEBOP_XML_NS); - showStructure(state, structure); - } - } + showStructure(state, structure); + } + } - private static boolean debugStructure(HttpServletRequest req) { - return "transform".equals(req.getParameter("debug")); - } + private static boolean debugStructure(HttpServletRequest req) { + return "transform".equals(req.getParameter("debug")); + } - /** - * Do nothing. Top-level add nodes is meaningless. - */ - @Override - public void generateXML(PageState state, Element elt) { - } + /** + * Do nothing. Top-level add nodes is meaningless. + */ + @Override + public void generateXML(PageState state, Element elt) { + } - /** - * Creates a PageState object and processes it by calling the respond - * method on the selected component. Processes a request by notifying - * the component from which the process originated and {@link #fireActionEvent - * broadcasts} an {@link ActionEvent} to all the listeners that - * registered with {@link #addActionListener addActionListener}. - * - * @see #generateXML(PageState,Document) generateXML - * @pre isLocked() - * @pre request != null - * @pre response != null - */ - public PageState process(HttpServletRequest request, - HttpServletResponse response) - throws ServletException { + /** + * Creates a PageState object and processes it by calling the respond method on the selected + * component. Processes a request by notifying the component from which the process originated + * and {@link #fireActionEvent + * broadcasts} an {@link ActionEvent} to all the listeners that registered with + * {@link #addActionListener addActionListener}. + * + * @see #generateXML(PageState,Document) generateXML + * @pre isLocked() + * @pre request != null + * @pre response != null + */ + public PageState process(HttpServletRequest request, + HttpServletResponse response) + throws ServletException { - PageState result = new PageState(this, request, response); - try { - DeveloperSupport.startStage("Bebop Page Process"); - process(result); - } finally { - DeveloperSupport.endStage("Bebop Page Process"); - } - return result; - } + PageState result = new PageState(this, request, response); + try { + DeveloperSupport.startStage("Bebop Page Process"); + process(result); + } finally { + DeveloperSupport.endStage("Bebop Page Process"); + } + return result; + } - /** - * Processes the supplied PageState object according to this PageModel. - * Calls the respond method on the selected Bebop component. - */ - public void process(PageState state) throws ServletException { - Assert.isLocked(this); - try { - DeveloperSupport.startStage("Bebop Request Event"); - fireRequestEvent(state); - } finally { - DeveloperSupport.endStage("Bebop Request Event"); - } + /** + * Processes the supplied PageState object according to this PageModel. Calls the respond method + * on the selected Bebop component. + */ + public void process(PageState state) throws ServletException { + Assert.isLocked(this); + try { + DeveloperSupport.startStage("Bebop Request Event"); + fireRequestEvent(state); + } finally { + DeveloperSupport.endStage("Bebop Request Event"); + } // Validate the state; any errors in the state will be displayed - // by generateXML - state.forceValidate(); + // by generateXML + state.forceValidate(); - if (state.isValid()) { - try { - DeveloperSupport.startStage("Bebop Respond"); - state.respond(); - } finally { - DeveloperSupport.endStage("Bebop Respond"); - } - try { - DeveloperSupport.startStage("Bebop Action Event"); - fireActionEvent(state); - } finally { - DeveloperSupport.endStage("Bebop Action Event"); - } - } - } + if (state.isValid()) { + try { + DeveloperSupport.startStage("Bebop Respond"); + state.respond(); + } finally { + DeveloperSupport.endStage("Bebop Respond"); + } + try { + DeveloperSupport.startStage("Bebop Action Event"); + fireActionEvent(state); + } finally { + DeveloperSupport.endStage("Bebop Action Event"); + } + } + } // /** // * Does all the servicing of a request except output generation. @@ -707,627 +688,625 @@ public class Page extends BlockStylable implements Container { // PageState state = process(req, res); // return state; // } - /** - * Builds a DOM Document from the current request state by doing a - * depth-first tree walk on the current set of components in this Page, - * calling generateXML on each. Does NOT do the rendering. If the HTTP - * response has already been committed, does not build the XML document. - * - * @return a DOM ready for rendering, or null if the response has - * already been committed. - * @post res.isCommitted() == (return == null) - */ - public Document buildDocument(HttpServletRequest req, - HttpServletResponse res) - throws ServletException { - try { - Document doc = new Document(); - PageState state = process(req, res); + /** + * Builds a DOM Document from the current request state by doing a depth-first tree walk on the + * current set of components in this Page, calling generateXML on each. Does NOT do the + * rendering. If the HTTP response has already been committed, does not build the XML document. + * + * @return a DOM ready for rendering, or null if the response has already been committed. + * + * @post res.isCommitted() == (return == null) + */ + public Document buildDocument(HttpServletRequest req, + HttpServletResponse res) + throws ServletException { + try { + Document doc = new Document(); + PageState state = process(req, res); // only generate XML document if the response is not already - // committed - if (!res.isCommitted()) { - try { - DeveloperSupport.startStage("Bebop XML"); - Profiler.startOp("XML"); - generateXML(state, doc); - } finally { - DeveloperSupport.endStage("Bebop XML"); - Profiler.stopOp("XML"); - } - return doc; - } else { - return null; - } - } catch (ParserConfigurationException e) { - throw new ServletException(e); - } - } - - /** - * Finishes building the page. The tree of components is traversed and - * each component is told to add its state parameters to the page's - * state model. - * - * @pre ! isLocked() - */ - private void finish() { - if (!m_finished) { - Assert.isUnlocked(this); - - Traversal componentRegistrar = new Traversal() { - @Override - protected void act(Component c) { - addComponent(c); - c.register(Page.this); - } - }; - if (m_panel == null) { - s_log.warn("m_panel is null"); - } - componentRegistrar.preorder(m_panel); - if (m_errorDisplay != null) { - addComponent(m_errorDisplay); - m_errorDisplay.register(Page.this); - } - - m_finished = true; - } - } - - /** - * Locks the page and all its components against further modifications. - * - *

Locking a page helps in finding mistakes that result from - * modifying a page's structure.

- */ - @Override - public void lock() { - if (!m_finished) { - finish(); - } - m_stateModel.lock(); - Traversal componentLocker = new Traversal() { - @Override - protected void act(Component c) { - c.lock(); - } - }; - - componentLocker.preorder(m_panel); - - super.lock(); - } - - @Override - public void respond(PageState state) throws javax.servlet.ServletException { - throw new UnsupportedOperationException(); - } - - /** - * Registers a listener that is notified whenever a request to this page - * is made, after the selected component has had a chance to respond. - * - * @pre l != null - * @pre ! isLocked() - */ - public void addActionListener(ActionListener l) { - Assert.isUnlocked(this); - m_actionListeners.add(l); - } - - /** - * Remove a previously registered action listener. - * - * @pre l != null - * @pre ! isLocked() - */ - public void removeActionListener(ActionListener l) { - Assert.isUnlocked(this); - m_actionListeners.remove(l); - } - - /** - * Registers a listener that is notified whenever a request to this page - * is made, before the selected component has had a chance to respond. - * - * @pre l != null - * @pre ! isLocked() - */ - public void addRequestListener(RequestListener l) { - Assert.isUnlocked(this); - m_requestListeners.add(l); - } - - /** - * Removes a previously registered request listener. - * - * @param 1 the listener to remove - * @pre l != null - * @pre ! isLocked() - */ - public void removeRequestListener(RequestListener l) { - Assert.isUnlocked(this); - m_requestListeners.remove(l); - } - - /** - * Broadcasts an {@link ActionEvent} to all registered listeners. The - * source of the event is this page, and the state recorded in the event - * is the one resulting from processing the current request. - * - * @param the state for this event - * - * @pre state != null - */ - protected void fireActionEvent(PageState state) { - ActionEvent e = null; - - for (Iterator i = m_actionListeners.iterator(); i.hasNext();) { - if (e == null) { - e = new ActionEvent(this, state); - } - - final ActionListener listener = (ActionListener) i.next(); - - if (s_log.isDebugEnabled()) { - s_log.debug("Firing action listener " + listener); - } - - listener.actionPerformed(e); - } - } - - /** - * Broadcasts a {@link RequestEvent} to all registered listeners. The - * source of the event is this page, and the state recorded in the event - * is the one resulting from processing the current request. - * - * @param state the state for this event - * - * @pre state != null - */ - protected void fireRequestEvent(PageState state) { - RequestEvent e = null; - - for (Iterator i = m_requestListeners.iterator(); i.hasNext();) { - if (e == null) { - e = new RequestEvent(this, state); - } - - final RequestListener listener = (RequestListener) i.next(); - - if (s_log.isDebugEnabled()) { - s_log.debug("Firing request listener " + listener); - } - - listener.pageRequested(e); - } - } - - /** - * Export page generator information if set. The m_pageGenerator is a - * HashMap containing the information as key value. In general this - * should include generator name and generator version. - * - * @param page parent element - should be bebeop:page - * - * @pre m_pageGenerator != null && !m_pageGenerator.isEmpty() - */ - final protected void exportSystemInformation(Element page) { - SystemInformation sysInfo = SystemInformation.getInstance(); - if (!sysInfo.isEmpty()) { - Element gen = page.newChildElement("bebop:systemInformation", BEBOP_XML_NS); - - Iterator> keyValues = sysInfo.iterator(); - while (keyValues.hasNext()) { - Map.Entry entry = keyValues.next(); - gen.addAttribute(entry.getKey(), entry.getValue()); - } - } - } - - // Client-side stylesheet storage - private class Stylesheet { - - String m_URI; - String m_type; - - public Stylesheet(String stylesheetURI, String mimeType) { - m_URI = stylesheetURI; - m_type = mimeType; - } - - public void generateXML(Element parent) { - Element style = parent.newChildElement("bebop:stylesheet", - BEBOP_XML_NS); - style.addAttribute("href", m_URI); - if (m_type != null) { - style.addAttribute("type", m_type); - } - } - } - - /** - * Adds a component to the page model. - * - * @deprecated This method will become private in ACS 5.0. - */ - public void addComponent(Component c) { - Assert.isUnlocked(this); - - if (!stateContains(c)) { - if (c == null) { - s_log.error("c is null"); - } /*else { - s_log.error("c: " + c.toString()); - }*/ - String key = c.getKey(); - if (key == null) { - key = Integer.toString(m_components.size()); - } - if (m_componentMap.get(key) != null) { - throw new IllegalArgumentException( - "Component key must not be duplicated. The key " + key - + " is shared by more than one component."); - } - m_componentMap.put(key, c); - m_components.add(c); - } - } - - /** - * Registers a state parameter for a component. It is permissible to - * register the same state parameter several times, from the same or - * different components. The name of the parameter will be changed to - * ensure that it won't clash with any other component's parameter. If - * the parameter is added more than once, the name is only changed the - * first time it is added. - * - * @param c the component to register the parameter for - * @param p the state parameter to register - * - * @see #addGlobalStateParam - * - * @pre stateContains(c) - * @pre ! isLocked() - * @pre p != null - */ - public void addComponentStateParam(Component c, ParameterModel p) { - Assert.isUnlocked(this); - - if (!stateContains(c)) { - throw new IllegalArgumentException( - "Component must be registered in Page"); - } - if (!m_stateModel.containsFormParam(p)) { - String name = parameterName(c, p.getName()); - s_log.debug(String.format("Setting name of parameter to add to '%s'", - name)); - p.setName(name); - m_stateModel.addFormParam(p); - - Collection params = (Collection) m_componentParameterMap.get(c); - if (params == null) { - params = new ArrayList(); - m_componentParameterMap.put(c, params); - } - params.add(p); - } - } - - /** - *

Get the parameters registered for a given component.

- */ - public Collection getComponentParameters(Component c) { - return (Collection) m_componentParameterMap.get(c); - } - - /** - * Gets the state index of a component. This is the number assigned to - * the component in the register traveral - * - * @param c the component to search for - * - * @return the index in this list of the first occurrence of the - * specified element, or -1 if this list does not contain this element. - * - * @pre c != null - * @post contains(c) implies (return >= 0) && (return < size()) - * @post !contains(c) implies return == -1 - */ - public int stateIndex(Component c) { - return m_components.indexOf(c); - } - - /** - * The number of components in the page model. - * - * @post return >= 0 - */ - public int stateSize() { - return m_components.size(); - } - - /** - * Checks whether this component is already in the page model. - * - * @pre c != null - */ - public boolean stateContains(Component c) { - return m_components.contains(c); - } - - /** - * Gets a page component by index. - * - * @pre (i >= 0) && (i < size()) - * @post return != null - */ - public Component getComponent(int i) { - return (Component) m_components.get(i); - } - - /** - * Gets a page component by key. - * - * @pre s != null - */ - Component getComponent(String s) { - return (Component) m_componentMap.get(s); - } - - /** - * Gets the form model that contains the parameters for the page's - * state. - */ - public final FormModel getStateModel() { - return m_stateModel; - } - - /** - * Gets the ParameterModels held in this Page. - * - * @return an iterator of ParameterModels. - */ - public Iterator getParameters() { - return m_stateModel.getParameters(); - } - - /** - * Checks whether the specified component is visible by default on the - * page. - * - * @param c a component contained in the page - * @return true if the component is visible by default; - * false otherwise. - * @see #setVisibleDefault setVisibleDefault - * @see Component#setVisible Component.setVisible - */ - public boolean isVisibleDefault(Component c) { - Assert.isTrue(stateContains(c)); - - return !m_invisible.get(stateIndex(c)); - } - - /** - * Sets whether the specified component is visible by default. The - * default visibility is used when a page is displayed for the first - * time and on subsequent requests until the visibility of a component - * is changed explicitly with {@link Component#setVisible - * Component.setVisible}. - * - *

When a component is first added to a page, it is visible. - * - * @param c a component whose visibility is to be set - * @param v true if the component is visible; - * false otherwise. - * @see Component#setVisible Component.setVisible - * @see Component#register Component.register - */ - public void setVisibleDefault(Component c, boolean v) { - Assert.isUnlocked(this); - - addComponent(c); - int i = stateIndex(c); - if (v) { - m_invisible.clear(i); - } else { - m_invisible.set(i); - } - } - - /** - * The global name of the parameter - * name in the component - * c. - */ - public String parameterName(Component c, String name) { - if (c == null || !stateContains(c)) { - return name; - } - - return componentPrefix(c) + name; - } - - /** - * The global name of the parameter - * name. - */ - public String parameterName(String name) { - return parameterName(null, name); - } - - void reset(final PageState ps, Component cmpnt) { - Traversal resetter = new Traversal() { - @Override - protected void act(Component c) { - Collection cp = getComponentParameters(c); - if (cp != null) { - Iterator iter = cp.iterator(); - while (iter.hasNext()) { - ParameterModel p = (ParameterModel) iter.next(); - ps.setValue(p, null); - } - } - c.setVisible(ps, isVisibleDefault(c)); - } - }; - resetter.preorder(cmpnt); - } - - /** - * Return the prefix that is prepended to each component's state - * parameters to keep them unique. - */ - private final String componentPrefix(Component c) { - if (c == null) { - return COMPONENT_PREFIX + "g" + DELIMITER; - } else { - // WRS: preferentially use key if it exists - String key = c.getKey(); - if (key == null) { - if (stateContains(c)) { - key = String.valueOf(stateIndex(c)); - } else { - throw new IllegalArgumentException( - "Cannot generate prefix for component: key is null " - + "and component " + c.toString() + "/" + c.getKey() - + " did not register with page."); - } - } - return COMPONENT_PREFIX + key + DELIMITER; - } - } - - /** - * Undo the name change that {@link #parameterName} does. - * - * @param name a possibly mangled name - * @return the unmangled name. - */ - private static final String unmangle(String name) { - if (!name.startsWith(COMPONENT_PREFIX)) { - return name; - } - // Find the second occurence of delimiter - int prefix = name.indexOf(DELIMITER, name.indexOf(DELIMITER) + 1); - if (prefix >= 0 && prefix < name.length()) { - return name.substring(prefix + 1); - } - return name; - } - // Procs for debugging output - private static String NAME = "name"; - - /** - * Produces an XML fragment that captures the layout of this page. - */ - private void showStructure(PageState s, Element root) { - final HttpServletRequest req = s.getRequest(); - Element state = root.newChildElement("bebop:state", BEBOP_XML_NS); - // Selected component - String sel = req.getParameter(m_selected.getName()); - Element selected = state.newChildElement("bebop:selected", BEBOP_XML_NS); - - selected.addAttribute(NAME, m_selected.getName()); - selected.setText(sel); - - // Control event - Element eventName = - state.newChildElement("bebop:eventName", BEBOP_XML_NS); - eventName.addAttribute(NAME, m_controlEvent.getName()); - eventName.setText(req.getParameter(m_controlEvent.getName())); - Element eventValue = - state.newChildElement("bebop:eventValue", BEBOP_XML_NS); - eventValue.addAttribute(NAME, m_controlValue.getName()); - eventValue.setText(req.getParameter(m_controlValue.getName())); - - // Global parameters - Element globalState = - root.newChildElement("bebop:params", BEBOP_XML_NS); - for (Iterator ii = getStateModel().getParameters(); ii.hasNext();) { - ParameterModel p = (ParameterModel) ii.next(); - if (!p.getName().startsWith(COMPONENT_PREFIX)) { - Element param = - globalState.newChildElement("bebop:param", BEBOP_XML_NS); - param.addAttribute(NAME, p.getName()); - param.setText(String.valueOf(s.getValue(p))); - } - } - - showVisibility(s, this, root); - } - - /** - * @see showStructure(PageState, Element) - */ - private void showVisibility(PageState s, Component c, Element parent) { - HttpServletRequest req = s.getRequest(); - - Element cmp = parent.newChildElement("bebop:component", BEBOP_XML_NS); - cmp.addAttribute(NAME, getDebugLabel(c)); - cmp.addAttribute("idx", String.valueOf(stateIndex(c))); - cmp.addAttribute("isVisible", (s.isVisible(c) ? "yes" : "no")); - cmp.addAttribute("class", c.getClass().getName()); - - if (c.getKey() != null) { - String prefix = componentPrefix(c); - for (Iterator i = getStateModel().getParameters(); i.hasNext();) { - ParameterModel p = (ParameterModel) i.next(); - if (!p.getName().startsWith(prefix)) { - continue; - } - - Element param = - parent.newChildElement("bebop:param", BEBOP_XML_NS); - param.addAttribute(NAME, unmangle(p.getName())); - param.addAttribute("defaultValue", - String.valueOf(req.getParameter(p.getName()))); - param.addAttribute("currentValue", String.valueOf(s.getValue(p))); - } - } - for (Iterator i = c.children(); i.hasNext();) { - showVisibility(s, ((Component) i.next()), cmp); - } - } - - private static String getDebugLabel(Component c) { - if (c.getKey() != null) { - return c.getKey(); - } - - String klass = c.getClass().getName(); - return klass.substring(klass.lastIndexOf(".") + 1, klass.length()); - } - - /** - * return a string that represents an ordered list of component ids used - * on the page. For situations where only the components present is of - * importance, this may be used by implementations of hashCode & equals - * - * @return - */ - public String getComponentString() { - Iterator it = m_componentMap.keySet().iterator(); - /*int hash = 0; - while (it.hasNext()) { - String componentId = (String)it.next(); - s_log.debug("component id = " + componentId); - hash = hash | componentId.hashCode(); - s_log.debug("hash so far = " + hash); - }*/ - Date start = new Date(); - - StringBuilder hashString = new StringBuilder(); - while (it.hasNext()) { - String componentId = (String) it.next(); - hashString.append(componentId); - } - s_log.debug("Time to create hashCode for page: " + (new Date().getTime() - start. - getTime())); - return hashString.toString(); - - - } + // committed + if (!res.isCommitted()) { + try { + DeveloperSupport.startStage("Bebop XML"); + Profiler.startOp("XML"); + generateXML(state, doc); + } finally { + DeveloperSupport.endStage("Bebop XML"); + Profiler.stopOp("XML"); + } + return doc; + } else { + return null; + } + } catch (ParserConfigurationException e) { + throw new ServletException(e); + } + } + + /** + * Finishes building the page. The tree of components is traversed and each component is told to + * add its state parameters to the page's state model. + * + * @pre ! isLocked() + */ + private void finish() { + if (!m_finished) { + Assert.isUnlocked(this); + + Traversal componentRegistrar = new Traversal() { + @Override + protected void act(Component c) { + addComponent(c); + c.register(Page.this); + } + + }; + if (m_panel == null) { + s_log.warn("m_panel is null"); + } + componentRegistrar.preorder(m_panel); + if (m_errorDisplay != null) { + addComponent(m_errorDisplay); + m_errorDisplay.register(Page.this); + } + + m_finished = true; + } + } + + /** + * Locks the page and all its components against further modifications. + * + *

+ * Locking a page helps in finding mistakes that result from modifying a page's structure.

+ */ + @Override + public void lock() { + if (!m_finished) { + finish(); + } + m_stateModel.lock(); + Traversal componentLocker = new Traversal() { + @Override + protected void act(Component c) { + c.lock(); + } + + }; + + componentLocker.preorder(m_panel); + + super.lock(); + } + + @Override + public void respond(PageState state) throws javax.servlet.ServletException { + throw new UnsupportedOperationException(); + } + + /** + * Registers a listener that is notified whenever a request to this page is made, after the + * selected component has had a chance to respond. + * + * @pre l != null + * @pre ! isLocked() + */ + public void addActionListener(ActionListener l) { + Assert.isUnlocked(this); + m_actionListeners.add(l); + } + + /** + * Remove a previously registered action listener. + * + * @pre l != null + * @pre ! isLocked() + */ + public void removeActionListener(ActionListener l) { + Assert.isUnlocked(this); + m_actionListeners.remove(l); + } + + /** + * Registers a listener that is notified whenever a request to this page is made, before the + * selected component has had a chance to respond. + * + * @pre l != null + * @pre ! isLocked() + */ + public void addRequestListener(RequestListener l) { + Assert.isUnlocked(this); + m_requestListeners.add(l); + } + + /** + * Removes a previously registered request listener. + * + * @param 1 the listener to remove + * + * @pre l != null + * @pre ! isLocked() + */ + public void removeRequestListener(RequestListener l) { + Assert.isUnlocked(this); + m_requestListeners.remove(l); + } + + /** + * Broadcasts an {@link ActionEvent} to all registered listeners. The source of the event is + * this page, and the state recorded in the event is the one resulting from processing the + * current request. + * + * @param the state for this event + * + * @pre state != null + */ + protected void fireActionEvent(PageState state) { + ActionEvent e = null; + + for (Iterator i = m_actionListeners.iterator(); i.hasNext();) { + if (e == null) { + e = new ActionEvent(this, state); + } + + final ActionListener listener = (ActionListener) i.next(); + + if (s_log.isDebugEnabled()) { + s_log.debug("Firing action listener " + listener); + } + + listener.actionPerformed(e); + } + } + + /** + * Broadcasts a {@link RequestEvent} to all registered listeners. The source of the event is + * this page, and the state recorded in the event is the one resulting from processing the + * current request. + * + * @param state the state for this event + * + * @pre state != null + */ + protected void fireRequestEvent(PageState state) { + RequestEvent e = null; + + for (Iterator i = m_requestListeners.iterator(); i.hasNext();) { + if (e == null) { + e = new RequestEvent(this, state); + } + + final RequestListener listener = (RequestListener) i.next(); + + if (s_log.isDebugEnabled()) { + s_log.debug("Firing request listener " + listener); + } + + listener.pageRequested(e); + } + } + + /** + * Export page generator information if set. The m_pageGenerator is a HashMap containing the + * information as key value. In general this should include generator name and generator + * version. + * + * @param page parent element - should be bebeop:page + * + * @pre m_pageGenerator != null && !m_pageGenerator.isEmpty() + */ + final protected void exportSystemInformation(Element page) { + SystemInformation sysInfo = SystemInformation.getInstance(); + if (!sysInfo.isEmpty()) { + Element gen = page.newChildElement("bebop:systemInformation", BEBOP_XML_NS); + + Iterator> keyValues = sysInfo.iterator(); + while (keyValues.hasNext()) { + Map.Entry entry = keyValues.next(); + gen.addAttribute(entry.getKey(), entry.getValue()); + } + } + } + + // Client-side stylesheet storage + private class Stylesheet { + + String m_URI; + String m_type; + + public Stylesheet(String stylesheetURI, String mimeType) { + m_URI = stylesheetURI; + m_type = mimeType; + } + + public void generateXML(Element parent) { + Element style = parent.newChildElement("bebop:stylesheet", + BEBOP_XML_NS); + style.addAttribute("href", m_URI); + if (m_type != null) { + style.addAttribute("type", m_type); + } + } + + } + + /** + * Adds a component to the page model. + * + * @deprecated This method will become private in ACS 5.0. + */ + public void addComponent(Component c) { + Assert.isUnlocked(this); + + if (!stateContains(c)) { + if (c == null) { + s_log.error("c is null"); + } /*else { + s_log.error("c: " + c.toString()); + }*/ + + String key = c.getKey(); + if (key == null) { + key = Integer.toString(m_components.size()); + } + if (m_componentMap.get(key) != null) { + throw new IllegalArgumentException( + "Component key must not be duplicated. The key " + key + + " is shared by more than one component."); + } + m_componentMap.put(key, c); + m_components.add(c); + } + } + + /** + * Registers a state parameter for a component. It is permissible to register the same state + * parameter several times, from the same or different components. The name of the parameter + * will be changed to ensure that it won't clash with any other component's parameter. If the + * parameter is added more than once, the name is only changed the first time it is added. + * + * @param c the component to register the parameter for + * @param p the state parameter to register + * + * @see #addGlobalStateParam + * + * @pre stateContains(c) + * @pre ! isLocked() + * @pre p != null + */ + public void addComponentStateParam(Component c, ParameterModel p) { + Assert.isUnlocked(this); + + if (!stateContains(c)) { + throw new IllegalArgumentException( + "Component must be registered in Page"); + } + if (!m_stateModel.containsFormParam(p)) { + String name = parameterName(c, p.getName()); + s_log.debug(String.format("Setting name of parameter to add to '%s'", + name)); + p.setName(name); + m_stateModel.addFormParam(p); + + Collection params = (Collection) m_componentParameterMap.get(c); + if (params == null) { + params = new ArrayList(); + m_componentParameterMap.put(c, params); + } + params.add(p); + } + } + + /** + *

+ * Get the parameters registered for a given component.

+ */ + public Collection getComponentParameters(Component c) { + return (Collection) m_componentParameterMap.get(c); + } + + /** + * Gets the state index of a component. This is the number assigned to the component in the + * register traveral + * + * @param c the component to search for + * + * @return the index in this list of the first occurrence of the specified element, or -1 if + * this list does not contain this element. + * + * @pre c != null + * @post contains(c) implies (return >= 0) && (return < size()) + * @pos + * t !contains(c) implies return == -1 + */ + public int stateIndex(Component c) { + return m_components.indexOf(c); + } + + /** + * The number of components in the page model. + * + * @post return >= 0 + */ + public int stateSize() { + return m_components.size(); + } + + /** + * Checks whether this component is already in the page model. + * + * @pre c != null + */ + public boolean stateContains(Component c) { + return m_components.contains(c); + } + + /** + * Gets a page component by index. + * + * @pre (i >= 0) && (i < size()) + * @pos + * t return != null + */ + public Component getComponent(int i) { + return (Component) m_components.get(i); + } + + /** + * Gets a page component by key. + * + * @pre s != null + */ + Component getComponent(String s) { + return (Component) m_componentMap.get(s); + } + + /** + * Gets the form model that contains the parameters for the page's state. + */ + public final FormModel getStateModel() { + return m_stateModel; + } + + /** + * Gets the ParameterModels held in this Page. + * + * @return an iterator of ParameterModels. + */ + public Iterator getParameters() { + return m_stateModel.getParameters(); + } + + /** + * Checks whether the specified component is visible by default on the page. + * + * @param c a component contained in the page + * + * @return true if the component is visible by default; false + * otherwise. + * + * @see #setVisibleDefault setVisibleDefault + * @see Component#setVisible Component.setVisible + */ + public boolean isVisibleDefault(Component c) { + Assert.isTrue(stateContains(c)); + + return !m_invisible.get(stateIndex(c)); + } + + /** + * Sets whether the specified component is visible by default. The default visibility is used + * when a page is displayed for the first time and on subsequent requests until the visibility + * of a component is changed explicitly with {@link Component#setVisible + * Component.setVisible}. + * + *

+ * When a component is first added to a page, it is visible. + * + * @param c a component whose visibility is to be set + * @param v true if the component is visible; false otherwise. + * + * @see Component#setVisible Component.setVisible + * @see Component#register Component.register + */ + public void setVisibleDefault(Component c, boolean v) { + Assert.isUnlocked(this); + + addComponent(c); + int i = stateIndex(c); + if (v) { + m_invisible.clear(i); + } else { + m_invisible.set(i); + } + } + + /** + * The global name of the parameter name in the component c. + */ + public String parameterName(Component c, String name) { + if (c == null || !stateContains(c)) { + return name; + } + + return componentPrefix(c) + name; + } + + /** + * The global name of the parameter name. + */ + public String parameterName(String name) { + return parameterName(null, name); + } + + void reset(final PageState ps, Component cmpnt) { + Traversal resetter = new Traversal() { + @Override + protected void act(Component c) { + Collection cp = getComponentParameters(c); + if (cp != null) { + Iterator iter = cp.iterator(); + while (iter.hasNext()) { + ParameterModel p = (ParameterModel) iter.next(); + ps.setValue(p, null); + } + } + c.setVisible(ps, isVisibleDefault(c)); + } + + }; + resetter.preorder(cmpnt); + } + + /** + * Return the prefix that is prepended to each component's state parameters to keep them unique. + */ + private final String componentPrefix(Component c) { + if (c == null) { + return COMPONENT_PREFIX + "g" + DELIMITER; + } else { + // WRS: preferentially use key if it exists + String key = c.getKey(); + if (key == null) { + if (stateContains(c)) { + key = String.valueOf(stateIndex(c)); + } else { + throw new IllegalArgumentException( + "Cannot generate prefix for component: key is null " + + "and component " + c.toString() + "/" + c.getKey() + + " did not register with page."); + } + } + return COMPONENT_PREFIX + key + DELIMITER; + } + } + + /** + * Undo the name change that {@link #parameterName} does. + * + * @param name a possibly mangled name + * + * @return the unmangled name. + */ + private static final String unmangle(String name) { + if (!name.startsWith(COMPONENT_PREFIX)) { + return name; + } + // Find the second occurence of delimiter + int prefix = name.indexOf(DELIMITER, name.indexOf(DELIMITER) + 1); + if (prefix >= 0 && prefix < name.length()) { + return name.substring(prefix + 1); + } + return name; + } + + // Procs for debugging output + private static String NAME = "name"; + + /** + * Produces an XML fragment that captures the layout of this page. + */ + private void showStructure(PageState s, Element root) { + final HttpServletRequest req = s.getRequest(); + Element state = root.newChildElement("bebop:state", BEBOP_XML_NS); + // Selected component + String sel = req.getParameter(m_selected.getName()); + Element selected = state.newChildElement("bebop:selected", BEBOP_XML_NS); + + selected.addAttribute(NAME, m_selected.getName()); + selected.setText(sel); + + // Control event + Element eventName = state.newChildElement("bebop:eventName", BEBOP_XML_NS); + eventName.addAttribute(NAME, m_controlEvent.getName()); + eventName.setText(req.getParameter(m_controlEvent.getName())); + Element eventValue = state.newChildElement("bebop:eventValue", BEBOP_XML_NS); + eventValue.addAttribute(NAME, m_controlValue.getName()); + eventValue.setText(req.getParameter(m_controlValue.getName())); + + // Global parameters + Element globalState = root.newChildElement("bebop:params", BEBOP_XML_NS); + for (Iterator ii = getStateModel().getParameters(); ii.hasNext();) { + ParameterModel p = (ParameterModel) ii.next(); + if (!p.getName().startsWith(COMPONENT_PREFIX)) { + Element param = globalState.newChildElement("bebop:param", BEBOP_XML_NS); + param.addAttribute(NAME, p.getName()); + param.setText(String.valueOf(s.getValue(p))); + } + } + + showVisibility(s, this, root); + } + + /** + * @see showStructure(PageState, Element) + */ + private void showVisibility(PageState s, Component c, Element parent) { + HttpServletRequest req = s.getRequest(); + + Element cmp = parent.newChildElement("bebop:component", BEBOP_XML_NS); + cmp.addAttribute(NAME, getDebugLabel(c)); + cmp.addAttribute("idx", String.valueOf(stateIndex(c))); + cmp.addAttribute("isVisible", (s.isVisible(c) ? "yes" : "no")); + cmp.addAttribute("class", c.getClass().getName()); + + if (c.getKey() != null) { + String prefix = componentPrefix(c); + for (Iterator i = getStateModel().getParameters(); i.hasNext();) { + ParameterModel p = (ParameterModel) i.next(); + if (!p.getName().startsWith(prefix)) { + continue; + } + + Element param = parent.newChildElement("bebop:param", BEBOP_XML_NS); + param.addAttribute(NAME, unmangle(p.getName())); + param.addAttribute("defaultValue", + String.valueOf(req.getParameter(p.getName()))); + param.addAttribute("currentValue", String.valueOf(s.getValue(p))); + } + } + for (Iterator i = c.children(); i.hasNext();) { + showVisibility(s, ((Component) i.next()), cmp); + } + } + + private static String getDebugLabel(Component c) { + if (c.getKey() != null) { + return c.getKey(); + } + + String klass = c.getClass().getName(); + return klass.substring(klass.lastIndexOf(".") + 1, klass.length()); + } + + /** + * return a string that represents an ordered list of component ids used on the page. For + * situations where only the components present is of importance, this may be used by + * implementations of hashCode & equals + * + * @return + */ + public String getComponentString() { + Iterator it = m_componentMap.keySet().iterator(); + /*int hash = 0; + while (it.hasNext()) { + String componentId = (String)it.next(); + s_log.debug("component id = " + componentId); + hash = hash | componentId.hashCode(); + s_log.debug("hash so far = " + hash); + }*/ + Date start = new Date(); + + StringBuilder hashString = new StringBuilder(); + while (it.hasNext()) { + String componentId = (String) it.next(); + hashString.append(componentId); + } + s_log.debug("Time to create hashCode for page: " + (new Date().getTime() - start. + getTime())); + return hashString.toString(); + + } + } diff --git a/ccm-core/src/com/arsdigita/core/Initializer.java b/ccm-core/src/com/arsdigita/core/Initializer.java index cac3316e6..106eb44fa 100755 --- a/ccm-core/src/com/arsdigita/core/Initializer.java +++ b/ccm-core/src/com/arsdigita/core/Initializer.java @@ -190,7 +190,7 @@ public class Initializer extends CompoundInitializer { }); // Set system informations - loadSystemInformation(); +// loadSystemInformation(); // register the document converters Converter converter = new PDFConverter(); @@ -229,14 +229,14 @@ public class Initializer extends CompoundInitializer { s_log.info("Core init(DomainInitEvent) done"); } - private void loadSystemInformation() { - SystemInformation sysInfo = SystemInformation.getInstance(); - - // Hardcoded for now - sysInfo.put("version", "v2.1.0"); - sysInfo.put("appname", "ScientificCMS"); - sysInfo.put("apphomepage", "http://www.scientificcms.org"); - sysInfo.lock(); - } +// private void loadSystemInformation() { +// SystemInformation sysInfo = SystemInformation.getInstance(); +// +// // Hardcoded for now +// sysInfo.put("version", "v2.3.x-SNAPSHOT"); +// sysInfo.put("appname", "ScientificCMS"); +// sysInfo.put("apphomepage", "http://www.scientificcms.org"); +// sysInfo.lock(); +// } } diff --git a/ccm-core/src/com/arsdigita/kernel/KernelConfig_parameter.properties b/ccm-core/src/com/arsdigita/kernel/KernelConfig_parameter.properties index 996cfb321..0db71c6a2 100755 --- a/ccm-core/src/com/arsdigita/kernel/KernelConfig_parameter.properties +++ b/ccm-core/src/com/arsdigita/kernel/KernelConfig_parameter.properties @@ -2,35 +2,43 @@ waf.debug.title=Global debug flag waf.debug.purpose=Enables or disables WAF debugging waf.debug.example=true waf.debug.format=true|false + waf.kernel.data_permission_check_enabled.title=DML permission checking flag waf.kernel.data_permission_check_enabled.purpose=Enables or disables permissions checks on database writes waf.kernel.data_permission_check_enabled.example=true waf.kernel.data_permission_check_enabled.format=true|false + waf.kernel.primary_user_identifier.title=The primary user identification waf.kernel.primary_user_identifier.purpose=Determines whether email addresses or screen names are used to authenticate users waf.kernel.primary_user_identifier.example=email waf.kernel.primary_user_identifier.format=email|screen_name + waf.kernel.remember_login.title=Remember login by default waf.kernel.remember_login.purpose=Determines whether the "remember login" feature is enabled or disabled by default waf.kernel.remember_login.example=true waf.kernel.remember_login.format=true|false + waf.kernel.secure_login.title=Require secure login waf.kernel.secure_login.purpose=Accept only credentials presented over secure connection waf.kernel.secure_login.example=true waf.kernel.secure_login.format=true|false + waf.kernel.sso_login.title=Enable SSO login waf.kernel.sso_login.purpose=Enable alternative "RegisterSSO" login context. waf.kernel.sso_login.example=false waf.kernel.sso_login.format=true|false + waf.kernel.supported_languages.title=Set the supported languages for categorization waf.kernel.supported_languages.purpose=Set the supported languages for categorization. First entry is the default language waf.kernel.supported_languages.example=en,de,fr,nl,it,pt,es waf.kernel.supported_languages.format=[string] + waf.kernel.language_independent_items.title=Allow language independent content items waf.kernel.language_independent_items.purpose=Allow language independent content items waf.kernel.language_independent_items.example=false waf.kernel.language_independent_items.format=true|false + waf.kernel.language_independent_code.title=Select language independent code waf.kernel.language_independent_code.purpose=Allow language independent code waf.kernel.language_independent_code.example=-- -waf.kernel.language_independent_code.format=[string] +waf.kernel.language_independent_code.format=[string] \ No newline at end of file diff --git a/ccm-core/src/com/arsdigita/util/SystemInformation.java b/ccm-core/src/com/arsdigita/util/SystemInformation.java index b73560763..60c804927 100644 --- a/ccm-core/src/com/arsdigita/util/SystemInformation.java +++ b/ccm-core/src/com/arsdigita/util/SystemInformation.java @@ -4,63 +4,84 @@ */ package com.arsdigita.util; +import com.arsdigita.runtime.AbstractConfig; +import com.arsdigita.util.parameter.Parameter; +import com.arsdigita.util.parameter.StringParameter; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import java.util.Set; /** * * @author Sören Bernstein + * @author Jens Pelzetter */ -public class SystemInformation implements Lockable { +public class SystemInformation extends AbstractConfig { //implements Lockable { - private Map systemInformation = new HashMap(); - private boolean locked = false; + private Parameter sysInfoParam = new StringParameter( + "ccm.systeminformation", + Parameter.REQUIRED, + "version::2.x.y; appname::LibreCCM; apphomepage::http://www.libreccm.org;"); + + private Map systemInformation;// = new HashMap(); + //private boolean locked = false; /** * The one and only instance of this class */ - private static final SystemInformation INSTANCE = new SystemInformation(); + private static SystemInformation INSTANCE;// = new SystemInformation(); - private SystemInformation() { - // Nothing + public SystemInformation() { + register(sysInfoParam); + + loadInfo(); } /** * @return The instance of this class. */ public static SystemInformation getInstance() { - return SystemInformation.INSTANCE; - } - - /** - * Put system information into the map. If this instance is locked, this method - * throw an {@link AssertionError}. - * - * @param key Key for the Map. Also used as attribute name during output. - * @param value Value - * @throws IllegalArgumentException if key or value is null or empty - */ - final public void put(String key, String value) throws IllegalArgumentException { - if (key == null || key.isEmpty()) { - throw new IllegalArgumentException("Parameter key must not be null or empty."); - } - if (value == null || value.isEmpty()) { - throw new IllegalArgumentException("Parameter value must not be null or empty."); - } - // Test if instance is not locked - Assert.isUnlocked(this); - systemInformation.put(key, value); + if (INSTANCE == null) { + INSTANCE = new SystemInformation(); + INSTANCE.load(); + } + + return INSTANCE; } +// /** +// * Put system information into the map. If this instance is locked, this method throw an +// * {@link AssertionError}. +// * +// * @param key Key for the Map. Also used as attribute name during output. +// * @param value Value +// * +// * @throws IllegalArgumentException if key or value is null or empty +// */ +// final public void put(final String key, final String value) throws IllegalArgumentException { +// if (key == null || key.isEmpty()) { +// throw new IllegalArgumentException("Parameter key must not be null or empty."); +// } +// if (value == null || value.isEmpty()) { +// throw new IllegalArgumentException("Parameter value must not be null or empty."); +// } +// // Test if instance is not locked +// Assert.isUnlocked(this); +// systemInformation.put(key, value); +// } /** * Get system informations by key. - * + * * @param key Key for the map + * * @return value for key + * * @throws IllegalArgumentException if key is null or empty */ final public String get(String key) throws IllegalArgumentException { + if (systemInformation == null) { + loadMap(); + } + if (key == null || key.isEmpty()) { throw new IllegalArgumentException("Parameter key must not be null or empty."); } @@ -69,32 +90,59 @@ public class SystemInformation implements Lockable { /** * Get iterator of this map. - * + * * @return iterator of map */ final public Iterator> iterator() { - return ((Set>) systemInformation.entrySet()).iterator(); - } - - /** - * - * @return - */ - final public boolean isEmpty() { - return systemInformation.isEmpty(); - } - /** - * Lock this instance to prevent further changes. - */ - final public void lock() { - locked = true; + if (systemInformation == null) { + loadMap(); + } + + return (systemInformation.entrySet()).iterator(); } /** - * Test, if this instance is locked. - * @return locked + * + * @return */ - final public boolean isLocked() { - return locked; + final public boolean isEmpty() { + if (systemInformation == null) { + loadMap(); + } + + return systemInformation.isEmpty(); + } + + /** + * Lock this instance to prevent further changes. + */ +// final public void lock() { +// locked = true; +// } +// +// /** +// * Test, if this instance is locked. +// * +// * @return locked +// */ +// final public boolean isLocked() { +// return locked; +// } + private void loadMap() { + systemInformation = new HashMap(); + + final String[] tokens = ((String) get(sysInfoParam)).split(";"); + for (String token : tokens) { + processToken(token); + } + } + + private void processToken(final String token) { + final String[] parts = token.split("::"); + if (2 == parts.length) { + systemInformation.put(parts[0].trim(), parts[1].trim()); + } + } + } diff --git a/ccm-sci-publications/application.xml b/ccm-sci-publications/application.xml index 2492882f0..ce166cb3a 100644 --- a/ccm-sci-publications/application.xml +++ b/ccm-sci-publications/application.xml @@ -2,7 +2,7 @@ diff --git a/ccm-sci-publications/pdl/com/arsdigita/content-types/Publication.pdl b/ccm-sci-publications/pdl/com/arsdigita/content-types/Publication.pdl index 27a106995..289fc619b 100644 --- a/ccm-sci-publications/pdl/com/arsdigita/content-types/Publication.pdl +++ b/ccm-sci-publications/pdl/com/arsdigita/content-types/Publication.pdl @@ -26,8 +26,8 @@ import com.arsdigita.cms.ContentBundle; object type Publication extends ContentPage { Integer[0..1] yearOfPublication = ct_publications.year INTEGER; - String[0..1] abstract = ct_publications.abstract VARCHAR(4096); - String[0..1] misc = ct_publications.misc VARCHAR(4096); + String[0..1] abstract = ct_publications.abstract CLOB; + String[0..1] misc = ct_publications.misc CLOB; //The reviewed property has been moved here for performance reasons. It //is necessary to have access to this property from a data query //over all publications of a person. Since this property was only diff --git a/ccm-sci-publications/sql/ccm-sci-publications/default/upgrade/6.6.6-6.6.7/abstract_to_text.sql b/ccm-sci-publications/sql/ccm-sci-publications/default/upgrade/6.6.6-6.6.7/abstract_to_text.sql new file mode 100644 index 000000000..51a858d4c --- /dev/null +++ b/ccm-sci-publications/sql/ccm-sci-publications/default/upgrade/6.6.6-6.6.7/abstract_to_text.sql @@ -0,0 +1,3 @@ +-- Alter abstract and misc column type to text +ALTER TABLE ct_publications ALTER COLUMN abstract TYPE text; +ALTER TABLE ct_publications ALTER COLUMN misc TYPE text; \ No newline at end of file diff --git a/ccm-sci-publications/sql/ccm-sci-publications/upgrade/postgres-6.6.6-6.6.7.sql b/ccm-sci-publications/sql/ccm-sci-publications/upgrade/postgres-6.6.6-6.6.7.sql new file mode 100644 index 000000000..94fbd377c --- /dev/null +++ b/ccm-sci-publications/sql/ccm-sci-publications/upgrade/postgres-6.6.6-6.6.7.sql @@ -0,0 +1,8 @@ +\echo 'ScientificCMS Publications module 6.6.6 -> 6.6.7 Upgrade script (PostgreSQL)' + +begin; + +\i ../default/upgrade/6.6.6-6.6.7/abstract_to_text.sql + +end; + diff --git a/ccm-sci-publications/src/ccm-sci-publications.upgrade b/ccm-sci-publications/src/ccm-sci-publications.upgrade index d009d708d..1bd6ab285 100644 --- a/ccm-sci-publications/src/ccm-sci-publications.upgrade +++ b/ccm-sci-publications/src/ccm-sci-publications.upgrade @@ -18,4 +18,7 @@