diff --git a/config/alfresco/messages/webclient-config-admin-interpreter-help.properties b/config/alfresco/messages/webclient-config-admin-interpreter-help.properties new file mode 100755 index 0000000000..deb28ac6aa --- /dev/null +++ b/config/alfresco/messages/webclient-config-admin-interpreter-help.properties @@ -0,0 +1 @@ +configadmin_console.help=alfresco/messages/webclient-config-admin-interpreter-help.txt diff --git a/config/alfresco/messages/webclient-config-admin-interpreter-help.txt b/config/alfresco/messages/webclient-config-admin-interpreter-help.txt new file mode 100755 index 0000000000..d0459f5d4a --- /dev/null +++ b/config/alfresco/messages/webclient-config-admin-interpreter-help.txt @@ -0,0 +1,29 @@ +## +## Meta commands +## + +ok> help + + List this help. + +ok> r + + Repeat last command. + +ok> quit | exit + + Quit this console. + + +## +## Web Client Config Admin Commands +## + +ok> reload + + Re-load Web Client config from configured config sources (refer to web-client-application-context.xml) + + +## +## end +## diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index f637613589..699fbbbff4 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -1499,6 +1499,15 @@ workflow_last_command=Last command: workflow_duration=Duration: workflow_duration_ms=ms +# WebClient Config Admin Console messages +title_configadmin_console=Web Client Config Admin Console +configadmin_context=Context +configadmin_command=Command (type help for help) +configadmin_command_submit=Submit +configadmin_last_command=Last command: +configadmin_duration=Duration: +configadmin_duration_ms=ms + # OpenSearch messages show=Show opensearch=OpenSearch diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml index d715c0988f..11f536f5c7 100644 --- a/config/alfresco/web-client-application-context.xml +++ b/config/alfresco/web-client-application-context.xml @@ -2,8 +2,12 @@ + + + + - + classpath:alfresco/web-client-config.xml @@ -18,14 +22,228 @@ classpath:alfresco/web-client-config-workflow-actions.xml classpath:alfresco/extension/web-client-config-custom.xml jar:*!/META-INF/web-client-config-custom.xml + + + workspace://SpacesStore/${spaces.company_home.childname}/${spaces.dictionary.childname}/app:webclient_extension/cm:web-client-config-custom.xml + + + + + + + + - - + + + + + + + + + + + + + + + org.alfresco.cache.globalConfigCache + + + + + + + + + + + + + + + + org.alfresco.globalConfigTransactionalCache + + + 10 + + + + + + + + + + + + + org.alfresco.cache.evaluatorsCache + + + + + + + + + + + + + + + + org.alfresco.evaluatorsTransactionalCache + + + 10 + + + + + + + + + + + + + org.alfresco.cache.sectionsByAreaCache + + + + + + + + + + + + + + + + org.alfresco.sectionsByAreaTransactionalCache + + + 10 + + + + + + + + + + + + + org.alfresco.cache.sectionsCache + + + + + + + + + + + + + + + + org.alfresco.sectionsTransactionalCache + + + 10 + + + + + + + + + + + + + org.alfresco.cache.elementReadersCache + + + + + + + + + + + + + + + + org.alfresco.elementReadersTransactionalCache + + + 10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + alfresco.messages.webclient-config-admin-interpreter-help + + + + + + + + + + diff --git a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java index 0d2b3c6db5..5ba7aabb51 100644 --- a/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java +++ b/source/java/org/alfresco/web/app/AlfrescoNavigationHandler.java @@ -376,7 +376,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler if (obj != null && obj instanceof Boolean && ((Boolean)obj).booleanValue()) { - if (this.plainDialogContainer == null) + if ((this.plainDialogContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); @@ -391,7 +391,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler } else { - if (this.dialogContainer == null) + if ((this.dialogContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); @@ -427,7 +427,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler if (obj != null && obj instanceof Boolean && ((Boolean)obj).booleanValue()) { - if (this.plainWizardContainer == null) + if ((this.plainWizardContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); @@ -442,7 +442,7 @@ public class AlfrescoNavigationHandler extends NavigationHandler } else { - if (this.wizardContainer == null) + if ((this.wizardContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); diff --git a/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java b/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java index 25064720f7..8b3305194a 100644 --- a/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java +++ b/source/java/org/alfresco/web/app/AlfrescoVariableResolver.java @@ -129,7 +129,7 @@ public class AlfrescoVariableResolver extends DelegatingVariableResolver */ protected String getDialogContainer(FacesContext context) { - if (this.dialogContainer == null) + if ((this.dialogContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); @@ -151,7 +151,7 @@ public class AlfrescoVariableResolver extends DelegatingVariableResolver */ protected String getWizardContainer(FacesContext context) { - if (this.wizardContainer == null) + if ((this.wizardContainer == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService configSvc = Application.getConfigService(context); Config globalConfig = configSvc.getGlobalConfig(); diff --git a/source/java/org/alfresco/web/app/Application.java b/source/java/org/alfresco/web/app/Application.java index 3d6466399f..266f8bb020 100644 --- a/source/java/org/alfresco/web/app/Application.java +++ b/source/java/org/alfresco/web/app/Application.java @@ -88,6 +88,9 @@ public class Application private static String websitesFolderName; private static String contentFormsFolderName; + private static Boolean isDynamicConfig = null; + + /** * Private constructor to prevent instantiation of this class */ @@ -651,7 +654,7 @@ public class Application { locale = Locale.getDefault(); } - bundle = ResourceBundleWrapper.getResourceBundle(MESSAGE_BUNDLE, locale); + bundle = ResourceBundleWrapper.getResourceBundleWrapper(session.getServletContext()).getResourceBundle(MESSAGE_BUNDLE, locale); session.setAttribute(MESSAGE_BUNDLE, bundle); } @@ -682,7 +685,7 @@ public class Application { locale = Locale.getDefault(); } - bundle = ResourceBundleWrapper.getResourceBundle(MESSAGE_BUNDLE, locale); + bundle = ResourceBundleWrapper.getResourceBundleWrapper(FacesContextUtils.getRequiredWebApplicationContext(context).getServletContext()).getResourceBundle(MESSAGE_BUNDLE, locale); session.put(MESSAGE_BUNDLE, bundle); } @@ -991,4 +994,15 @@ public class Application return loginPage; } + + public static boolean isDynamicConfig(FacesContext context) + { + if (isDynamicConfig == null) + { + String dynamicConfigParam = FacesContextUtils.getRequiredWebApplicationContext(context).getServletContext().getInitParameter("org.alfresco.webclient.dynamicConfig"); + isDynamicConfig = new Boolean(((dynamicConfigParam == null) || (new Boolean(dynamicConfigParam).booleanValue() == true))); + } + + return isDynamicConfig.booleanValue(); + } } diff --git a/source/java/org/alfresco/web/app/ResourceBundleWrapper.java b/source/java/org/alfresco/web/app/ResourceBundleWrapper.java index e4ea3b4f53..e2274b0b79 100644 --- a/source/java/org/alfresco/web/app/ResourceBundleWrapper.java +++ b/source/java/org/alfresco/web/app/ResourceBundleWrapper.java @@ -24,15 +24,23 @@ */ package org.alfresco.web.app; +import java.io.InputStream; import java.util.Enumeration; import java.util.Locale; import java.util.MissingResourceException; +import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import java.util.Vector; +import javax.servlet.ServletContext; + import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.repo.i18n.MessageService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.web.bean.repository.Repository; import org.apache.log4j.Logger; import org.apache.log4j.Priority; +import org.springframework.web.context.support.WebApplicationContextUtils; /** * Wrapper around Alfresco Resource Bundle objects. Used to catch and handle missing @@ -48,6 +56,24 @@ public final class ResourceBundleWrapper extends ResourceBundle private ResourceBundle delegate; private ResourceBundle delegateCustom; + private MessageService messageService; + + public static final String BEAN_RESOURCE_BUNDLE_WRAPPER = "resourceBundleWrapper"; + + public static final String PATH = "app:company_home/app:dictionary/cm:webclient_extension"; + + public ResourceBundleWrapper(MessageService messageService) + { + this.messageService = messageService; + } + + // Helper to get the ResourceBundleWrapper instance with access to the repository + public static ResourceBundleWrapper getResourceBundleWrapper(ServletContext context) + { + return (ResourceBundleWrapper)WebApplicationContextUtils.getRequiredWebApplicationContext(context).getBean( + BEAN_RESOURCE_BUNDLE_WRAPPER); + } + /** * Constructor * @@ -139,7 +165,7 @@ public final class ResourceBundleWrapper extends ResourceBundle * * @return Wrapped ResourceBundle instance for specified locale */ - public static ResourceBundle getResourceBundle(String name, Locale locale) + public ResourceBundle getResourceBundle(String name, Locale locale) { ResourceBundle bundle = ResourceBundle.getBundle(name, locale); if (bundle == null) @@ -148,18 +174,55 @@ public final class ResourceBundleWrapper extends ResourceBundle } // also look up the custom version of the bundle in the extension package - String customName = determineCustomBundleName(name); ResourceBundle customBundle = null; + + // first try in the repo otherwise try the classpath + StoreRef storeRef = null; + String path = null; + try { - customBundle = ResourceBundle.getBundle(customName, locale); - - if (logger.isDebugEnabled()) - logger.debug("Located and loaded custom bundle: " + customName); + String customName = null; + int idx = name.lastIndexOf("."); + if (idx != -1) + { + customName = name.substring(idx+1, name.length()); + } + else + { + customName = name; + } + + storeRef = Repository.getStoreRef(); + + // TODO - make path configurable in one place ... + // Note: path here is XPath for selectNodes query + path = PATH + "/cm:" + customName; + InputStream is = messageService.getRepoResourceBundle(Repository.getStoreRef(), path, locale); + customBundle = new PropertyResourceBundle(is); + is.close(); } - catch (MissingResourceException mre) + catch (Throwable t) { - // ignore the error, just leave custom bundle as null + // for now ... ignore the error, cannot be found or read from repo + logger.debug("Custom Web Client properties not found: " + storeRef + path); + } + + if (customBundle == null) + { + // classpath + String customName = determineCustomBundleName(name); + try + { + customBundle = ResourceBundle.getBundle(customName, locale); + + if (logger.isDebugEnabled()) + logger.debug("Located and loaded custom bundle: " + customName); + } + catch (MissingResourceException mre) + { + // ignore the error, just leave custom bundle as null + } } // apply our wrapper to catch MissingResourceException diff --git a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java index d377e7f2d5..f9f91452f3 100644 --- a/source/java/org/alfresco/web/bean/AdvancedSearchBean.java +++ b/source/java/org/alfresco/web/bean/AdvancedSearchBean.java @@ -593,7 +593,7 @@ public class AdvancedSearchBean */ public List getContentTypes() { - if (this.contentTypes == null) + if ((this.contentTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); @@ -641,7 +641,7 @@ public class AdvancedSearchBean */ public List getFolderTypes() { - if (this.folderTypes == null) + if ((this.folderTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); @@ -689,7 +689,7 @@ public class AdvancedSearchBean */ public List getContentFormats() { - if (this.contentFormats == null) + if ((this.contentFormats == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { this.contentFormats = new ArrayList(80); ServiceRegistry registry = Repository.getServiceRegistry(FacesContext.getCurrentInstance()); @@ -813,11 +813,14 @@ public class AdvancedSearchBean search.addRangeQuery(ContentModel.PROP_MODIFIED, strModifiedDate, strModifiedDateTo, true); } + // in case of dynamic config, only lookup once + Map customPropertyLookup = getCustomPropertyLookup(); + // walk each of the custom properties add add them as additional attributes for (String qname : this.customProperties.keySet()) { Object value = this.customProperties.get(qname); - DataTypeDefinition typeDef = getCustomPropertyLookup().get(qname); + DataTypeDefinition typeDef = customPropertyLookup.get(qname); if (typeDef != null) { QName typeName = typeDef.getName(); @@ -1292,10 +1295,13 @@ public class AdvancedSearchBean this.panels.put(PANEL_ATTRS, true); } + // in case of dynamic config, only lookup once + Map customPropertyLookup = getCustomPropertyLookup(); + // custom fields - calculate which are required to set through the custom properties lookup table - for (String qname : getCustomPropertyLookup().keySet()) + for (String qname : customPropertyLookup.keySet()) { - DataTypeDefinition typeDef = getCustomPropertyLookup().get(qname); + DataTypeDefinition typeDef = customPropertyLookup.get(qname); if (typeDef != null) { QName typeName = typeDef.getName(); @@ -1523,7 +1529,7 @@ public class AdvancedSearchBean */ private AdvancedSearchConfigElement getSearchConfig() { - if (searchConfigElement == null) + if ((this.searchConfigElement == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { searchConfigElement = (AdvancedSearchConfigElement)Application.getConfigService( FacesContext.getCurrentInstance()).getConfig("Advanced Search"). @@ -1540,7 +1546,7 @@ public class AdvancedSearchBean */ private Map getCustomPropertyLookup() { - if (customPropertyLookup == null) + if ((customPropertyLookup == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { customPropertyLookup = new HashMap(7, 1.0f); List customProps = getSearchConfig().getCustomProperties(); diff --git a/source/java/org/alfresco/web/bean/BrowseBean.java b/source/java/org/alfresco/web/bean/BrowseBean.java index 02fe46edfa..2e7e4cc2b9 100644 --- a/source/java/org/alfresco/web/bean/BrowseBean.java +++ b/source/java/org/alfresco/web/bean/BrowseBean.java @@ -537,7 +537,11 @@ public class BrowseBean implements IContextListener */ public void addNodeEventListener(NodeEventListener listener) { - getNodeEventListeners().add(listener); + if (this.nodeEventListeners == null) + { + this.nodeEventListeners = new HashSet(); + } + this.nodeEventListeners.add(listener); } /** @@ -545,7 +549,10 @@ public class BrowseBean implements IContextListener */ public void removeNodeEventListener(NodeEventListener listener) { - getNodeEventListeners().remove(listener); + if (this.nodeEventListeners != null) + { + this.nodeEventListeners.remove(listener); + } } @@ -628,6 +635,10 @@ public class BrowseBean implements IContextListener List children = this.fileFolderService.list(parentRef); this.containerNodes = new ArrayList(children.size()); this.contentNodes = new ArrayList(children.size()); + + // in case of dynamic config, only lookup once + Set nodeEventListeners = getNodeEventListeners(); + for (FileInfo fileInfo : children) { // create our Node representation from the NodeRef @@ -691,7 +702,7 @@ public class BrowseBean implements IContextListener // inform any listeners that a Node wrapper has been created if (node != null) { - for (NodeEventListener listener : getNodeEventListeners()) + for (NodeEventListener listener : nodeEventListeners) { listener.created(node, type); } @@ -785,6 +796,9 @@ public class BrowseBean implements IContextListener this.contentNodes = new ArrayList(results.length()); if (results.length() != 0) { + // in case of dynamic config, only lookup once + Set nodeEventListeners = getNodeEventListeners(); + for (ResultSetRow row: results) { NodeRef nodeRef = row.getNodeRef(); @@ -859,7 +873,7 @@ public class BrowseBean implements IContextListener // inform any listeners that a Node wrapper has been created if (node != null) { - for (NodeEventListener listener : getNodeEventListeners()) + for (NodeEventListener listener : nodeEventListeners) { listener.created(node, type); } @@ -1555,6 +1569,7 @@ public class BrowseBean implements IContextListener */ private void initFromClientConfig() { + // TODO - review implications of these default values on dynamic/MT client: viewsConfig & browseViewMode, as well as page size content/spaces ... ConfigService config = Application.getConfigService(FacesContext.getCurrentInstance()); this.viewsConfig = (ViewsConfigElement)config.getConfig("Views"). @@ -1571,33 +1586,49 @@ public class BrowseBean implements IContextListener */ private Set getNodeEventListeners() { - if (this.nodeEventListeners == null) - { - this.nodeEventListeners = new HashSet(); + if ((this.nodeEventListeners == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) + { + Set allNodeEventListeners = new HashSet(); - FacesContext fc = FacesContext.getCurrentInstance(); + if (Application.isDynamicConfig(FacesContext.getCurrentInstance()) && (this.nodeEventListeners != null)) + { + // for dynamic config, can add/remove node event listeners dynamically ... + // however, in case anyone is using public methods (add/removeNodeEventListener) + // we merge list here with list returned from the config + allNodeEventListeners.addAll(this.nodeEventListeners); + } - Config listenerConfig = Application.getConfigService(fc).getConfig("Node Event Listeners"); - if (listenerConfig != null) - { - ConfigElement listenerElement = listenerConfig.getConfigElement("node-event-listeners"); - if (listenerElement != null) - { - for (ConfigElement child : listenerElement.getChildren()) - { - if (child.getName().equals("listener")) - { - // retrieved the JSF Managed Bean identified in the config - String listenerName = child.getValue().trim(); - Object bean = FacesHelper.getManagedBean(fc, listenerName); - if (bean instanceof NodeEventListener) - { - addNodeEventListener((NodeEventListener)bean); - } - } - } - } - } + FacesContext fc = FacesContext.getCurrentInstance(); + Config listenerConfig = Application.getConfigService(fc).getConfig("Node Event Listeners"); + if (listenerConfig != null) + { + ConfigElement listenerElement = listenerConfig.getConfigElement("node-event-listeners"); + if (listenerElement != null) + { + for (ConfigElement child : listenerElement.getChildren()) + { + if (child.getName().equals("listener")) + { + // retrieved the JSF Managed Bean identified in the config + String listenerName = child.getValue().trim(); + Object bean = FacesHelper.getManagedBean(fc, listenerName); + if (bean instanceof NodeEventListener) + { + allNodeEventListeners.add((NodeEventListener)bean); + } + } + } + } + } + + if (Application.isDynamicConfig(FacesContext.getCurrentInstance())) + { + return allNodeEventListeners; + } + else + { + this.nodeEventListeners = allNodeEventListeners; + } } return this.nodeEventListeners; } diff --git a/source/java/org/alfresco/web/bean/ConfigAdminConsoleBean.java b/source/java/org/alfresco/web/bean/ConfigAdminConsoleBean.java new file mode 100755 index 0000000000..87ec8c58cf --- /dev/null +++ b/source/java/org/alfresco/web/bean/ConfigAdminConsoleBean.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.bean; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.alfresco.web.config.ConfigAdminInterpreter; + + +/** + * Backing bean to support the Web Client Config Admin Console + */ +public class ConfigAdminConsoleBean +{ + // command + private String command = ""; + private String submittedCommand = "none"; + private long duration = 0L; + private String result = null; + + // supporting repository services + private ConfigAdminInterpreter configAdminInterpreter; + + + /** + * @param configAdminInterpreter Web Client config admin interpreter + */ + public void setConfigAdminInterpreter(ConfigAdminInterpreter configAdminInterpreter) + { + this.configAdminInterpreter = configAdminInterpreter; + } + + /** + * Gets the command result + * + * @return result + */ + public String getResult() + { + if (result == null) + { + interpretCommand("help"); + } + return result; + } + + /** + * Sets the command result + * + * @param result + */ + public void setResult(String result) + { + this.result = result; + } + + /** + * Gets the current query + * + * @return query statement + */ + public String getCommand() + { + return command; + } + + /** + * Set the current command + * + * @param command command + */ + public void setCommand(String command) + { + this.command = command; + } + + /** + * Gets the submitted command + * + * @return submitted command + */ + public String getSubmittedCommand() + { + return submittedCommand; + } + + /** + * Set the submitted command + * + * @param submittedCommand The submitted command + */ + public void setSubmittedCommand(String submittedCommand) + { + this.submittedCommand = submittedCommand; + } + + /** + * Gets the last command duration + * + * @return command duration + */ + public long getDuration() + { + return duration; + } + + /** + * Set the duration + * + * @param duration The duration + */ + public void setDuration(long duration) + { + this.duration = duration; + } + + /** + * Action to submit command + * + * @return next action + */ + public String submitCommand() + { + interpretCommand(command); + return "success"; + } + + /** + * Gets the current user name + * + * @return user name + */ + public String getCurrentUserName() + { + return configAdminInterpreter.getCurrentUserName(); + } + + /** + * Interpret repo admin console command + * + * @param command command + */ + private void interpretCommand(String command) + { + try + { + long startms = System.currentTimeMillis(); + String result = configAdminInterpreter.interpretCommand(command); + setDuration(System.currentTimeMillis() - startms); + setResult(result); + setCommand(""); + setSubmittedCommand(command); + } + catch (Exception e) + { + StringWriter stackTrace = new StringWriter(); + e.printStackTrace(new PrintWriter(stackTrace)); + setResult(stackTrace.toString()); + } + } + +} diff --git a/source/java/org/alfresco/web/bean/DocumentPropertiesBean.java b/source/java/org/alfresco/web/bean/DocumentPropertiesBean.java index 596c2aaca7..1197eb518e 100644 --- a/source/java/org/alfresco/web/bean/DocumentPropertiesBean.java +++ b/source/java/org/alfresco/web/bean/DocumentPropertiesBean.java @@ -350,7 +350,7 @@ public class DocumentPropertiesBean */ public boolean getOtherPropertiesPresent() { - if (this.hasOtherProperties == null) + if ((this.hasOtherProperties == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { // we need to use the config service to see whether there are any // editable properties configured for this document. diff --git a/source/java/org/alfresco/web/bean/LoginBean.java b/source/java/org/alfresco/web/bean/LoginBean.java index 043df18922..03b2ceff1d 100644 --- a/source/java/org/alfresco/web/bean/LoginBean.java +++ b/source/java/org/alfresco/web/bean/LoginBean.java @@ -292,6 +292,11 @@ public class LoginBean else { // special case to handle jump to My Alfresco page initially + + // note: to enable MT runtime client config customization, need to re-init NavigationBean + // in context of tenant login page + this.navigator.initFromClientConfig(); + if (NavigationBean.LOCATION_MYALFRESCO.equals(this.preferences.getStartLocation())) { return "myalfresco"; diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java index c79ba2715b..9a242bca4b 100644 --- a/source/java/org/alfresco/web/bean/NavigationBean.java +++ b/source/java/org/alfresco/web/bean/NavigationBean.java @@ -844,12 +844,14 @@ public class NavigationBean // ------------------------------------------------------------------------------ - // Private helpers + // Helpers /** * Initialise default values from client configuration + * + * Package visibility to allow LoginBean to re-init (for example, in context of tenant config) */ - private void initFromClientConfig() + /* package */ void initFromClientConfig() { this.clientConfig = Application.getClientConfig(FacesContext.getCurrentInstance()); this.helpUrl = clientConfig.getHelpUrl(); diff --git a/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java b/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java index 7dca58f519..ec0fba33e5 100644 --- a/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java +++ b/source/java/org/alfresco/web/bean/actions/BaseActionWizard.java @@ -247,7 +247,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getRemovableAspects() { - if (this.removableAspects == null) + if ((this.removableAspects == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { // get the list of common aspects this.removableAspects = new ArrayList(); @@ -289,7 +289,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getAddableAspects() { - if (this.addableAspects == null) + if ((this.addableAspects == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { // get the list of common aspects this.addableAspects = new ArrayList(); @@ -331,7 +331,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getTestableAspects() { - if (this.testableAspects == null) + if ((this.testableAspects == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { // get the list of common aspects this.testableAspects = new ArrayList(); @@ -371,7 +371,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getObjectTypes() { - if (this.objectTypes == null) + if ((this.objectTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); @@ -477,7 +477,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getTransformers() { - if (this.transformers == null) + if ((this.transformers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance()); Config wizardCfg = svc.getConfig("Action Wizards"); @@ -530,7 +530,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ public List getImageTransformers() { - if (this.imageTransformers == null) + if ((this.imageTransformers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance()); Config wizardCfg = svc.getConfig("Action Wizards"); @@ -891,7 +891,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ protected void initialiseActionHandlers() { - if (this.actionHandlers == null) + if ((this.actionHandlers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance()); Config wizardCfg = svc.getConfig("Action Wizards"); @@ -944,7 +944,7 @@ public abstract class BaseActionWizard extends BaseWizardBean */ protected List getCommonAspects() { - if (this.commonAspects == null) + if ((this.commonAspects == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance()); Config wizardCfg = svc.getConfig("Action Wizards"); diff --git a/source/java/org/alfresco/web/bean/content/AddContentDialog.java b/source/java/org/alfresco/web/bean/content/AddContentDialog.java index 40c11a8732..833fff7c51 100644 --- a/source/java/org/alfresco/web/bean/content/AddContentDialog.java +++ b/source/java/org/alfresco/web/bean/content/AddContentDialog.java @@ -282,7 +282,7 @@ public class AddContentDialog extends BaseContentWizard protected List getInlineEditableMimeTypes() { - if (this.inlineEditableMimeTypes == null) + if ((this.inlineEditableMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { this.inlineEditableMimeTypes = new ArrayList(8); diff --git a/source/java/org/alfresco/web/bean/content/BaseContentWizard.java b/source/java/org/alfresco/web/bean/content/BaseContentWizard.java index a2ee002e96..21760b214d 100644 --- a/source/java/org/alfresco/web/bean/content/BaseContentWizard.java +++ b/source/java/org/alfresco/web/bean/content/BaseContentWizard.java @@ -285,7 +285,7 @@ public abstract class BaseContentWizard extends BaseWizardBean */ public List getObjectTypes() { - if (this.objectTypes == null) + if ((this.objectTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); @@ -493,6 +493,7 @@ public abstract class BaseContentWizard extends BaseWizardBean */ protected void initOtherProperties() { + // TODO - review implications of these default values for dynamic/MT client ConfigService configSvc = Application.getConfigService(FacesContext.getCurrentInstance()); if (configSvc != null) diff --git a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java index aac67b2979..0d3d4359f5 100644 --- a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java +++ b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java @@ -146,7 +146,7 @@ public class CreateContentWizard extends BaseContentWizard */ public List getCreateMimeTypes() { - if (this.createMimeTypes == null) + if ((this.createMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); diff --git a/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java b/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java index bb846ab33d..978beac8d1 100644 --- a/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java +++ b/source/java/org/alfresco/web/bean/dashboard/DashboardWizard.java @@ -224,7 +224,7 @@ public class DashboardWizard extends BaseWizardBean */ public List getAllDashlets() { - if (this.dashlets == null) + if ((this.dashlets == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext fc = FacesContext.getCurrentInstance(); DashboardsConfigElement config = DashboardManager.getDashboardConfig(); @@ -282,7 +282,7 @@ public class DashboardWizard extends BaseWizardBean */ public List getLayoutDescriptions() { - if (this.layoutDescriptions == null) + if ((this.layoutDescriptions == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { buildLayoutValueLists(); } @@ -294,7 +294,7 @@ public class DashboardWizard extends BaseWizardBean */ public List getLayoutIcons() { - if (this.layoutIcons == null) + if ((this.layoutIcons == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { buildLayoutValueLists(); } diff --git a/source/java/org/alfresco/web/bean/forums/ForumsBean.java b/source/java/org/alfresco/web/bean/forums/ForumsBean.java index 4ba07a70f8..1956cdf738 100644 --- a/source/java/org/alfresco/web/bean/forums/ForumsBean.java +++ b/source/java/org/alfresco/web/bean/forums/ForumsBean.java @@ -890,6 +890,7 @@ public class ForumsBean implements IContextListener */ private void initFromClientConfig() { + // TODO - review implications of these default values for dynamic/MT client this.viewsConfig = (ViewsConfigElement)Application.getConfigService( FacesContext.getCurrentInstance()).getConfig("Views"). getConfigElement(ViewsConfigElement.CONFIG_ELEMENT_ID); diff --git a/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java b/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java index 4728205656..1029e77309 100644 --- a/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java +++ b/source/java/org/alfresco/web/bean/rules/CreateRuleWizard.java @@ -286,7 +286,7 @@ public class CreateRuleWizard extends BaseActionWizard */ public List getModelTypes() { - if (this.modelTypes == null) + if ((this.modelTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); ConfigService svc = Application.getConfigService(context); @@ -772,7 +772,7 @@ public class CreateRuleWizard extends BaseActionWizard */ protected void initialiseConditionHandlers() { - if (this.conditionHandlers == null) + if ((this.conditionHandlers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance()); Config wizardCfg = svc.getConfig("Action Wizards"); diff --git a/source/java/org/alfresco/web/bean/spaces/CreateSpaceWizard.java b/source/java/org/alfresco/web/bean/spaces/CreateSpaceWizard.java index 465d680683..96177775c3 100644 --- a/source/java/org/alfresco/web/bean/spaces/CreateSpaceWizard.java +++ b/source/java/org/alfresco/web/bean/spaces/CreateSpaceWizard.java @@ -522,7 +522,7 @@ public class CreateSpaceWizard extends BaseWizardBean @SuppressWarnings("unchecked") public List getFolderTypes() { - if (this.folderTypes == null) + if ((this.folderTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext context = FacesContext.getCurrentInstance(); this.folderTypes = new ArrayList(2); @@ -637,7 +637,7 @@ public class CreateSpaceWizard extends BaseWizardBean */ public List getFolderTypeDescriptions() { - if (this.folderTypeDescriptions == null) + if ((this.folderTypeDescriptions == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { // call the getFolderType method to construct the list getFolderTypes(); diff --git a/source/java/org/alfresco/web/bean/wcm/AVMUtil.java b/source/java/org/alfresco/web/bean/wcm/AVMUtil.java index 6b6d9d0f00..c72f89f309 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMUtil.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMUtil.java @@ -1034,7 +1034,7 @@ public final class AVMUtil private static ConfigElement getDeploymentConfig() { - if (deploymentConfig == null) + if ((deploymentConfig == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService cfgService = Application.getConfigService(FacesContext.getCurrentInstance()); ConfigElement wcmCfg = cfgService.getGlobalConfig().getConfigElement("wcm"); @@ -1049,7 +1049,7 @@ public final class AVMUtil private static ConfigElement getLinksManagementConfig() { - if (linksManagementConfig == null) + if ((linksManagementConfig == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { ConfigService cfgService = Application.getConfigService(FacesContext.getCurrentInstance()); ConfigElement wcmCfg = cfgService.getGlobalConfig().getConfigElement("wcm"); diff --git a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java index 6af9b34909..40048fa990 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMWorkflowUtil.java @@ -188,7 +188,7 @@ public class AVMWorkflowUtil extends WorkflowUtil */ public static List getConfiguredWorkflows() { - if (configuredWorkflowDefs == null) + if ((configuredWorkflowDefs == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext fc = FacesContext.getCurrentInstance(); List defs = Collections.emptyList(); diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index f92c5164a7..ed86c5324c 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -622,7 +622,7 @@ public class CreateWebContentWizard extends BaseContentWizard */ public List getCreateMimeTypes() { - if (this.createMimeTypes == null) + if ((this.createMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { final FacesContext context = FacesContext.getCurrentInstance(); diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java index 0918ff7a30..f75080e387 100644 --- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java +++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java @@ -662,9 +662,9 @@ public class StartWorkflowWizard extends BaseWizardBean * @return The configured comma separated list of WCM workflows, if the config * can not be found an empty string will be returned */ - protected Map getWCMWorkflows() + protected Map getWCMWorkflows() { - if (wcmWorkflows == null) + if ((wcmWorkflows == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance()))) { FacesContext fc = FacesContext.getCurrentInstance(); ConfigElement config = Application.getConfigService(fc).getGlobalConfig().getConfigElement("wcm"); diff --git a/source/java/org/alfresco/web/config/ConfigAdminInterpreter.java b/source/java/org/alfresco/web/config/ConfigAdminInterpreter.java new file mode 100755 index 0000000000..f8ad9df415 --- /dev/null +++ b/source/java/org/alfresco/web/config/ConfigAdminInterpreter.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.config; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.List; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.admin.BaseInterpreter; +import org.alfresco.repo.config.xml.RepoXMLConfigService; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.ParameterCheck; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.ClassPathResource; + +/** + * A simple interactive console for (first cut) Web Client Config Admin. + * + */ +public class ConfigAdminInterpreter extends BaseInterpreter +{ + // dependencies + private RepoXMLConfigService webClientConfigService; + + public void setRepoXMLConfigService(RepoXMLConfigService webClientConfigService) + { + this.webClientConfigService = webClientConfigService; + } + + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + + /** + * + */ + public static BaseInterpreter getConsoleBean(ApplicationContext context) + { + return (ConfigAdminInterpreter)context.getBean("webClientConfigAdminInterpreter"); + } + + protected boolean hasAuthority(String username) + { + return ((username != null) && (tenantService.getBaseNameUser(username).equals(BaseInterpreter.DEFAULT_ADMIN))); + } + + /** + * Execute a single command using the BufferedReader passed in for any data needed. + * + * TODO: Use decent parser! + * + * @param line The unparsed command + * @return The textual output of the command. + */ + protected String executeCommand(String line) + throws IOException + { + String[] command = line.split(" "); + if (command.length == 0) + { + command = new String[1]; + command[0] = line; + } + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + + // repeat last command? + if (command[0].equals("r")) + { + if (lastCommand == null) + { + return "No command entered yet."; + } + return "repeating command " + lastCommand + "\n\n" + executeCommand(lastCommand); + } + + // remember last command + lastCommand = line; + + // execute command + if (command[0].equals("help")) + { + String helpFile = I18NUtil.getMessage("configadmin_console.help"); + ClassPathResource helpResource = new ClassPathResource(helpFile); + byte[] helpBytes = new byte[500]; + InputStream helpStream = helpResource.getInputStream(); + try + { + int read = helpStream.read(helpBytes); + while (read != -1) + { + bout.write(helpBytes, 0, read); + read = helpStream.read(helpBytes); + } + } + finally + { + helpStream.close(); + } + } + + else if (command[0].equals("reload")) + { + if (command.length > 1) + { + return "Syntax Error.\n"; + } + + // destroy and re-initialise config service + webClientConfigService.reset(); + + out.println("Web Client config has been reloaded"); + } + + else + { + return "No such command, try 'help'.\n"; + } + + out.flush(); + String retVal = new String(bout.toByteArray()); + out.close(); + return retVal; + } +} \ No newline at end of file diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index fc9ede36b3..cb461b3c28 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -2348,6 +2348,17 @@ workflowInterpreter #{workflowInterpreter} + + + + Backing bean used for the Web Client Config Admin Console + ConfigAdminConsoleBean + org.alfresco.web.bean.ConfigAdminConsoleBean + session + + configAdminInterpreter + #{webClientConfigAdminInterpreter} + diff --git a/source/web/jsp/admin/webclientconfig-console.jsp b/source/web/jsp/admin/webclientconfig-console.jsp new file mode 100755 index 0000000000..c938e0ef79 --- /dev/null +++ b/source/web/jsp/admin/webclientconfig-console.jsp @@ -0,0 +1,107 @@ +<%-- + * Copyright (C) 2005-2007 Alfresco Software Limited. + + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" +--%> +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> +<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %> + + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + + + + + + +
+ + + + + +
+ +
+ +
+ + + + + + + +
User:
+ +
+ + + + + + + + + +
+ + + +
+
+ + + + + + + + +
+
+
+ ----- +
+
+
+ +
+ +
+ +