diff --git a/config/alfresco/extension/web-client-rm-custom.xml.sample b/config/alfresco/extension/web-client-rm-custom.xml.sample new file mode 100644 index 0000000000..7854de078c --- /dev/null +++ b/config/alfresco/extension/web-client-rm-custom.xml.sample @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 4dfab5ca5a..e0cd825e02 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -93,7 +93,6 @@ no_categories_applied_space=This space does not yet have any categories applied. has_following_categories_space=This space has the following categories applied... moved=moved copied=copied -document_action=The document will be {0} to ''{1}'' if the ''{2}'' action is taken. clipboard=Clipboard recent_spaces=Recent Spaces shortcuts=Shortcuts @@ -527,7 +526,6 @@ custom_view=Custom View view_links=Links not_inline_editable=This document is not inline editable. allow_inline_editing=Allow Inline Editing -not_in_workflow=This document is not part of any workflow. not_in_category=This document is not categorized. not_in_category_space=This space is not categorized. not_versioned=This document has no version history. @@ -1161,6 +1159,15 @@ admin_limited_license=Licensed: {0} license granted to {1} and limited to {3} da admin_unlimited_license=Licensed: {0} license granted to {1} and does not expire (issued on {2,date,short}). admin_invalid_license=Licensed: LICENSE INVALID - Alfresco Repository restricted to read-only capability. +# Workflow Console messages +title_workflow_console=Workflow Console +workflow_context=Context +workflow_command=Command (type help for help) +workflow_command_submit=Submit +workflow_last_command=Last command: +workflow_duration=Duration: +workflow_duration_ms=ms + # UI Page Titles title_about=About Alfresco title_login=Alfresco Web Client - Login diff --git a/config/alfresco/web-client-application-context.xml b/config/alfresco/web-client-application-context.xml index f43adab142..1a3c05c9b8 100644 --- a/config/alfresco/web-client-application-context.xml +++ b/config/alfresco/web-client-application-context.xml @@ -16,6 +16,7 @@ classpath:alfresco/web-client-config-wcm-actions.xml classpath:alfresco/web-client-config-workflow-actions.xml classpath:alfresco/extension/web-client-config-custom.xml + classpath:alfresco/extension/web-client-rm-custom.xml diff --git a/config/alfresco/web-client-config-actions.xml b/config/alfresco/web-client-config-actions.xml index cefde01e6a..2d3559591c 100644 --- a/config/alfresco/web-client-config-actions.xml +++ b/config/alfresco/web-client-config-actions.xml @@ -392,7 +392,7 @@ - ChangePermissions + CreateChildren advanced_space_wizard /images/icons/create_space.gif diff --git a/config/alfresco/web-client-config-properties.xml b/config/alfresco/web-client-config-properties.xml index 84c9cde9b5..01f56d7b85 100644 --- a/config/alfresco/web-client-config-properties.xml +++ b/config/alfresco/web-client-config-properties.xml @@ -26,30 +26,6 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + @@ -337,145 +313,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/alfresco/web-client-config.xml b/config/alfresco/web-client-config.xml index 9e5ffd48c4..6d4a92244a 100644 --- a/config/alfresco/web-client-config.xml +++ b/config/alfresco/web-client-config.xml @@ -46,6 +46,9 @@ -1 + + 500 + @@ -164,16 +167,6 @@ - - - - - - - - - - @@ -267,13 +260,6 @@ - - - - - - - diff --git a/source/java/org/alfresco/web/action/evaluator/CancelWorkflowEvaluator.java b/source/java/org/alfresco/web/action/evaluator/CancelWorkflowEvaluator.java index cdefed2495..86a7219a8c 100644 --- a/source/java/org/alfresco/web/action/evaluator/CancelWorkflowEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/CancelWorkflowEvaluator.java @@ -21,7 +21,6 @@ import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.util.ISO9075; import org.alfresco.web.action.ActionEvaluator; @@ -45,37 +44,28 @@ public class CancelWorkflowEvaluator implements ActionEvaluator public boolean evaluate(Node node) { boolean result = false; - - // get the id of the task - String taskId = (String)node.getProperties().get("id"); - if (taskId != null) + FacesContext context = FacesContext.getCurrentInstance(); + + // get the task from the node + WorkflowTask task = (WorkflowTask)node.getProperties().get("workflowTask"); + if (task != null) { - FacesContext context = FacesContext.getCurrentInstance(); - - // get the initiator of the workflow the task belongs to - WorkflowService workflowSvc = Repository.getServiceRegistry( - context).getWorkflowService(); - - WorkflowTask task = workflowSvc.getTaskById(taskId); - if (task != null) + NodeRef initiator = task.path.instance.initiator; + if (initiator != null) { - NodeRef initiator = task.path.instance.initiator; - if (initiator != null) + // find the current username + User user = Application.getCurrentUser(context); + String currentUserName = ISO9075.encode(user.getUserName()); + + // get the username of the initiator + NodeService nodeSvc = Repository.getServiceRegistry( + context).getNodeService(); + String userName = (String)nodeSvc.getProperty(initiator, ContentModel.PROP_USERNAME); + + // if the current user started the workflow allow the cancel action + if (currentUserName.equals(userName)) { - // find the current username - User user = Application.getCurrentUser(context); - String currentUserName = ISO9075.encode(user.getUserName()); - - // get the username of the initiator - NodeService nodeSvc = Repository.getServiceRegistry( - context).getNodeService(); - String userName = (String)nodeSvc.getProperty(initiator, ContentModel.PROP_USERNAME); - - // if the current user started the workflow allow the cancel action - if (currentUserName.equals(userName)) - { - result = true; - } + result = true; } } } diff --git a/source/java/org/alfresco/web/app/servlet/BaseTemplateContentServlet.java b/source/java/org/alfresco/web/app/servlet/BaseTemplateContentServlet.java new file mode 100644 index 0000000000..741d1d9948 --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/BaseTemplateContentServlet.java @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.app.servlet; + +import java.io.IOException; +import java.net.SocketException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.transaction.UserTransaction; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.TemplateException; +import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.alfresco.service.cmr.repository.TemplateNode; +import org.alfresco.service.cmr.repository.TemplateService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.web.ui.common.Utils; +import org.apache.commons.logging.Log; + +/** + * Base class for the template content servlets. Provides common + * processing for the request. + * + * @see org.alfresco.web.app.servlet.TemplateContentServlet + * @see org.alfresco.web.app.servlet.GuestTemplateContentServlet + * + * @author Kevin Roast + * @author gavinc + */ +public abstract class BaseTemplateContentServlet extends BaseServlet +{ + private static final String MIMETYPE_HTML = "text/html"; + + private static final long serialVersionUID = -4123407921997235977L; + + private static final String ARG_MIMETYPE = "mimetype"; + private static final String ARG_TEMPLATE_PATH = "templatePath"; + private static final String ARG_CONTEXT_PATH = "contextPath"; + + /** + * Gets the logger to use for this request. + *

+ * This will show all debug entries from this class as though they + * came from the subclass. + * + * @return The logger + */ + protected abstract Log getLogger(); + + /** + * Builds the FreeMarker model + * + * @param services Service Registry instance + * @param req Http request + * @param templateRef The node ref of the template to process + * @return The FreeMarker model + */ + protected abstract Map buildModel(ServiceRegistry services, + HttpServletRequest req, NodeRef templateRef); + + /** + * Processes the template request using the current context i.e. no + * authentication checks are made, it is presumed they have already + * been done. + * + * @param req The HTTP request + * @param res The HTTP response + * @param redirectToLogin Flag to determine whether to redirect to the login + * page if the user does not have the correct permissions + */ + protected void processTemplateRequest(HttpServletRequest req, HttpServletResponse res, + boolean redirectToLogin) throws ServletException, IOException + { + Log logger = getLogger(); + String uri = req.getRequestURI(); + + if (logger.isDebugEnabled()) + { + String queryString = req.getQueryString(); + logger.debug("Processing URL: " + uri + + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); + } + + uri = uri.substring(req.getContextPath().length()); + StringTokenizer t = new StringTokenizer(uri, "/"); + int tokenCount = t.countTokens(); + + t.nextToken(); // skip servlet name + + NodeRef nodeRef = null; + NodeRef templateRef = null; + + String contentPath = req.getParameter(ARG_CONTEXT_PATH); + if (contentPath != null && contentPath.length() != 0) + { + // process the name based path to resolve the NodeRef + PathRefInfo pathInfo = resolveNamePath(getServletContext(), contentPath); + + nodeRef = pathInfo.NodeRef; + } + else if (tokenCount > 3) + { + // get NodeRef to the content from the URL elements + StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken()); + nodeRef = new NodeRef(storeRef, t.nextToken()); + } + + // get NodeRef to the template if supplied + String templatePath = req.getParameter(ARG_TEMPLATE_PATH); + if (templatePath != null && templatePath.length() != 0) + { + // process the name based path to resolve the NodeRef + PathRefInfo pathInfo = resolveNamePath(getServletContext(), templatePath); + + templateRef = pathInfo.NodeRef; + } + else if (tokenCount >= 7) + { + StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken()); + templateRef = new NodeRef(storeRef, t.nextToken()); + } + + // if no context is specified, use the template itself + // TODO: should this default to something else? + if (nodeRef == null && templateRef != null) + { + nodeRef = templateRef; + } + + if (nodeRef == null) + { + throw new TemplateException("Not enough elements supplied in URL or no 'path' argument specified."); + } + + // get the services we need to retrieve the content + ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext()); + NodeService nodeService = serviceRegistry.getNodeService(); + TemplateService templateService = serviceRegistry.getTemplateService(); + PermissionService permissionService = serviceRegistry.getPermissionService(); + + // check that the user has at least READ access on any nodes - else redirect to the login page + if (permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED || + (templateRef != null && permissionService.hasPermission(templateRef, PermissionService.READ) == AccessStatus.DENIED)) + { + if (redirectToLogin) + { + if (logger.isDebugEnabled()) + logger.debug("Redirecting to login page..."); + + redirectToLoginPage(req, res, getServletContext()); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Returning 403 Forbidden error..."); + + res.sendError(HttpServletResponse.SC_FORBIDDEN); + } + + return; + } + + String mimetype = MIMETYPE_HTML; + if (req.getParameter(ARG_MIMETYPE) != null) + { + mimetype = req.getParameter(ARG_MIMETYPE); + } + res.setContentType(mimetype); + + try + { + UserTransaction txn = null; + try + { + txn = serviceRegistry.getTransactionService().getUserTransaction(true); + txn.begin(); + + // if template not supplied, then use the default against the node + if (templateRef == null) + { + if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPLATABLE)) + { + templateRef = (NodeRef)nodeService.getProperty(nodeRef, ContentModel.PROP_TEMPLATE); + } + if (templateRef == null) + { + throw new TemplateException("Template reference not set against node or not supplied in URL."); + } + } + + // create the model - put the supplied noderef in as space/document as appropriate + Object model = getModel(serviceRegistry, req, templateRef, nodeRef); + + // process the template against the node content directly to the response output stream + // assuming the repo is capable of streaming in chunks, this should allow large files + // to be streamed directly to the browser response stream. + try + { + templateService.processTemplate( + null, + templateRef.toString(), + model, + res.getWriter()); + + // commit the transaction + txn.commit(); + } + catch (SocketException e) + { + if (e.getMessage().contains("ClientAbortException")) + { + // the client cut the connection - our mission was accomplished apart from a little error message + logger.error("Client aborted stream read:\n node: " + nodeRef + "\n template: " + templateRef); + try { if (txn != null) {txn.rollback();} } catch (Exception tex) {} + } + else + { + throw e; + } + } + } + catch (Throwable txnErr) + { + try { if (txn != null) {txn.rollback();} } catch (Exception tex) {} + throw txnErr; + } + } + catch (Throwable err) + { + throw new AlfrescoRuntimeException("Error during template servlet processing: " + err.getMessage(), err); + } + } + + /** + * Build the model that to process the template against. + *

+ * The model includes the usual template root objects such as 'companyhome', 'userhome', + * 'person' and also includes the node specified on the servlet URL as 'space' and 'document' + * + * @param services ServiceRegistry required for TemplateNode construction + * @param req Http request - for accessing Session and url args + * @param templateRef NodeRef of the template itself + * @param nodeRef NodeRef of the space/document to process template against + * + * @return an object model ready for executing template against + */ + @SuppressWarnings("unchecked") + private Object getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef) + { + // build FreeMarker default model and merge + Map root = buildModel(services, req, templateRef); + + // put the current NodeRef in as "space" and "document" + TemplateNode node = new TemplateNode(nodeRef, services, this.imageResolver); + root.put("space", node); + root.put("document", node); + + // add URL arguments as a map called 'args' to the root of the model + Map args = new HashMap(8, 1.0f); + Enumeration names = req.getParameterNames(); + while (names.hasMoreElements()) + { + String name = (String)names.nextElement(); + args.put(name, req.getParameter(name)); + } + root.put("args", args); + + return root; + } + + /** Template Image resolver helper */ + private TemplateImageResolver imageResolver = new TemplateImageResolver() + { + public String resolveImagePathForName(String filename, boolean small) + { + return Utils.getFileTypeImage(getServletContext(), filename, small); + } + }; +} diff --git a/source/java/org/alfresco/web/app/servlet/GuestTemplateContentServlet.java b/source/java/org/alfresco/web/app/servlet/GuestTemplateContentServlet.java new file mode 100644 index 0000000000..6800dcacd5 --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/GuestTemplateContentServlet.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.app.servlet; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.web.bean.repository.User; +import org.alfresco.web.ui.repo.component.template.DefaultModelHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Servlet responsible for streaming content from a template processed against a node directly + * to the response stream. + *

+ * The URL to the servlet should be generated thus: + *

/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000
+ * or + *
/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000/workspace/SpacesStore/0000-0000-0000-0000
+ * or + *
/alfresco/template?templatePath=/Company%20Home/Data%20Dictionary/Presentation%20Templates/doc_info.ftl&contextPath=/Company%20Home/mydoc.txt
+ *

+ * The store protocol, followed by the store ID, followed by the content Node Id used to + * identify the node to execute the default template for. The second set of elements encode + * the store and node Id of the template to used if a default is not set or not requested. Instead + * of using NodeRef references to the template and context, path arguments can be used. The URL args + * of 'templatePath' and 'contextPath' can be used instead to specify name based encoded Paths to the + * template and its context. + *

+ * The URL may be followed by a 'mimetype' argument specifying the mimetype to return the result as + * on the stream. Otherwise it is assumed that HTML is the default response mimetype. + *

+ * Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication: + * ?ticket=1234567890 + *

+ * And/or also followed by the "?guest=true" argument to force guest access login for the URL. If the + * guest=true parameter is used the current session will be logged out and the guest user logged in. + * Therefore upon completion of this request the current user will be "guest". + *

+ * This servlet only accesses content available to the guest user. If the guest user does not + * have access to the requested a 401 Forbidden response is returned to the caller. + *

+ * This servlet does not effect the current session, therefore if guest access is required to a + * resource this servlet can be used without logging out the current user. + * + * @author gavinc + */ +public class GuestTemplateContentServlet extends BaseTemplateContentServlet +{ + private static final long serialVersionUID = -2510767849932627519L; + + private static final Log logger = LogFactory.getLog(GuestTemplateContentServlet.class); + + private static final String DEFAULT_URL = "/guestTemplate/{0}/{1}/{2}"; + private static final String TEMPLATE_URL = "/guestTemplate/{0}/{1}/{2}/{3}/{4}/{5}"; + + @Override + protected Log getLogger() + { + return logger; + } + + @Override + protected Map buildModel(ServiceRegistry services, HttpServletRequest req, + NodeRef templateRef) + { + // setup the guest user to pass to the build model helper method + AuthenticationService auth = (AuthenticationService)services.getAuthenticationService(); + PersonService personService = (PersonService)services.getPersonService(); + NodeService nodeService = (NodeService)services.getNodeService(); + + NodeRef guestRef = personService.getPerson(PermissionService.GUEST_AUTHORITY); + User guestUser = new User(PermissionService.GUEST_AUTHORITY, auth.getCurrentTicket(), guestRef); + NodeRef guestHomeRef = (NodeRef)nodeService.getProperty(guestRef, ContentModel.PROP_HOMEFOLDER); + if (nodeService.exists(guestHomeRef) == false) + { + throw new InvalidNodeRefException(guestHomeRef); + } + guestUser.setHomeSpaceId(guestHomeRef.getId()); + + // build the default model + return DefaultModelHelper.buildDefaultModel(services, guestUser, templateRef); + } + + /** + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + protected void service(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException + { + if (logger.isDebugEnabled()) + { + String queryString = req.getQueryString(); + logger.debug("Setting up guest access to URL: " + req.getRequestURI() + + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); + } + + TemplateContentWork tcw = new TemplateContentWork(req, res); + AuthenticationUtil.runAs(tcw, PermissionService.GUEST_AUTHORITY); + } + + /** + * Helper to generate a URL to process a template against a node. + *

+ * The result of the template is supplied returned as the response. + * + * @param nodeRef NodeRef of the content node to generate URL for (cannot be null) + * @param templateRef NodeRef of the template to process against, or null to use default + * + * @return URL to process the template + */ + public final static String generateURL(NodeRef nodeRef, NodeRef templateRef) + { + if (templateRef == null) + { + return MessageFormat.format(DEFAULT_URL, new Object[] { + nodeRef.getStoreRef().getProtocol(), + nodeRef.getStoreRef().getIdentifier(), + nodeRef.getId() } ); + } + else + { + return MessageFormat.format(TEMPLATE_URL, new Object[] { + nodeRef.getStoreRef().getProtocol(), + nodeRef.getStoreRef().getIdentifier(), + nodeRef.getId(), + templateRef.getStoreRef().getProtocol(), + templateRef.getStoreRef().getIdentifier(), + templateRef.getId()} ); + } + } + + /** + * Class to wrap the call to processTemplateRequest. + * + * @author gavinc + */ + public class TemplateContentWork implements RunAsWork + { + private HttpServletRequest req = null; + private HttpServletResponse res = null; + + public TemplateContentWork(HttpServletRequest req, HttpServletResponse res) + { + this.req = req; + this.res = res; + } + + public Object doWork() throws Exception + { + processTemplateRequest(this.req, this.res, false); + + return null; + } + } +} diff --git a/source/java/org/alfresco/web/app/servlet/JBPMProcessImageServlet.java b/source/java/org/alfresco/web/app/servlet/JBPMProcessImageServlet.java new file mode 100644 index 0000000000..fd4e895f5e --- /dev/null +++ b/source/java/org/alfresco/web/app/servlet/JBPMProcessImageServlet.java @@ -0,0 +1,65 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.alfresco.web.app.servlet; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jbpm.JbpmContext; +import org.jbpm.graph.def.ProcessDefinition; + + +// +// +// TODO: DC: Tidy up +// +// + + + + +public class JBPMProcessImageServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + long processDefinitionId = Long.parseLong( request.getParameter( "definitionId" ) ); + JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext(); + ProcessDefinition processDefinition = jbpmContext.getGraphSession().loadProcessDefinition(processDefinitionId); + byte[] bytes = processDefinition.getFileDefinition().getBytes("processimage.jpg"); + OutputStream out = response.getOutputStream(); + out.write(bytes); + out.flush(); + + // leave this in. it is in case we want to set the mime type later. + // get the mime type + // String contentType = URLConnection.getFileNameMap().getContentTypeFor( fileName ); + // set the content type (=mime type) + // response.setContentType( contentType ); + } +} diff --git a/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java b/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java index a728e7bc93..09effd521d 100644 --- a/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java +++ b/source/java/org/alfresco/web/app/servlet/TemplateContentServlet.java @@ -17,32 +17,16 @@ package org.alfresco.web.app.servlet; import java.io.IOException; -import java.net.SocketException; import java.text.MessageFormat; -import java.util.Enumeration; -import java.util.HashMap; import java.util.Map; -import java.util.StringTokenizer; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.transaction.UserTransaction; -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.repository.TemplateException; -import org.alfresco.service.cmr.repository.TemplateImageResolver; -import org.alfresco.service.cmr.repository.TemplateNode; -import org.alfresco.service.cmr.repository.TemplateService; -import org.alfresco.service.cmr.security.AccessStatus; -import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.web.app.Application; -import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.repo.component.template.DefaultModelHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -71,24 +55,37 @@ import org.apache.commons.logging.LogFactory; * Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication: * ?ticket=1234567890 *

- * And/or also followed by the "?guest=true" argument to force guest access login for the URL. + * And/or also followed by the "?guest=true" argument to force guest access login for the URL. If the + * guest=true parameter is used the current session will be logged out and the guest user logged in. + * Therefore upon completion of this request the current user will be "guest". + *

+ * If the user attempting the request is not authorised to access the requested node the login page + * will be redirected to. * * @author Kevin Roast */ -public class TemplateContentServlet extends BaseServlet -{ - private static final String MIMETYPE_HTML = "text/html"; +public class TemplateContentServlet extends BaseTemplateContentServlet +{ + private static final long serialVersionUID = -2510767849932627519L; - private static final long serialVersionUID = -4123407921997235977L; - - private static Log logger = LogFactory.getLog(TemplateContentServlet.class); + private static final Log logger = LogFactory.getLog(TemplateContentServlet.class); private static final String DEFAULT_URL = "/template/{0}/{1}/{2}"; private static final String TEMPLATE_URL = "/template/{0}/{1}/{2}/{3}/{4}/{5}"; - private static final String ARG_MIMETYPE = "mimetype"; - private static final String ARG_TEMPLATE_PATH = "templatePath"; - private static final String ARG_CONTEXT_PATH = "contextPath"; + @Override + protected Log getLogger() + { + return logger; + } + + @Override + protected Map buildModel(ServiceRegistry services, HttpServletRequest req, + NodeRef templateRef) + { + return DefaultModelHelper.buildDefaultModel(services, + Application.getCurrentUser(req.getSession()), templateRef); + } /** * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) @@ -96,12 +93,10 @@ public class TemplateContentServlet extends BaseServlet protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { - String uri = req.getRequestURI(); - if (logger.isDebugEnabled()) { String queryString = req.getQueryString(); - logger.debug("Processing URL: " + uri + + logger.debug("Authenticating request to URL: " + req.getRequestURI() + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); } @@ -111,189 +106,9 @@ public class TemplateContentServlet extends BaseServlet return; } - uri = uri.substring(req.getContextPath().length()); - StringTokenizer t = new StringTokenizer(uri, "/"); - int tokenCount = t.countTokens(); - - t.nextToken(); // skip servlet name - - NodeRef nodeRef = null; - NodeRef templateRef = null; - - String contentPath = req.getParameter(ARG_CONTEXT_PATH); - if (contentPath != null && contentPath.length() != 0) - { - // process the name based path to resolve the NodeRef - PathRefInfo pathInfo = resolveNamePath(getServletContext(), contentPath); - - nodeRef = pathInfo.NodeRef; - } - else if (tokenCount > 3) - { - // get NodeRef to the content from the URL elements - StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken()); - nodeRef = new NodeRef(storeRef, t.nextToken()); - } - - // get NodeRef to the template if supplied - String templatePath = req.getParameter(ARG_TEMPLATE_PATH); - if (templatePath != null && templatePath.length() != 0) - { - // process the name based path to resolve the NodeRef - PathRefInfo pathInfo = resolveNamePath(getServletContext(), templatePath); - - templateRef = pathInfo.NodeRef; - } - else if (tokenCount >= 7) - { - StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken()); - templateRef = new NodeRef(storeRef, t.nextToken()); - } - - // if no context is specified, use the template itself - // TODO: should this default to something else? - if (nodeRef == null && templateRef != null) - { - nodeRef = templateRef; - } - - if (nodeRef == null) - { - throw new TemplateException("Not enough elements supplied in URL or no 'path' argument specified."); - } - - // get the services we need to retrieve the content - ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext()); - NodeService nodeService = serviceRegistry.getNodeService(); - TemplateService templateService = serviceRegistry.getTemplateService(); - PermissionService permissionService = serviceRegistry.getPermissionService(); - - // check that the user has at least READ access on any nodes - else redirect to the login page - if (permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED || - (templateRef != null && permissionService.hasPermission(templateRef, PermissionService.READ) == AccessStatus.DENIED)) - { - redirectToLoginPage(req, res, getServletContext()); - return; - } - - String mimetype = MIMETYPE_HTML; - if (req.getParameter(ARG_MIMETYPE) != null) - { - mimetype = req.getParameter(ARG_MIMETYPE); - } - res.setContentType(mimetype); - - try - { - UserTransaction txn = null; - try - { - txn = serviceRegistry.getTransactionService().getUserTransaction(true); - txn.begin(); - - // if template not supplied, then use the default against the node - if (templateRef == null) - { - if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_TEMPLATABLE)) - { - templateRef = (NodeRef)nodeService.getProperty(nodeRef, ContentModel.PROP_TEMPLATE); - } - if (templateRef == null) - { - throw new TemplateException("Template reference not set against node or not supplied in URL."); - } - } - - // create the model - put the supplied noderef in as space/document as appropriate - Object model = getModel(serviceRegistry, req, templateRef, nodeRef); - - // process the template against the node content directly to the response output stream - // assuming the repo is capable of streaming in chunks, this should allow large files - // to be streamed directly to the browser response stream. - try - { - templateService.processTemplate( - null, - templateRef.toString(), - model, - res.getWriter()); - - // commit the transaction - txn.commit(); - } - catch (SocketException e) - { - if (e.getMessage().contains("ClientAbortException")) - { - // the client cut the connection - our mission was accomplished apart from a little error message - logger.error("Client aborted stream read:\n node: " + nodeRef + "\n template: " + templateRef); - try { if (txn != null) {txn.rollback();} } catch (Exception tex) {} - } - else - { - throw e; - } - } - } - catch (Throwable txnErr) - { - try { if (txn != null) {txn.rollback();} } catch (Exception tex) {} - throw txnErr; - } - } - catch (Throwable err) - { - throw new AlfrescoRuntimeException("Error during template servlet processing: " + err.getMessage(), err); - } + processTemplateRequest(req, res, true); } - /** - * Build the model that to process the template against. - *

- * The model includes the usual template root objects such as 'companyhome', 'userhome', - * 'person' and also includes the node specified on the servlet URL as 'space' and 'document' - * - * @param services ServiceRegistry required for TemplateNode construction - * @param req Http request - for accessing Session and url args - * @param templateRef NodeRef of the template itself - * @param nodeRef NodeRef of the space/document to process template against - * - * @return an object model ready for executing template against - */ - @SuppressWarnings("unchecked") - private Object getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef) - { - // build FreeMarker default model and merge - Map root = DefaultModelHelper.buildDefaultModel( - services, Application.getCurrentUser(req.getSession()), templateRef); - - // put the current NodeRef in as "space" and "document" - TemplateNode node = new TemplateNode(nodeRef, services, this.imageResolver); - root.put("space", node); - root.put("document", node); - - // add URL arguments as a map called 'args' to the root of the model - Map args = new HashMap(8, 1.0f); - Enumeration names = req.getParameterNames(); - while (names.hasMoreElements()) - { - String name = (String)names.nextElement(); - args.put(name, req.getParameter(name)); - } - root.put("args", args); - - return root; - } - - /** Template Image resolver helper */ - private TemplateImageResolver imageResolver = new TemplateImageResolver() - { - public String resolveImagePathForName(String filename, boolean small) - { - return Utils.getFileTypeImage(getServletContext(), filename, small); - } - }; - /** * Helper to generate a URL to process a template against a node. *

diff --git a/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java b/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java index 135da7aadf..1ffb92f8df 100644 --- a/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java +++ b/source/java/org/alfresco/web/app/servlet/command/ApproveWorkflowCommand.java @@ -20,7 +20,7 @@ import java.util.Map; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.web.bean.WorkflowUtil; +import org.alfresco.web.bean.workflow.WorkflowUtil; /** * Approve Workflow command implementation diff --git a/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java b/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java index aee30ccb9b..2775f360fe 100644 --- a/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java +++ b/source/java/org/alfresco/web/app/servlet/command/RejectWorkflowCommand.java @@ -20,7 +20,7 @@ import java.util.Map; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.web.bean.WorkflowUtil; +import org.alfresco.web.bean.workflow.WorkflowUtil; /** * Reject Workflow command implementation diff --git a/source/java/org/alfresco/web/bean/BaseDetailsBean.java b/source/java/org/alfresco/web/bean/BaseDetailsBean.java index 09d0b7b6bb..c235d4aa2c 100644 --- a/source/java/org/alfresco/web/bean/BaseDetailsBean.java +++ b/source/java/org/alfresco/web/bean/BaseDetailsBean.java @@ -39,6 +39,7 @@ import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.bean.actions.handlers.SimpleWorkflowHandler; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.workflow.WorkflowUtil; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.Utils.URLMode; import org.alfresco.web.ui.common.component.UIActionLink; diff --git a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java index 9a90fb796a..f58e734bf9 100644 --- a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java +++ b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java @@ -1,1050 +1,1051 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.web.bean; - -import java.io.File; -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - -import javax.faces.context.FacesContext; -import javax.faces.event.ActionEvent; -import javax.transaction.UserTransaction; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.repo.version.VersionModel; -import org.alfresco.repo.workflow.WorkflowModel; -import org.alfresco.service.cmr.coci.CheckOutCheckInService; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.InvalidNodeRefException; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.version.Version; -import org.alfresco.service.cmr.version.VersionType; -import org.alfresco.service.cmr.workflow.WorkflowService; -import org.alfresco.service.cmr.workflow.WorkflowTask; -import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.service.namespace.QName; -import org.alfresco.web.app.AlfrescoNavigationHandler; -import org.alfresco.web.app.Application; -import org.alfresco.web.app.context.UIContextService; -import org.alfresco.web.app.servlet.DownloadContentServlet; -import org.alfresco.web.bean.repository.Node; -import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.ui.common.Utils; -import org.alfresco.web.ui.common.component.UIActionLink; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * @author Kevin Roast - */ -public class CheckinCheckoutBean -{ - // ------------------------------------------------------------------------------ - // Bean property getters and setters - - /** - * @param navigator The NavigationBean to set. - */ - public void setNavigator(NavigationBean navigator) - { - this.navigator = navigator; - } - - /** - * @return Returns the BrowseBean. - */ - public BrowseBean getBrowseBean() - { - return this.browseBean; - } - - /** - * @param browseBean The BrowseBean to set. - */ - public void setBrowseBean(BrowseBean browseBean) - { - this.browseBean = browseBean; - } - - /** - * @return Returns the NodeService. - */ - public NodeService getNodeService() - { - return this.nodeService; - } - - /** - * @param nodeService The NodeService to set. - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - /** - * @return Returns the VersionOperationsService. - */ - public CheckOutCheckInService getVersionOperationsService() - { - return this.versionOperationsService; - } - - /** - * @param versionOperationsService The VersionOperationsService to set. - */ - public void setVersionOperationsService(CheckOutCheckInService versionOperationsService) - { - this.versionOperationsService = versionOperationsService; - } - - /** - * @return Returns the ContentService. - */ - public ContentService getContentService() - { - return this.contentService; - } - - /** - * @param contentService The ContentService to set. - */ - public void setContentService(ContentService contentService) - { - this.contentService = contentService; - } - - /** - * @param workflowService The WorkflowService to set. - */ - public void setWorkflowService(WorkflowService workflowService) - { - this.workflowService = workflowService; - } - - /** - * @return The document node being used for the current operation - */ - public Node getDocument() - { - return this.document; - } - - /** - * @param document The document node to be used for the current operation - */ - public void setDocument(Node document) - { - this.document = document; - } - - /** - * @return Returns the working copy Document. - */ - public Node getWorkingDocument() - { - return this.workingDocument; - } - - /** - * @param workingDocument The working copy Document to set. - */ - public void setWorkingDocument(Node workingDocument) - { - this.workingDocument = workingDocument; - } - - /** - * Determines whether the document being checked in has - * the versionable aspect applied - * - * @return true if the versionable aspect is applied - */ - public boolean isVersionable() - { - return getDocument().hasAspect(ContentModel.ASPECT_VERSIONABLE); - } - - /** - * @param keepCheckedOut The keepCheckedOut to set. - */ - public void setKeepCheckedOut(boolean keepCheckedOut) - { - this.keepCheckedOut = keepCheckedOut; - } - - /** - * @return Returns the keepCheckedOut. - */ - public boolean getKeepCheckedOut() - { - return this.keepCheckedOut; - } - - /** - * @param minorChange The minorChange to set. - */ - public void setMinorChange(boolean minorChange) - { - this.minorChange = minorChange; - } - - /** - * @return Returns the minorChange flag. - */ - public boolean getMinorChange() - { - return this.minorChange; - } - - /** - * @return Returns the version history notes. - */ - public String getVersionNotes() - { - return this.versionNotes; - } - - /** - * @param versionNotes The version history notes to set. - */ - public void setVersionNotes(String versionNotes) - { - this.versionNotes = versionNotes; - } - - /** - * @return Returns the selected Space Id. - */ - public NodeRef getSelectedSpaceId() - { - return this.selectedSpaceId; - } - - /** - * @param selectedSpaceId The selected Space Id to set. - */ - public void setSelectedSpaceId(NodeRef selectedSpaceId) - { - this.selectedSpaceId = selectedSpaceId; - } - - /** - * @return Returns the copy location. Either the current or other space. - */ - public String getCopyLocation() - { - if (this.fileName != null) - { - return CheckinCheckoutBean.COPYLOCATION_OTHER; - } - else - { - return this.copyLocation; - } - } - - /** - * @param copyLocation The copy location. Either the current or other space. - */ - public void setCopyLocation(String copyLocation) - { - this.copyLocation = copyLocation; - } - - /** - * @return Returns the message to display when a file has been uploaded - */ - public String getFileUploadSuccessMsg() - { - String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success"); - return MessageFormat.format(msg, new Object[] {getFileName()}); - } - - /** - * @return Returns the name of the file - */ - public String getFileName() - { - // try and retrieve the file and filename from the file upload bean - // representing the file we previously uploaded. - FacesContext ctx = FacesContext.getCurrentInstance(); - FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). - get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); - if (fileBean != null) - { - this.file = fileBean.getFile(); - this.fileName = fileBean.getFileName(); - } - - return this.fileName; - } - - /** - * @param fileName The name of the file - */ - public void setFileName(String fileName) - { - this.fileName = fileName; - - // we also need to keep the file upload bean in sync - FacesContext ctx = FacesContext.getCurrentInstance(); - FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). - get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); - if (fileBean != null) - { - fileBean.setFileName(this.fileName); - } - } - - /** - * @return Returns the document content used for HTML in-line editing. - */ - public String getDocumentContent() - { - return this.documentContent; - } - - /** - * @param documentContent The document content for HTML in-line editing. - */ - public void setDocumentContent(String documentContent) - { - this.documentContent = documentContent; - } - - /** - * @return Returns output from the in-line editor page. - */ - public String getEditorOutput() - { - return this.editorOutput; - } - - /** - * @param editorOutput The output from the in-line editor page - */ - public void setEditorOutput(String editorOutput) - { - this.editorOutput = editorOutput; - } - - - // ------------------------------------------------------------------------------ - // Navigation action event handlers - - /** - * Action event called by all actions that need to setup a Content Document context on the - * CheckinCheckoutBean before an action page/wizard is called. The context will be a Node in - * setDocument() which can be retrieved on action pages via getDocument(). - * - * @param event ActionEvent - */ - public void setupContentAction(ActionEvent event) - { - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - String id = params.get("id"); - if (id != null && id.length() != 0) - { - setupContentDocument(id); - } - else - { - setDocument(null); - } - - resetState(); - } - - public void setupWorkflowContentAction(ActionEvent event) - { - // do the common processing - setupContentAction(event); - - // retrieve the id of the task - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - this.workflowTaskId = params.get("taskId"); - - this.isWorkflowAction = true; - - if (logger.isDebugEnabled()) - logger.debug("Setup for workflow package action for task id: " + this.workflowTaskId); - } - - /** - * Setup a content document node context - * - * @param id GUID of the node to setup as the content document context - * - * @return The Node - */ - private Node setupContentDocument(String id) - { - if (logger.isDebugEnabled()) - logger.debug("Setup for action, setting current document to: " + id); - - Node node = null; - - try - { - // create the node ref, then our node representation - NodeRef ref = new NodeRef(Repository.getStoreRef(), id); - node = new Node(ref); - - // create content URL to the content download servlet with ID and expected filename - // the myfile part will be ignored by the servlet but gives the browser a hint - String url = DownloadContentServlet.generateDownloadURL(ref, node.getName()); - node.getProperties().put("url", url); - node.getProperties().put("workingCopy", node.hasAspect(ContentModel.ASPECT_WORKING_COPY)); - node.getProperties().put("fileType32", Utils.getFileTypeImage(node.getName(), false)); - - // remember the document - setDocument(node); - - // refresh the UI, calling this method now is fine as it basically makes sure certain - // beans clear the state - so when we finish here other beans will have been reset - UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans(); - } - catch (InvalidNodeRefException refErr) - { - Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) ); - } - - return node; - } - - /** - * Action called upon completion of the Check Out file page - */ - public String checkoutFile() - { - String outcome = null; - - UserTransaction tx = null; - - Node node = getDocument(); - if (node != null) - { - try - { - tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); - tx.begin(); - - if (logger.isDebugEnabled()) - logger.debug("Trying to checkout content node Id: " + node.getId()); - - // checkout the node content to create a working copy - if (logger.isDebugEnabled()) - { - logger.debug("Checkout copy location: " + getCopyLocation()); - logger.debug("Selected Space Id: " + this.selectedSpaceId); - } - NodeRef workingCopyRef = null; - if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null) - { - // checkout to a arbituary parent Space - NodeRef destRef = this.selectedSpaceId; - - ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(destRef); - workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef(), - destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName()); - } - else - { - // checkout the content to the current space - workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef()); - - // if this is a workflow action and there is a task id present we need - // to also link the working copy to the workflow package so it appears - // in the resources panel in the manage task dialog - if (this.isWorkflowAction && this.workflowTaskId != null) - { - WorkflowTask task = this.workflowService.getTaskById(this.workflowTaskId); - if (task != null) - { - NodeRef workflowPackage = (NodeRef)task.properties.get(WorkflowModel.ASSOC_PACKAGE); - if (workflowPackage != null) - { - this.nodeService.addChild(workflowPackage, workingCopyRef, - ContentModel.ASSOC_CONTAINS, QName.createQName( - NamespaceService.CONTENT_MODEL_1_0_URI, - QName.createValidLocalName((String)this.nodeService.getProperty( - workingCopyRef, ContentModel.PROP_NAME)))); - - if (logger.isDebugEnabled()) - logger.debug("Added working copy to workflow package: " + workflowPackage); - } - } - } - } - - // set the working copy Node instance - Node workingCopy = new Node(workingCopyRef); - setWorkingDocument(workingCopy); - - // create content URL to the content download servlet with ID and expected filename - // the myfile part will be ignored by the servlet but gives the browser a hint - String url = DownloadContentServlet.generateDownloadURL(workingCopyRef, workingCopy.getName()); - - workingCopy.getProperties().put("url", url); - workingCopy.getProperties().put("fileType32", Utils.getFileTypeImage(workingCopy.getName(), false)); - - // commit the transaction - tx.commit(); - - // show the page that display the checkout link - outcome = "checkoutFileLink"; - } - catch (Throwable err) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - Utils.addErrorMessage(Application.getMessage( - FacesContext.getCurrentInstance(), MSG_ERROR_CHECKOUT) + err.getMessage(), err); - } - } - else - { - logger.warn("WARNING: checkoutFile called without a current Document!"); - } - - return outcome; - } - - /** - * Action called upon completion of the Check Out file Link download page - */ - public String checkoutFileOK() - { - String outcome = null; - - Node node = getWorkingDocument(); - if (node != null) - { - // reset the underlying node - if (this.browseBean.getDocument() != null) - { - this.browseBean.getDocument().reset(); - } - - // clean up and clear action context - resetState(); - setDocument(null); - setWorkingDocument(null); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - else - { - logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); - } - - return outcome; - } - - /** - * Action called upon completion of the Edit File download page - */ - public String editFileOK() - { - String outcome = null; - - Node node = getDocument(); - if (node != null) - { - // clean up and clear action context - resetState(); - setDocument(null); - setWorkingDocument(null); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - else - { - logger.warn("WARNING: editFileOK called without a current Document!"); - } - - return outcome; - } - - /** - * Action handler called to calculate which editing screen to display based on the mimetype - * of a document. If appropriate, the in-line editing screen will be shown. - */ - public void editFile(ActionEvent event) - { - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - String id = params.get("id"); - if (id != null && id.length() != 0) - { - boolean editingInline = false; - Node node = setupContentDocument(id); - - // detect the inline editing aspect to see which edit mode to use - if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) && - node.getProperties().get(ContentModel.PROP_EDITINLINE) != null && - ((Boolean)node.getProperties().get(ContentModel.PROP_EDITINLINE)).booleanValue() == true) - { - // retrieve the content reader for this node - ContentReader reader = getContentService().getReader(node.getNodeRef(), ContentModel.PROP_CONTENT); - if (reader != null) - { - editingInline = true; - String mimetype = reader.getMimetype(); - - // calculate which editor screen to display - if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype) || - MimetypeMap.MIMETYPE_XML.equals(mimetype) || - MimetypeMap.MIMETYPE_TEXT_CSS.equals(mimetype) || - MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype)) - { - // make content available to the editing screen - setEditorOutput(reader.getContentString()); - - // navigate to appropriate screen - FacesContext fc = FacesContext.getCurrentInstance(); - this.navigator.setupDispatchContext(node); - String outcome; - if (MimetypeMap.MIMETYPE_XML.equals(mimetype)) - { - outcome = "dialog:editXmlInline"; - } - else - { - outcome = "dialog:editTextInline"; - } - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, outcome); - } - else - { - // make content available to the editing screen - setDocumentContent(reader.getContentString()); - setEditorOutput(null); - - // navigate to appropriate screen - FacesContext fc = FacesContext.getCurrentInstance(); - this.navigator.setupDispatchContext(node); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline"); - } - } - } - - if (editingInline == false) - { - // normal downloadable document - FacesContext fc = FacesContext.getCurrentInstance(); - this.navigator.setupDispatchContext(node); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile"); - } - } - } - - /** - * Action handler called to set the content of a node from an inline editing page. - */ - public String editInlineOK() - { - String outcome = null; - - UserTransaction tx = null; - - Node node = getDocument(); - if (node != null) - { - try - { - tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); - tx.begin(); - - if (logger.isDebugEnabled()) - logger.debug("Trying to update content node Id: " + node.getId()); - - // get an updating writer that we can use to modify the content on the current node - ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); - writer.putContent(this.editorOutput); - - // commit the transaction - tx.commit(); - - // clean up and clear action context - resetState(); - setDocument(null); - setDocumentContent(null); - setEditorOutput(null); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - catch (Throwable err) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - Utils.addErrorMessage(Application.getMessage( - FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage()); - } - } - else - { - logger.warn("WARNING: editInlineOK called without a current Document!"); - } - - return outcome; - } - - /** - * Action to undo the checkout of a document just checked out from the checkout screen. - */ - public String undoCheckout() - { - String outcome = null; - - Node node = getWorkingDocument(); - if (node != null) - { - try - { - // try to cancel checkout of the working copy - this.versionOperationsService.cancelCheckout(node.getNodeRef()); - - resetState(); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - catch (Throwable err) - { - Utils.addErrorMessage(Application.getMessage( - FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err); - } - } - else - { - logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); - } - - return outcome; - } - - /** - * Action to undo the checkout of a locked document. This document may either by the original copy - * or the working copy node. Therefore calculate which it is, if the working copy is found then - * we simply cancel checkout on that document. If the original copy is found then we need to find - * the appropriate working copy and perform the action on that node. - */ - public String undoCheckoutFile() - { - String outcome = null; - - Node node = getDocument(); - if (node != null) - { - try - { - if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY)) - { - this.versionOperationsService.cancelCheckout(node.getNodeRef()); - } - else if (node.hasAspect(ContentModel.ASPECT_LOCKABLE)) - { - // TODO: find the working copy for this document and cancel the checkout on it - // is this possible? as currently only the workingcopy aspect has the copyReference - // attribute - this means we cannot find out where the copy is to cancel it! - // can we construct an XPath node lookup? - throw new RuntimeException("NOT IMPLEMENTED"); - } - else - { - throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!"); - } - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - - if (this.isWorkflowAction == false) - { - outcome = outcome + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; - } - - resetState(); - } - catch (Throwable err) - { - Utils.addErrorMessage(MSG_ERROR_CANCELCHECKOUT + err.getMessage(), err); - } - } - else - { - logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); - } - - return outcome; - } - - /** - * Action called upon completion of the Check In file page - */ - public String checkinFileOK() - { - String outcome = null; - - UserTransaction tx = null; - - // NOTE: for checkin the document node _is_ the working document! - Node node = getDocument(); - if (node != null && (getCopyLocation().equals(COPYLOCATION_CURRENT) || this.getFileName() != null)) - { - try - { - FacesContext context = FacesContext.getCurrentInstance(); - tx = Repository.getUserTransaction(context); - tx.begin(); - - if (logger.isDebugEnabled()) - logger.debug("Trying to checkin content node Id: " + node.getId()); - - // we can either checkin the content from the current working copy node - // which would have been previously updated by the user - String contentUrl; - if (getCopyLocation().equals(COPYLOCATION_CURRENT)) - { - ContentData contentData = (ContentData) node.getProperties().get(ContentModel.PROP_CONTENT); - contentUrl = (contentData == null ? null : contentData.getContentUrl()); - } - // or specify a specific file as the content instead - else - { - // add the content to an anonymous but permanent writer location - // we can then retrieve the URL to the content to to be set on the node during checkin - ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); - // also update the mime type in case a different type of file is uploaded - String mimeType = Repository.getMimeTypeForFileName(context, this.fileName); - writer.setMimetype(mimeType); - writer.putContent(this.file); - contentUrl = writer.getContentUrl(); - } - - if (contentUrl == null || contentUrl.length() == 0) - { - throw new IllegalStateException("Content URL is empty for specified working copy content node!"); - } - - // add version history text to props - Map props = new HashMap(1, 1.0f); - props.put(Version.PROP_DESCRIPTION, this.versionNotes); - // set the flag for minor or major change - if (this.minorChange) - { - props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); - } - else - { - props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); - } - - // perform the checkin - this.versionOperationsService.checkin(node.getNodeRef(), - props, contentUrl, this.keepCheckedOut); - - // commit the transaction - tx.commit(); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - - if (this.isWorkflowAction == false) - { - outcome = outcome + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; - } - - // clear action context - setDocument(null); - resetState(); - } - catch (Throwable err) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - Utils.addErrorMessage(Application.getMessage( - FacesContext.getCurrentInstance(), MSG_ERROR_CHECKIN) + err.getMessage(), err); - } - } - else - { - logger.warn("WARNING: checkinFileOK called without a current Document!"); - } - - return outcome; - } - - /** - * Action called upon completion of the Update File page - */ - public String updateFileOK() - { - String outcome = null; - - UserTransaction tx = null; - - // NOTE: for update the document node _is_ the working document! - Node node = getDocument(); - if (node != null && this.getFileName() != null) - { - try - { - FacesContext context = FacesContext.getCurrentInstance(); - tx = Repository.getUserTransaction(context); - tx.begin(); - - if (logger.isDebugEnabled()) - logger.debug("Trying to update content node Id: " + node.getId()); - - // get an updating writer that we can use to modify the content on the current node - ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); - - // also update the mime type in case a different type of file is uploaded - String mimeType = Repository.getMimeTypeForFileName(context, this.fileName); - writer.setMimetype(mimeType); - - writer.putContent(this.file); - - // commit the transaction - tx.commit(); - - // clear action context - setDocument(null); - resetState(); - - outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - catch (Throwable err) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} - Utils.addErrorMessage(Application.getMessage( - FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage(), err); - } - } - else - { - logger.warn("WARNING: updateFileOK called without a current Document!"); - } - - return outcome; - } - - /** - * Deals with the cancel button being pressed on the check in file page - */ - public String cancel() - { - // reset the state - resetState(); - - return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - - /** - * Clear form state and upload file bean - */ - private void resetState() - { - // delete the temporary file we uploaded earlier - if (this.file != null) - { - this.file.delete(); - } - - this.file = null; - this.fileName = null; - this.keepCheckedOut = false; - this.minorChange = true; - this.copyLocation = COPYLOCATION_CURRENT; - this.versionNotes = ""; - this.selectedSpaceId = null; - this.isWorkflowAction = false; - this.workflowTaskId = null; - - // remove the file upload bean from the session - FacesContext ctx = FacesContext.getCurrentInstance(); - ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME); - } - - - // ------------------------------------------------------------------------------ - // Private data - - private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class); - - /** I18N messages */ - public static final String MSG_ERROR_CHECKIN = "error_checkin"; - public static final String MSG_ERROR_CANCELCHECKOUT = "error_cancel_checkout"; - public static final String MSG_ERROR_UPDATE = "error_update"; - public static final String MSG_ERROR_CHECKOUT = "error_checkout"; - - /** constants for copy location selection */ - private static final String COPYLOCATION_CURRENT = "current"; - private static final String COPYLOCATION_OTHER = "other"; - - /** The current document */ - private Node document; - - /** The working copy of the document we are checking out */ - private Node workingDocument; - - /** Content of the document used for HTML in-line editing */ - private String documentContent; - - /** Content of the document returned from in-line editing */ - private String editorOutput; - - /** transient form and upload properties */ - private File file; - private String fileName; - private boolean keepCheckedOut = false; - private boolean minorChange = true; - private boolean isWorkflowAction = false; - private String workflowTaskId; - private String copyLocation = COPYLOCATION_CURRENT; - private String versionNotes = ""; - private NodeRef selectedSpaceId = null; - - /** The BrowseBean to be used by the bean */ - protected BrowseBean browseBean; - - /** The NavigationBean bean reference */ - protected NavigationBean navigator; - - /** The NodeService to be used by the bean */ - protected NodeService nodeService; - - /** The VersionOperationsService to be used by the bean */ - protected CheckOutCheckInService versionOperationsService; - - /** The ContentService to be used by the bean */ - protected ContentService contentService; - - /** The WorkflowService to be used by the bean */ - protected WorkflowService workflowService; -} +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.bean; + +import java.io.File; +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import javax.faces.context.FacesContext; +import javax.faces.event.ActionEvent; +import javax.transaction.UserTransaction; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.version.VersionModel; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.version.Version; +import org.alfresco.service.cmr.version.VersionType; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.app.Application; +import org.alfresco.web.app.context.UIContextService; +import org.alfresco.web.app.servlet.DownloadContentServlet; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIActionLink; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Kevin Roast + */ +public class CheckinCheckoutBean +{ + // ------------------------------------------------------------------------------ + // Bean property getters and setters + + /** + * @param navigator The NavigationBean to set. + */ + public void setNavigator(NavigationBean navigator) + { + this.navigator = navigator; + } + + /** + * @return Returns the BrowseBean. + */ + public BrowseBean getBrowseBean() + { + return this.browseBean; + } + + /** + * @param browseBean The BrowseBean to set. + */ + public void setBrowseBean(BrowseBean browseBean) + { + this.browseBean = browseBean; + } + + /** + * @return Returns the NodeService. + */ + public NodeService getNodeService() + { + return this.nodeService; + } + + /** + * @param nodeService The NodeService to set. + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @return Returns the VersionOperationsService. + */ + public CheckOutCheckInService getVersionOperationsService() + { + return this.versionOperationsService; + } + + /** + * @param versionOperationsService The VersionOperationsService to set. + */ + public void setVersionOperationsService(CheckOutCheckInService versionOperationsService) + { + this.versionOperationsService = versionOperationsService; + } + + /** + * @return Returns the ContentService. + */ + public ContentService getContentService() + { + return this.contentService; + } + + /** + * @param contentService The ContentService to set. + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * @param workflowService The WorkflowService to set. + */ + public void setWorkflowService(WorkflowService workflowService) + { + this.workflowService = workflowService; + } + + /** + * @return The document node being used for the current operation + */ + public Node getDocument() + { + return this.document; + } + + /** + * @param document The document node to be used for the current operation + */ + public void setDocument(Node document) + { + this.document = document; + } + + /** + * @return Returns the working copy Document. + */ + public Node getWorkingDocument() + { + return this.workingDocument; + } + + /** + * @param workingDocument The working copy Document to set. + */ + public void setWorkingDocument(Node workingDocument) + { + this.workingDocument = workingDocument; + } + + /** + * Determines whether the document being checked in has + * the versionable aspect applied + * + * @return true if the versionable aspect is applied + */ + public boolean isVersionable() + { + return getDocument().hasAspect(ContentModel.ASPECT_VERSIONABLE); + } + + /** + * @param keepCheckedOut The keepCheckedOut to set. + */ + public void setKeepCheckedOut(boolean keepCheckedOut) + { + this.keepCheckedOut = keepCheckedOut; + } + + /** + * @return Returns the keepCheckedOut. + */ + public boolean getKeepCheckedOut() + { + return this.keepCheckedOut; + } + + /** + * @param minorChange The minorChange to set. + */ + public void setMinorChange(boolean minorChange) + { + this.minorChange = minorChange; + } + + /** + * @return Returns the minorChange flag. + */ + public boolean getMinorChange() + { + return this.minorChange; + } + + /** + * @return Returns the version history notes. + */ + public String getVersionNotes() + { + return this.versionNotes; + } + + /** + * @param versionNotes The version history notes to set. + */ + public void setVersionNotes(String versionNotes) + { + this.versionNotes = versionNotes; + } + + /** + * @return Returns the selected Space Id. + */ + public NodeRef getSelectedSpaceId() + { + return this.selectedSpaceId; + } + + /** + * @param selectedSpaceId The selected Space Id to set. + */ + public void setSelectedSpaceId(NodeRef selectedSpaceId) + { + this.selectedSpaceId = selectedSpaceId; + } + + /** + * @return Returns the copy location. Either the current or other space. + */ + public String getCopyLocation() + { + if (this.fileName != null) + { + return CheckinCheckoutBean.COPYLOCATION_OTHER; + } + else + { + return this.copyLocation; + } + } + + /** + * @param copyLocation The copy location. Either the current or other space. + */ + public void setCopyLocation(String copyLocation) + { + this.copyLocation = copyLocation; + } + + /** + * @return Returns the message to display when a file has been uploaded + */ + public String getFileUploadSuccessMsg() + { + String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success"); + return MessageFormat.format(msg, new Object[] {getFileName()}); + } + + /** + * @return Returns the name of the file + */ + public String getFileName() + { + // try and retrieve the file and filename from the file upload bean + // representing the file we previously uploaded. + FacesContext ctx = FacesContext.getCurrentInstance(); + FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). + get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); + if (fileBean != null) + { + this.file = fileBean.getFile(); + this.fileName = fileBean.getFileName(); + } + + return this.fileName; + } + + /** + * @param fileName The name of the file + */ + public void setFileName(String fileName) + { + this.fileName = fileName; + + // we also need to keep the file upload bean in sync + FacesContext ctx = FacesContext.getCurrentInstance(); + FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). + get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); + if (fileBean != null) + { + fileBean.setFileName(this.fileName); + } + } + + /** + * @return Returns the document content used for HTML in-line editing. + */ + public String getDocumentContent() + { + return this.documentContent; + } + + /** + * @param documentContent The document content for HTML in-line editing. + */ + public void setDocumentContent(String documentContent) + { + this.documentContent = documentContent; + } + + /** + * @return Returns output from the in-line editor page. + */ + public String getEditorOutput() + { + return this.editorOutput; + } + + /** + * @param editorOutput The output from the in-line editor page + */ + public void setEditorOutput(String editorOutput) + { + this.editorOutput = editorOutput; + } + + + // ------------------------------------------------------------------------------ + // Navigation action event handlers + + /** + * Action event called by all actions that need to setup a Content Document context on the + * CheckinCheckoutBean before an action page/wizard is called. The context will be a Node in + * setDocument() which can be retrieved on action pages via getDocument(). + * + * @param event ActionEvent + */ + public void setupContentAction(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String id = params.get("id"); + if (id != null && id.length() != 0) + { + setupContentDocument(id); + } + else + { + setDocument(null); + } + + resetState(); + } + + public void setupWorkflowContentAction(ActionEvent event) + { + // do the common processing + setupContentAction(event); + + // retrieve the id of the task + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + this.workflowTaskId = params.get("taskId"); + + this.isWorkflowAction = true; + + if (logger.isDebugEnabled()) + logger.debug("Setup for workflow package action for task id: " + this.workflowTaskId); + } + + /** + * Setup a content document node context + * + * @param id GUID of the node to setup as the content document context + * + * @return The Node + */ + private Node setupContentDocument(String id) + { + if (logger.isDebugEnabled()) + logger.debug("Setup for action, setting current document to: " + id); + + Node node = null; + + try + { + // create the node ref, then our node representation + NodeRef ref = new NodeRef(Repository.getStoreRef(), id); + node = new Node(ref); + + // create content URL to the content download servlet with ID and expected filename + // the myfile part will be ignored by the servlet but gives the browser a hint + String url = DownloadContentServlet.generateDownloadURL(ref, node.getName()); + node.getProperties().put("url", url); + node.getProperties().put("workingCopy", node.hasAspect(ContentModel.ASPECT_WORKING_COPY)); + node.getProperties().put("fileType32", Utils.getFileTypeImage(node.getName(), false)); + + // remember the document + setDocument(node); + + // refresh the UI, calling this method now is fine as it basically makes sure certain + // beans clear the state - so when we finish here other beans will have been reset + UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans(); + } + catch (InvalidNodeRefException refErr) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) ); + } + + return node; + } + + /** + * Action called upon completion of the Check Out file page + */ + public String checkoutFile() + { + String outcome = null; + + UserTransaction tx = null; + + Node node = getDocument(); + if (node != null) + { + try + { + tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx.begin(); + + if (logger.isDebugEnabled()) + logger.debug("Trying to checkout content node Id: " + node.getId()); + + // checkout the node content to create a working copy + if (logger.isDebugEnabled()) + { + logger.debug("Checkout copy location: " + getCopyLocation()); + logger.debug("Selected Space Id: " + this.selectedSpaceId); + } + NodeRef workingCopyRef = null; + if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null) + { + // checkout to a arbituary parent Space + NodeRef destRef = this.selectedSpaceId; + + ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(destRef); + workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef(), + destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName()); + } + else + { + // checkout the content to the current space + workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef()); + + // if this is a workflow action and there is a task id present we need + // to also link the working copy to the workflow package so it appears + // in the resources panel in the manage task dialog + if (this.isWorkflowAction && this.workflowTaskId != null) + { + WorkflowTask task = this.workflowService.getTaskById(this.workflowTaskId); + if (task != null) + { + NodeRef workflowPackage = (NodeRef)task.properties.get(WorkflowModel.ASSOC_PACKAGE); + if (workflowPackage != null) + { + this.nodeService.addChild(workflowPackage, workingCopyRef, + ContentModel.ASSOC_CONTAINS, QName.createQName( + NamespaceService.CONTENT_MODEL_1_0_URI, + QName.createValidLocalName((String)this.nodeService.getProperty( + workingCopyRef, ContentModel.PROP_NAME)))); + + if (logger.isDebugEnabled()) + logger.debug("Added working copy to workflow package: " + workflowPackage); + } + } + } + } + + // set the working copy Node instance + Node workingCopy = new Node(workingCopyRef); + setWorkingDocument(workingCopy); + + // create content URL to the content download servlet with ID and expected filename + // the myfile part will be ignored by the servlet but gives the browser a hint + String url = DownloadContentServlet.generateDownloadURL(workingCopyRef, workingCopy.getName()); + + workingCopy.getProperties().put("url", url); + workingCopy.getProperties().put("fileType32", Utils.getFileTypeImage(workingCopy.getName(), false)); + + // commit the transaction + tx.commit(); + + // show the page that display the checkout link + outcome = "checkoutFileLink"; + } + catch (Throwable err) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_CHECKOUT) + err.getMessage(), err); + } + } + else + { + logger.warn("WARNING: checkoutFile called without a current Document!"); + } + + return outcome; + } + + /** + * Action called upon completion of the Check Out file Link download page + */ + public String checkoutFileOK() + { + String outcome = null; + + Node node = getWorkingDocument(); + if (node != null) + { + // reset the underlying node + if (this.browseBean.getDocument() != null) + { + this.browseBean.getDocument().reset(); + } + + // clean up and clear action context + resetState(); + setDocument(null); + setWorkingDocument(null); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + else + { + logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); + } + + return outcome; + } + + /** + * Action called upon completion of the Edit File download page + */ + public String editFileOK() + { + String outcome = null; + + Node node = getDocument(); + if (node != null) + { + // clean up and clear action context + resetState(); + setDocument(null); + setWorkingDocument(null); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + else + { + logger.warn("WARNING: editFileOK called without a current Document!"); + } + + return outcome; + } + + /** + * Action handler called to calculate which editing screen to display based on the mimetype + * of a document. If appropriate, the in-line editing screen will be shown. + */ + public void editFile(ActionEvent event) + { + UIActionLink link = (UIActionLink)event.getComponent(); + Map params = link.getParameterMap(); + String id = params.get("id"); + if (id != null && id.length() != 0) + { + boolean editingInline = false; + Node node = setupContentDocument(id); + + // detect the inline editing aspect to see which edit mode to use + if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) && + node.getProperties().get(ContentModel.PROP_EDITINLINE) != null && + ((Boolean)node.getProperties().get(ContentModel.PROP_EDITINLINE)).booleanValue() == true) + { + // retrieve the content reader for this node + ContentReader reader = getContentService().getReader(node.getNodeRef(), ContentModel.PROP_CONTENT); + if (reader != null) + { + editingInline = true; + String mimetype = reader.getMimetype(); + + // calculate which editor screen to display + if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype) || + MimetypeMap.MIMETYPE_XML.equals(mimetype) || + MimetypeMap.MIMETYPE_TEXT_CSS.equals(mimetype) || + MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype)) + { + // make content available to the editing screen + setEditorOutput(reader.getContentString()); + + // navigate to appropriate screen + FacesContext fc = FacesContext.getCurrentInstance(); + this.navigator.setupDispatchContext(node); + String outcome; + if (MimetypeMap.MIMETYPE_XML.equals(mimetype)) + { + outcome = "dialog:editXmlInline"; + } + else + { + outcome = "dialog:editTextInline"; + } + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, outcome); + } + else + { + // make content available to the editing screen + setDocumentContent(reader.getContentString()); + setEditorOutput(null); + + // navigate to appropriate screen + FacesContext fc = FacesContext.getCurrentInstance(); + this.navigator.setupDispatchContext(node); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline"); + } + } + } + + if (editingInline == false) + { + // normal downloadable document + FacesContext fc = FacesContext.getCurrentInstance(); + this.navigator.setupDispatchContext(node); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile"); + } + } + } + + /** + * Action handler called to set the content of a node from an inline editing page. + */ + public String editInlineOK() + { + String outcome = null; + + UserTransaction tx = null; + + Node node = getDocument(); + if (node != null) + { + try + { + tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); + tx.begin(); + + if (logger.isDebugEnabled()) + logger.debug("Trying to update content node Id: " + node.getId()); + + // get an updating writer that we can use to modify the content on the current node + ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); + writer.putContent(this.editorOutput); + + // commit the transaction + tx.commit(); + + // clean up and clear action context + resetState(); + setDocument(null); + setDocumentContent(null); + setEditorOutput(null); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + catch (Throwable err) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage()); + } + } + else + { + logger.warn("WARNING: editInlineOK called without a current Document!"); + } + + return outcome; + } + + /** + * Action to undo the checkout of a document just checked out from the checkout screen. + */ + public String undoCheckout() + { + String outcome = null; + + Node node = getWorkingDocument(); + if (node != null) + { + try + { + // try to cancel checkout of the working copy + this.versionOperationsService.cancelCheckout(node.getNodeRef()); + + resetState(); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + catch (Throwable err) + { + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err); + } + } + else + { + logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + } + + return outcome; + } + + /** + * Action to undo the checkout of a locked document. This document may either by the original copy + * or the working copy node. Therefore calculate which it is, if the working copy is found then + * we simply cancel checkout on that document. If the original copy is found then we need to find + * the appropriate working copy and perform the action on that node. + */ + public String undoCheckoutFile() + { + String outcome = null; + + Node node = getDocument(); + if (node != null) + { + try + { + if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY)) + { + this.versionOperationsService.cancelCheckout(node.getNodeRef()); + } + else if (node.hasAspect(ContentModel.ASPECT_LOCKABLE)) + { + // TODO: find the working copy for this document and cancel the checkout on it + // is this possible? as currently only the workingcopy aspect has the copyReference + // attribute - this means we cannot find out where the copy is to cancel it! + // can we construct an XPath node lookup? + throw new RuntimeException("NOT IMPLEMENTED"); + } + else + { + throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!"); + } + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + + if (this.isWorkflowAction == false) + { + outcome = outcome + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; + } + + resetState(); + } + catch (Throwable err) + { + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err); + } + } + else + { + logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + } + + return outcome; + } + + /** + * Action called upon completion of the Check In file page + */ + public String checkinFileOK() + { + String outcome = null; + + UserTransaction tx = null; + + // NOTE: for checkin the document node _is_ the working document! + Node node = getDocument(); + if (node != null && (getCopyLocation().equals(COPYLOCATION_CURRENT) || this.getFileName() != null)) + { + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context); + tx.begin(); + + if (logger.isDebugEnabled()) + logger.debug("Trying to checkin content node Id: " + node.getId()); + + // we can either checkin the content from the current working copy node + // which would have been previously updated by the user + String contentUrl; + if (getCopyLocation().equals(COPYLOCATION_CURRENT)) + { + ContentData contentData = (ContentData) node.getProperties().get(ContentModel.PROP_CONTENT); + contentUrl = (contentData == null ? null : contentData.getContentUrl()); + } + // or specify a specific file as the content instead + else + { + // add the content to an anonymous but permanent writer location + // we can then retrieve the URL to the content to to be set on the node during checkin + ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); + // also update the mime type in case a different type of file is uploaded + String mimeType = Repository.getMimeTypeForFileName(context, this.fileName); + writer.setMimetype(mimeType); + writer.putContent(this.file); + contentUrl = writer.getContentUrl(); + } + + if (contentUrl == null || contentUrl.length() == 0) + { + throw new IllegalStateException("Content URL is empty for specified working copy content node!"); + } + + // add version history text to props + Map props = new HashMap(1, 1.0f); + props.put(Version.PROP_DESCRIPTION, this.versionNotes); + // set the flag for minor or major change + if (this.minorChange) + { + props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR); + } + else + { + props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR); + } + + // perform the checkin + this.versionOperationsService.checkin(node.getNodeRef(), + props, contentUrl, this.keepCheckedOut); + + // commit the transaction + tx.commit(); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + + if (this.isWorkflowAction == false) + { + outcome = outcome + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse"; + } + + // clear action context + setDocument(null); + resetState(); + } + catch (Throwable err) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_CHECKIN) + err.getMessage(), err); + } + } + else + { + logger.warn("WARNING: checkinFileOK called without a current Document!"); + } + + return outcome; + } + + /** + * Action called upon completion of the Update File page + */ + public String updateFileOK() + { + String outcome = null; + + UserTransaction tx = null; + + // NOTE: for update the document node _is_ the working document! + Node node = getDocument(); + if (node != null && this.getFileName() != null) + { + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context); + tx.begin(); + + if (logger.isDebugEnabled()) + logger.debug("Trying to update content node Id: " + node.getId()); + + // get an updating writer that we can use to modify the content on the current node + ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); + + // also update the mime type in case a different type of file is uploaded + String mimeType = Repository.getMimeTypeForFileName(context, this.fileName); + writer.setMimetype(mimeType); + + writer.putContent(this.file); + + // commit the transaction + tx.commit(); + + // clear action context + setDocument(null); + resetState(); + + outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + catch (Throwable err) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + Utils.addErrorMessage(Application.getMessage( + FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage(), err); + } + } + else + { + logger.warn("WARNING: updateFileOK called without a current Document!"); + } + + return outcome; + } + + /** + * Deals with the cancel button being pressed on the check in file page + */ + public String cancel() + { + // reset the state + resetState(); + + return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; + } + + /** + * Clear form state and upload file bean + */ + private void resetState() + { + // delete the temporary file we uploaded earlier + if (this.file != null) + { + this.file.delete(); + } + + this.file = null; + this.fileName = null; + this.keepCheckedOut = false; + this.minorChange = true; + this.copyLocation = COPYLOCATION_CURRENT; + this.versionNotes = ""; + this.selectedSpaceId = null; + this.isWorkflowAction = false; + this.workflowTaskId = null; + + // remove the file upload bean from the session + FacesContext ctx = FacesContext.getCurrentInstance(); + ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME); + } + + + // ------------------------------------------------------------------------------ + // Private data + + private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class); + + /** I18N messages */ + public static final String MSG_ERROR_CHECKIN = "error_checkin"; + public static final String MSG_ERROR_CANCELCHECKOUT = "error_cancel_checkout"; + public static final String MSG_ERROR_UPDATE = "error_update"; + public static final String MSG_ERROR_CHECKOUT = "error_checkout"; + + /** constants for copy location selection */ + private static final String COPYLOCATION_CURRENT = "current"; + private static final String COPYLOCATION_OTHER = "other"; + + /** The current document */ + private Node document; + + /** The working copy of the document we are checking out */ + private Node workingDocument; + + /** Content of the document used for HTML in-line editing */ + private String documentContent; + + /** Content of the document returned from in-line editing */ + private String editorOutput; + + /** transient form and upload properties */ + private File file; + private String fileName; + private boolean keepCheckedOut = false; + private boolean minorChange = true; + private boolean isWorkflowAction = false; + private String workflowTaskId; + private String copyLocation = COPYLOCATION_CURRENT; + private String versionNotes = ""; + private NodeRef selectedSpaceId = null; + + /** The BrowseBean to be used by the bean */ + protected BrowseBean browseBean; + + /** The NavigationBean bean reference */ + protected NavigationBean navigator; + + /** The NodeService to be used by the bean */ + protected NodeService nodeService; + + /** The VersionOperationsService to be used by the bean */ + protected CheckOutCheckInService versionOperationsService; + + /** The ContentService to be used by the bean */ + protected ContentService contentService; + + /** The WorkflowService to be used by the bean */ + protected WorkflowService workflowService; +} diff --git a/source/java/org/alfresco/web/bean/SearchContext.java b/source/java/org/alfresco/web/bean/SearchContext.java index cf5b0855e1..52f8dc4610 100644 --- a/source/java/org/alfresco/web/bean/SearchContext.java +++ b/source/java/org/alfresco/web/bean/SearchContext.java @@ -86,6 +86,7 @@ public final class SearchContext implements Serializable private static final char OP_WILDCARD = '*'; private static final char OP_AND = '+'; private static final char OP_NOT = '-'; + private static final String STR_OP_WILDCARD = "" + OP_WILDCARD; /** Search mode constants */ public final static int SEARCH_ALL = 0; @@ -174,21 +175,7 @@ public final class SearchContext implements Serializable nameAttrBuf.append(OP_NOT); } - // simple single word text search - if (text.charAt(0) != OP_WILDCARD) - { - // escape characters and append the wildcard character - String safeText = QueryParser.escape(text); - fullTextBuf.append("TEXT:").append(safeText).append(OP_WILDCARD); - nameAttrBuf.append("@").append(nameAttr).append(":").append(safeText).append(OP_WILDCARD); - } - else - { - // found a leading wildcard - prepend it again after escaping the other characters - String safeText = QueryParser.escape(text.substring(1)); - fullTextBuf.append("TEXT:*").append(safeText).append(OP_WILDCARD); - nameAttrBuf.append("@").append(nameAttr).append(":*").append(safeText).append(OP_WILDCARD); - } + processSearchTextAttribute(nameAttr, text, nameAttrBuf, fullTextBuf); } } else @@ -253,18 +240,8 @@ public final class SearchContext implements Serializable nameAttrBuf.append(OP_AND); } - if (term.charAt(0) != OP_WILDCARD) - { - String safeTerm = QueryParser.escape(term); - fullTextBuf.append("TEXT:").append(safeTerm).append(OP_WILDCARD); - nameAttrBuf.append("@").append(nameAttr).append(":").append(safeTerm).append(OP_WILDCARD); - } - else - { - String safeTerm = QueryParser.escape(term.substring(1)); - fullTextBuf.append("TEXT:*").append(safeTerm).append(OP_WILDCARD); - nameAttrBuf.append("@").append(nameAttr).append(":*").append(safeTerm).append(OP_WILDCARD); - } + processSearchTextAttribute(nameAttr, term, nameAttrBuf, fullTextBuf); + fullTextBuf.append(' '); nameAttrBuf.append(' '); @@ -317,11 +294,9 @@ public final class SearchContext implements Serializable for (QName qname : queryAttributes.keySet()) { String value = queryAttributes.get(qname).trim(); - if (value.length() != 0 && value.length() >= minimum) + if (value.length() >= minimum) { - String escapedName = Repository.escapeQName(qname); - attributeQuery.append(" +@").append(escapedName) - .append(":").append(QueryParser.escape(value)).append(OP_WILDCARD); + processSearchAttribute(qname, value, attributeQuery); } } @@ -480,6 +455,114 @@ public final class SearchContext implements Serializable return query; } + /** + * Build the lucene search terms required for the specified attribute and append to a buffer. + * Supports text values with a wildcard '*' character as the prefix and/or the suffix. + * + * @param qname QName of the attribute + * @param value Non-null value of the attribute + * @param buf Buffer to append lucene terms to + */ + private static void processSearchAttribute(QName qname, String value, StringBuilder buf) + { + if (value.indexOf(' ') == -1) + { + String safeValue; + String prefix = ""; + String suffix = ""; + + // look for a wildcard suffix + if (value.charAt(value.length() - 1) != OP_WILDCARD) + { + // look for wildcard prefix + if (value.charAt(0) != OP_WILDCARD) + { + safeValue = QueryParser.escape(value); + } + else + { + safeValue = QueryParser.escape(value.substring(1)); + prefix = STR_OP_WILDCARD; + } + } + else + { + // found a wildcard suffix - append it again after escaping the other characters + suffix = STR_OP_WILDCARD; + + // look for wildcard prefix + if (value.charAt(0) != OP_WILDCARD) + { + safeValue = QueryParser.escape(value.substring(0, value.length() - 1)); + } + else + { + safeValue = QueryParser.escape(value.substring(1, value.length() - 1)); + prefix = STR_OP_WILDCARD; + } + } + + buf.append(" +@").append(Repository.escapeQName(qname)).append(":") + .append(prefix).append(safeValue).append(suffix); + } + else + { + // phrase multi-word search + String safeValue = QueryParser.escape(value); + buf.append(" +@").append(Repository.escapeQName(qname)).append(":\"").append(safeValue).append('"'); + } + } + + /** + * Build the lucene search terms required for the specified attribute and append to multiple buffers. + * Supports text values with a wildcard '*' character as the prefix and/or the suffix. + * + * @param qname QName.toString() of the attribute + * @param value Non-null value of the attribute + * @param attrBuf Attribute search buffer to append lucene terms to + * @param textBuf Text search buffer to append lucene terms to + */ + private static void processSearchTextAttribute(String qname, String value, StringBuilder attrBuf, StringBuilder textBuf) + { + String safeValue; + String suffix = ""; + String prefix = ""; + + if (value.charAt(value.length() - 1) != OP_WILDCARD) + { + // look for wildcard prefix + if (value.charAt(0) != OP_WILDCARD) + { + safeValue = QueryParser.escape(value); + } + else + { + // found a leading wildcard - prepend it again after escaping the other characters + prefix = STR_OP_WILDCARD; + safeValue = QueryParser.escape(value.substring(1)); + } + } + else + { + suffix = STR_OP_WILDCARD; + + // look for wildcard prefix + if (value.charAt(0) != OP_WILDCARD) + { + safeValue = QueryParser.escape(value.substring(0, value.length() - 1)); + } + else + { + prefix = STR_OP_WILDCARD; + safeValue = QueryParser.escape(value.substring(1, value.length() - 1)); + } + } + + textBuf.append("TEXT:").append(prefix).append(safeValue).append(suffix); + attrBuf.append("@").append(qname).append(":") + .append(prefix).append(safeValue).append(suffix); + } + /** * Generate a search XPATH pointing to the specified node, optionally return an XPATH * that includes the child nodes. diff --git a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java index 39b0793ad3..5e3bc342a0 100644 --- a/source/java/org/alfresco/web/bean/SpaceDetailsBean.java +++ b/source/java/org/alfresco/web/bean/SpaceDetailsBean.java @@ -34,6 +34,7 @@ import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; +import org.alfresco.web.app.servlet.GuestTemplateContentServlet; import org.alfresco.web.app.servlet.TemplateContentServlet; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; @@ -506,9 +507,9 @@ public class SpaceDetailsBean extends BaseDetailsBean // build RSS feed template URL from selected template and the space NodeRef and // add the guest=true URL parameter - this is required for no login access and // add the mimetype=text/xml URL parameter - required to return correct stream type - return TemplateContentServlet.generateURL(space.getNodeRef(), + return GuestTemplateContentServlet.generateURL(space.getNodeRef(), (NodeRef)space.getProperties().get(ContentModel.PROP_FEEDTEMPLATE)) - + "/rss.xml?guest=true" + "&mimetype=text%2Fxml"; + + "/rss.xml?mimetype=text%2Fxml"; } /** diff --git a/source/java/org/alfresco/web/bean/dialog/DialogManager.java b/source/java/org/alfresco/web/bean/dialog/DialogManager.java index f4238e9131..272266819e 100644 --- a/source/java/org/alfresco/web/bean/dialog/DialogManager.java +++ b/source/java/org/alfresco/web/bean/dialog/DialogManager.java @@ -71,14 +71,14 @@ public final class DialogManager "' does not implement the required IDialogBean interface"); } + // create the DialogState object + this.currentDialogState = new DialogState(config, dialog); + // initialise the managed bean dialog.init(this.paramsToApply); // reset the current parameters so subsequent dialogs don't get them this.paramsToApply = null; - - // create the DialogState object - this.currentDialogState = new DialogState(config, dialog); } /** diff --git a/source/java/org/alfresco/web/bean/repository/Node.java b/source/java/org/alfresco/web/bean/repository/Node.java index f5e3388f19..c892abaadf 100644 --- a/source/java/org/alfresco/web/bean/repository/Node.java +++ b/source/java/org/alfresco/web/bean/repository/Node.java @@ -89,7 +89,7 @@ public class Node implements Serializable /** * @return All the properties known about this node. */ - public Map getProperties() + public final Map getProperties() { if (this.propsRetrieved == false) { diff --git a/source/java/org/alfresco/web/bean/repository/TransientNode.java b/source/java/org/alfresco/web/bean/repository/TransientNode.java index 9f5332fd8b..fa7ca06c0a 100644 --- a/source/java/org/alfresco/web/bean/repository/TransientNode.java +++ b/source/java/org/alfresco/web/bean/repository/TransientNode.java @@ -70,6 +70,9 @@ public class TransientNode extends Node // setup the transient node so that the super class methods work // and do not need to go back to the repository + if (logger.isDebugEnabled()) + logger.debug("Initialising transient node with data: " + data); + DictionaryService ddService = this.getServiceRegistry().getDictionaryService(); // marshall the given properties and associations into the internal maps @@ -94,25 +97,11 @@ public class TransientNode extends Node { if (assocDef.isChild()) { - // TODO: handle lists of NodeRef's - NodeRef child = null; Object obj = data.get(item); - if (obj instanceof String) - { - child = new NodeRef((String)obj); - } - else if (obj instanceof NodeRef) - { - child = (NodeRef)obj; - } - else if (obj instanceof List) - { - if (logger.isWarnEnabled()) - logger.warn("0..* child associations are not supported yet"); - } - - if (child != null) + if (obj instanceof NodeRef) { + NodeRef child = (NodeRef)obj; + // create a child association reference, add it to a list and add the list // to the list of child associations for this node List assocs = new ArrayList(1); @@ -122,28 +111,36 @@ public class TransientNode extends Node this.childAssociations.put(item, assocs); } + else if (obj instanceof List) + { + List targets = (List)obj; + + List assocs = new ArrayList(targets.size()); + + for (Object target : targets) + { + if (target instanceof NodeRef) + { + NodeRef currentChild = (NodeRef)target; + ChildAssociationRef childRef = new ChildAssociationRef(assocDef.getName(), + this.nodeRef, null, currentChild); + assocs.add(childRef); + } + } + + if (assocs.size() > 0) + { + this.childAssociations.put(item, assocs); + } + } } else { - // TODO: handle lists of NodeRef's - NodeRef target = null; Object obj = data.get(item); - if (obj instanceof String) - { - target = new NodeRef((String)obj); - } - else if (obj instanceof NodeRef) - { - target = (NodeRef)obj; - } - else if (obj instanceof List) - { - if (logger.isWarnEnabled()) - logger.warn("0..* associations are not supported yet"); - } - - if (target != null) + if (obj instanceof NodeRef) { + NodeRef target = (NodeRef)obj; + // create a association reference, add it to a list and add the list // to the list of associations for this node List assocs = new ArrayList(1); @@ -152,6 +149,27 @@ public class TransientNode extends Node this.associations.put(item, assocs); } + else if (obj instanceof List) + { + List targets = (List)obj; + + List assocs = new ArrayList(targets.size()); + + for (Object target : targets) + { + if (target instanceof NodeRef) + { + NodeRef currentTarget = (NodeRef)target; + AssociationRef assocRef = new AssociationRef(this.nodeRef, assocDef.getName(), currentTarget); + assocs.add(assocRef); + } + } + + if (assocs.size() > 0) + { + this.associations.put(item, assocs); + } + } } } } diff --git a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java index 2e63eb4630..04ba84f892 100644 --- a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java +++ b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java @@ -136,7 +136,7 @@ public class ManageTaskDialog extends BaseDialogBean logger.debug("Saving task: " + this.task.id); // prepare the edited parameters for saving - Map params = WorkflowBean.prepareTaskParams(this.taskNode); + Map params = WorkflowUtil.prepareTaskParams(this.taskNode); if (logger.isDebugEnabled()) logger.debug("Saving task with parameters: " + params); @@ -262,7 +262,7 @@ public class ManageTaskDialog extends BaseDialogBean tx.begin(); // prepare the edited parameters for saving - Map params = WorkflowBean.prepareTaskParams(this.taskNode); + Map params = WorkflowUtil.prepareTaskParams(this.taskNode); if (logger.isDebugEnabled()) logger.debug("Transitioning task with parameters: " + params); @@ -399,7 +399,7 @@ public class ManageTaskDialog extends BaseDialogBean */ public void togglePackageItemComplete(ActionEvent event) { - // TODO: implement this! + // TODO: not supported yet } // ------------------------------------------------------------------------------ diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java index 7425da8575..5616f95813 100644 --- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java +++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java @@ -119,7 +119,7 @@ public class StartWorkflowWizard extends BaseWizardBean logger.debug("Starting workflow: " + this.selectedWorkflow); // prepare the parameters from the current state of the property sheet - Map params = WorkflowBean.prepareTaskParams(this.startTaskNode); + Map params = WorkflowUtil.prepareTaskParams(this.startTaskNode); if (logger.isDebugEnabled()) logger.debug("Starting workflow with parameters: " + params); diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java index 4e5da783fd..eca548a8ed 100644 --- a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java @@ -1,25 +1,19 @@ package org.alfresco.web.bean.workflow; -import java.io.Serializable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.faces.context.FacesContext; import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.workflow.WorkflowModel; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition; import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.cmr.workflow.WorkflowTransition; -import org.alfresco.service.namespace.QName; import org.alfresco.util.ISO9075; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; @@ -31,7 +25,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Managed bean used for handling workflow related features + * Managed bean used for providing support for the workflow task dashlets * * @author gavinc */ @@ -55,40 +49,43 @@ public class WorkflowBean */ public List getTasksToDo() { - // get the current username - FacesContext context = FacesContext.getCurrentInstance(); - User user = Application.getCurrentUser(context); - String userName = ISO9075.encode(user.getUserName()); - - UserTransaction tx = null; - try + if (this.tasks == null) { - tx = Repository.getUserTransaction(context, true); - tx.begin(); + // get the current username + FacesContext context = FacesContext.getCurrentInstance(); + User user = Application.getCurrentUser(context); + String userName = ISO9075.encode(user.getUserName()); - // get the current in progress tasks for the current user - List tasks = this.workflowService.getAssignedTasks( - userName, WorkflowTaskState.IN_PROGRESS); - - // create a list of transient nodes to represent - this.tasks = new ArrayList(tasks.size()); - for (WorkflowTask task : tasks) + UserTransaction tx = null; + try { - Node node = createTask(task); - this.tasks.add(node); + tx = Repository.getUserTransaction(context, true); + tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Added to do task: " + node); + // get the current in progress tasks for the current user + List tasks = this.workflowService.getAssignedTasks( + userName, WorkflowTaskState.IN_PROGRESS); + + // create a list of transient nodes to represent + this.tasks = new ArrayList(tasks.size()); + for (WorkflowTask task : tasks) + { + Node node = createTask(task); + this.tasks.add(node); + + if (logger.isDebugEnabled()) + logger.debug("Added to do task: " + node); + } + + // commit the changes + tx.commit(); + } + catch (Throwable e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage("Failed to get to do tasks: " + e.toString(), e); } - - // commit the changes - tx.commit(); - } - catch (Throwable e) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} - Utils.addErrorMessage("Failed to get to do tasks: " + e.toString(), e); } return this.tasks; @@ -102,40 +99,43 @@ public class WorkflowBean */ public List getTasksCompleted() { - // get the current username - FacesContext context = FacesContext.getCurrentInstance(); - User user = Application.getCurrentUser(context); - String userName = ISO9075.encode(user.getUserName()); - - UserTransaction tx = null; - try + if (this.completedTasks == null) { - tx = Repository.getUserTransaction(context, true); - tx.begin(); + // get the current username + FacesContext context = FacesContext.getCurrentInstance(); + User user = Application.getCurrentUser(context); + String userName = ISO9075.encode(user.getUserName()); - // get the current in progress tasks for the current user - List tasks = this.workflowService.getAssignedTasks( - userName, WorkflowTaskState.COMPLETED); - - // create a list of transient nodes to represent - this.completedTasks = new ArrayList(tasks.size()); - for (WorkflowTask task : tasks) + UserTransaction tx = null; + try { - Node node = createTask(task); - this.completedTasks.add(node); + tx = Repository.getUserTransaction(context, true); + tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Added completed task: " + node); + // get the current in progress tasks for the current user + List tasks = this.workflowService.getAssignedTasks( + userName, WorkflowTaskState.COMPLETED); + + // create a list of transient nodes to represent + this.completedTasks = new ArrayList(tasks.size()); + for (WorkflowTask task : tasks) + { + Node node = createTask(task); + this.completedTasks.add(node); + + if (logger.isDebugEnabled()) + logger.debug("Added completed task: " + node); + } + + // commit the changes + tx.commit(); } - - // commit the changes - tx.commit(); - } - catch (Throwable e) - { - // rollback the transaction - try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} - Utils.addErrorMessage("Failed to get completed tasks: " + e.toString(), e); + catch (Throwable e) + { + // rollback the transaction + try { if (tx != null) {tx.rollback();} } catch (Exception ex) {} + Utils.addErrorMessage("Failed to get completed tasks: " + e.toString(), e); + } } return this.completedTasks; @@ -163,47 +163,6 @@ public class WorkflowBean // ------------------------------------------------------------------------------ // Helper methods - - public static Map prepareTaskParams(Node node) - { - Map params = new HashMap(); - - // marshal the properties and associations captured by the property sheet - // back into a Map to pass to the workflow service - - // go through all the properties in the transient node and add them to - // params map - Map props = node.getProperties(); - for (String propName : props.keySet()) - { - QName propQName = Repository.resolveToQName(propName); - params.put(propQName, (Serializable)props.get(propName)); - } - - // go through any associations that have been added to the start task - // and build a list of NodeRefs representing the targets - Map> assocs = node.getAddedAssociations(); - for (String assocName : assocs.keySet()) - { - QName assocQName = Repository.resolveToQName(assocName); - - // get the associations added and create list of targets - Map addedAssocs = assocs.get(assocName); - List targets = new ArrayList(addedAssocs.size()); - for (AssociationRef assoc : addedAssocs.values()) - { - targets.add(assoc.getTargetRef()); - } - - // add the targets for this particular association - if (targets.size() > 0) - { - params.put(assocQName, (Serializable)targets); - } - } - - return params; - } /** * Creates and populates a TransientNode to represent the given @@ -225,15 +184,6 @@ public class WorkflowBean node.getProperties().put("type", taskDef.metadata.getTitle()); node.getProperties().put("id", task.id); - // add the name of the source space (if there is one) - NodeRef context = (NodeRef)task.properties.get(WorkflowModel.PROP_CONTEXT); - if (context != null && this.nodeService.exists(context)) - { - String name = Repository.getNameForNode(this.nodeService, context); - node.getProperties().put("sourceSpaceName", name); - node.getProperties().put("sourceSpaceId", context.getId()); - } - // add extra properties for completed tasks if (task.state.equals(WorkflowTaskState.COMPLETED)) { @@ -260,6 +210,9 @@ public class WorkflowBean // add the workflow instance id and name this taks belongs to node.getProperties().put("workflowInstanceId", task.path.instance.id); + + // add the task itself as a property + node.getProperties().put("workflowTask", task); } return node; diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowConsoleBean.java b/source/java/org/alfresco/web/bean/workflow/WorkflowConsoleBean.java new file mode 100644 index 0000000000..cdf66e8149 --- /dev/null +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowConsoleBean.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.web.bean.workflow; + +import org.alfresco.repo.workflow.WorkflowInterpreter; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; + + +/** + * Backing bean to support the Workflow Console + */ +public class WorkflowConsoleBean +{ + // command + private String command = ""; + private String submittedCommand = "none"; + private long duration = 0L; + private String result = null; + + // supporting repository services + private WorkflowInterpreter workflowInterpreter; + + + /** + * @param nodeService node service + */ + public void setWorkflowInterpreter(WorkflowInterpreter workflowInterpreter) + { + this.workflowInterpreter = workflowInterpreter; + } + + /** + * 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 query + * + * @param query query statement + */ + public void setCommand(String command) + { + this.command = command; + } + + /** + * Gets the submitted command + * + * @return submitted command + */ + public String getSubmittedCommand() + { + return submittedCommand; + } + + /** + * Set the current query + * + * @param query query statement + */ + public void setSubmittedCommand(String submittedCommand) + { + this.submittedCommand = submittedCommand; + } + + /** + * Gets the last command duration + * + * @return command duration + */ + public long getDuration() + { + return duration; + } + + /** + * Set the current query + * + * @param query query statement + */ + 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 workflowInterpreter.getCurrentUserName(); + } + + /** + * Gets the current workflow definition + * + * @return workflow definition + */ + public String getCurrentWorkflowDef() + { + WorkflowDefinition def = workflowInterpreter.getCurrentWorkflowDef(); + return (def == null) ? "None" : def.title + " v" + def.version; + } + + /** + * Interpret workflow console command + * + * @param command command + */ + private void interpretCommand(String command) + { + try + { + long startms = System.currentTimeMillis(); + String result = workflowInterpreter.interpretCommand(command); + setDuration(System.currentTimeMillis() - startms); + setResult(result); + setCommand(""); + setSubmittedCommand(command); + } + catch (Exception e) + { + setResult(e.toString()); + } + } + +} diff --git a/source/java/org/alfresco/web/bean/WorkflowUtil.java b/source/java/org/alfresco/web/bean/workflow/WorkflowUtil.java similarity index 64% rename from source/java/org/alfresco/web/bean/WorkflowUtil.java rename to source/java/org/alfresco/web/bean/workflow/WorkflowUtil.java index fa57b332d7..2f6412f4e9 100644 --- a/source/java/org/alfresco/web/bean/WorkflowUtil.java +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowUtil.java @@ -14,22 +14,29 @@ * language governing permissions and limitations under the * License. */ -package org.alfresco.web.bean; +package org.alfresco.web.bean.workflow; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.CopyService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.web.bean.repository.Node; -import org.apache.log4j.Logger; +import org.alfresco.web.bean.repository.Repository; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** - * Helper class for common Simple Workflow functionality. + * Helper class for common Workflow functionality. *

* This class should be replaced with calls to a WorkflowService once it is available. * @@ -37,7 +44,7 @@ import org.apache.log4j.Logger; */ public class WorkflowUtil { - private static Logger logger = Logger.getLogger(WorkflowUtil.class); + private static Log logger = LogFactory.getLog(WorkflowUtil.class); /** * Execute the Approve step for the Simple Workflow on a node. @@ -139,9 +146,14 @@ public class WorkflowUtil else { // copy the document to the specified folder - String qname = QName.createValidLocalName(docNode.getName()); - copyService.copy(ref, rejectFolder, ContentModel.ASSOC_CONTAINS, - QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, qname)); + String name = docNode.getName(); + String qname = QName.createValidLocalName(name); + NodeRef newNode = copyService.copy(ref, rejectFolder, ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, qname), true); + + // the copy service does not copy the name of the node so we + // need to update the property on the copied item + nodeService.setProperty(newNode, ContentModel.PROP_NAME, name); } if (logger.isDebugEnabled()) @@ -151,4 +163,60 @@ public class WorkflowUtil rejectFolder.getId()); } } + + /** + * Prepares the given node for persistence in the workflow engine. + * + * @param node The node to package up for persistence + * @return The map of data representing the node + */ + public static Map prepareTaskParams(Node node) + { + Map params = new HashMap(); + + // marshal the properties and associations captured by the property sheet + // back into a Map to pass to the workflow service + + // go through all the properties in the transient node and add them to + // params map + Map props = node.getProperties(); + for (String propName : props.keySet()) + { + QName propQName = Repository.resolveToQName(propName); + params.put(propQName, (Serializable)props.get(propName)); + } + + // go through any associations that have been added to the start task + // and build a list of NodeRefs representing the targets + Map> assocs = node.getAddedAssociations(); + for (String assocName : assocs.keySet()) + { + QName assocQName = Repository.resolveToQName(assocName); + + // get the associations added and create list of targets + Map addedAssocs = assocs.get(assocName); + List targets = new ArrayList(addedAssocs.size()); + for (AssociationRef assoc : addedAssocs.values()) + { + targets.add(assoc.getTargetRef()); + } + + // add the targets for this particular association + if (targets.size() > 0) + { + params.put(assocQName, (Serializable)targets); + } + } + + // TODO: Deal with child associations if and when we need to support + // them for workflow tasks, for now warn that they are being used + Map childAssocs = node.getAddedChildAssociations(); + if (childAssocs.size() > 0) + { + if (logger.isWarnEnabled()) + logger.warn("Child associations are present but are not supported for workflow tasks, ignoring..."); + } + + return params; + } } diff --git a/source/java/org/alfresco/web/config/ClientConfigElement.java b/source/java/org/alfresco/web/config/ClientConfigElement.java index eba6408ad9..e8a384439f 100644 --- a/source/java/org/alfresco/web/config/ClientConfigElement.java +++ b/source/java/org/alfresco/web/config/ClientConfigElement.java @@ -36,13 +36,19 @@ public class ClientConfigElement extends ConfigElementAdapter private int searchMinimum = 3; private boolean forceAndTerms = false; private int searchMaxResults = -1; + private int selectorsSearchMaxResults = 500; private String helpUrl = null; private String editLinkType = "http"; private String homeSpacePermission = null; +<<<<<<< .working private boolean ajaxEnabled = false; private String initialLocation = "myalfresco"; private String wcmDomain = null; private String wcmPort = null; +======= + private boolean ajaxEnabled = false; + private String initialLocation = "myalfresco"; +>>>>>>> .merge-right.r4305 /** * Default Constructor @@ -137,17 +143,34 @@ public class ClientConfigElement extends ConfigElementAdapter combinedElement.setSearchMaxResults(newElement.getSearchMaxResults()); } +<<<<<<< .working if (newElement.isShelfVisible() != combinedElement.isShelfVisible()) +======= + if (newElement.getSelectorsSearchMaxResults() != combinedElement.getSelectorsSearchMaxResults()) +>>>>>>> .merge-right.r4305 { +<<<<<<< .working combinedElement.setShelfVisible(newElement.isShelfVisible()); +======= + combinedElement.setSelectorsSearchMaxResults(newElement.getSelectorsSearchMaxResults()); +>>>>>>> .merge-right.r4305 } +<<<<<<< .working if (newElement.getFromEmailAddress() != null && (newElement.getFromEmailAddress().equals(combinedElement.getFromEmailAddress()) == false)) +======= + if (newElement.isShelfVisible() != combinedElement.isShelfVisible()) +>>>>>>> .merge-right.r4305 { +<<<<<<< .working combinedElement.setFromEmailAddress(newElement.getFromEmailAddress()); +======= + combinedElement.setShelfVisible(newElement.isShelfVisible()); +>>>>>>> .merge-right.r4305 } +<<<<<<< .working if (newElement.isAjaxEnabled() != combinedElement.isAjaxEnabled()) { combinedElement.setAjaxEnabled(newElement.isAjaxEnabled()); @@ -178,6 +201,26 @@ public class ClientConfigElement extends ConfigElementAdapter } return combinedElement; +======= + if (newElement.getFromEmailAddress() != null && + (newElement.getFromEmailAddress().equals(combinedElement.getFromEmailAddress()) == false)) + { + combinedElement.setFromEmailAddress(newElement.getFromEmailAddress()); + } + + if (newElement.isAjaxEnabled() != combinedElement.isAjaxEnabled()) + { + combinedElement.setAjaxEnabled(newElement.isAjaxEnabled()); + } + + if (newElement.getInitialLocation() != null && + newElement.getInitialLocation().equals(combinedElement.getInitialLocation()) == false) + { + combinedElement.setInitialLocation(newElement.getInitialLocation()); + } + + return combinedElement; +>>>>>>> .merge-right.r4305 } /** @@ -330,10 +373,9 @@ public class ClientConfigElement extends ConfigElementAdapter * * @return */ - public int getSearchMaxResults() { - return searchMaxResults; + return this.searchMaxResults; } /** @@ -346,6 +388,29 @@ public class ClientConfigElement extends ConfigElementAdapter { this.searchMaxResults = searchMaxResults; } + + /** + * If positive, this will limit the size of the result set from the search + * used in selector components. + * + * @return The maximum number of results to display + */ + public int getSelectorsSearchMaxResults() + { + return this.selectorsSearchMaxResults; + } + + /** + * Set if the the result set from a search for the selector components + * will be of limited size. If negative it is unlimited, by default, + * this is set to 500. + * + * @param selectorsSearchMaxResults + */ + /*package*/ void setSelectorsSearchMaxResults(int selectorsSearchMaxResults) + { + this.selectorsSearchMaxResults = selectorsSearchMaxResults; + } /** * @return Returns the default Home Space permissions. @@ -362,6 +427,7 @@ public class ClientConfigElement extends ConfigElementAdapter { this.homeSpacePermission = homeSpacePermission; } +<<<<<<< .working /** * @return Returns whether AJAX support is enabled in the client @@ -428,4 +494,40 @@ public class ClientConfigElement extends ConfigElementAdapter { this.wcmPort = wcmPort; } +======= + + /** + * @return Returns whether AJAX support is enabled in the client + */ + public boolean isAjaxEnabled() + { + return this.ajaxEnabled; + } + + /** + * Sets whether AJAX support is enabled in the client + * + * @param ajaxEnabled + */ + /*package*/ void setAjaxEnabled(boolean ajaxEnabled) + { + this.ajaxEnabled = ajaxEnabled; + } + + /** + * @return Returns the default initial location for the user. + */ + public String getInitialLocation() + { + return this.initialLocation; + } + + /** + * @param initialLocation The initial location to set. + */ + /*package*/ void setInitialLocation(String initialLocation) + { + this.initialLocation = initialLocation; + } +>>>>>>> .merge-right.r4305 } diff --git a/source/java/org/alfresco/web/config/ClientElementReader.java b/source/java/org/alfresco/web/config/ClientElementReader.java index 593112d366..9b6d81e7ea 100644 --- a/source/java/org/alfresco/web/config/ClientElementReader.java +++ b/source/java/org/alfresco/web/config/ClientElementReader.java @@ -36,6 +36,7 @@ public class ClientElementReader implements ConfigElementReader public static final String ELEMENT_SEARCHMINIMUM = "search-minimum"; public static final String ELEMENT_SEARCHANDTERMS = "search-and-terms"; public static final String ELEMENT_SEARCHMAXRESULTS = "search-max-results"; + public static final String ELEMENT_SELECTORSSEARCHMAXRESULTS = "selectors-search-max-results"; public static final String ELEMENT_HOMESPACEPERMISSION = "home-space-permission"; public static final String ELEMENT_FROMEMAILADDRESS = "from-email-address"; public static final String ELEMENT_SHELFVISIBLE = "shelf-visible"; @@ -113,6 +114,14 @@ public class ClientElementReader implements ConfigElementReader configElement.setSearchMaxResults(Integer.parseInt(searchMaxResults.getTextTrim())); } + // get the selectors search max results size + Element selectorsSearchMaxResults = element.element(ELEMENT_SELECTORSSEARCHMAXRESULTS); + if (selectorsSearchMaxResults != null) + { + configElement.setSelectorsSearchMaxResults( + Integer.parseInt(selectorsSearchMaxResults.getTextTrim())); + } + // get the default permission for newly created users Home Spaces Element permission = element.element(ELEMENT_HOMESPACEPERMISSION); if (permission != null) diff --git a/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java b/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java index d9458bd107..26196fb2c0 100644 --- a/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java +++ b/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java @@ -37,8 +37,6 @@ import javax.faces.model.SelectItem; import org.alfresco.web.app.Application; import org.alfresco.web.ui.common.Utils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * @author kevinr @@ -58,8 +56,6 @@ public class DatePickerRenderer extends BaseRenderer private static final int CMD_SET = 1; private static final int CMD_RESET = 2; private static final int CMD_TODAY = 3; - - private static final Log logger = LogFactory.getLog(DatePickerRenderer.class); /** * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent) diff --git a/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java b/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java index 2aeec8d7a4..de99c00fab 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIContentSelector.java @@ -30,7 +30,9 @@ import javax.faces.el.ValueBinding; import org.alfresco.model.ContentModel; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -353,15 +355,30 @@ public class UIContentSelector extends UIInput query.append(":*" + safeContains + "*"); } + + int maxResults = Application.getClientConfig(context).getSelectorsSearchMaxResults(); if (logger.isDebugEnabled()) + { logger.debug("Query: " + query.toString()); + logger.debug("Max results size: " + maxResults); + } + + // setup search parameters, including limiting the results + SearchParameters searchParams = new SearchParameters(); + searchParams.addStore(Repository.getStoreRef()); + searchParams.setLanguage(SearchService.LANGUAGE_LUCENE); + searchParams.setQuery(query.toString()); + if (maxResults > 0) + { + searchParams.setLimit(maxResults); + searchParams.setLimitBy(LimitBy.FINAL_SIZE); + } ResultSet results = null; try { - results = Repository.getServiceRegistry(context).getSearchService().query( - Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString()); + results = Repository.getServiceRegistry(context).getSearchService().query(searchParams); this.availableOptions = results.getNodeRefs(); } finally diff --git a/source/java/org/alfresco/web/ui/repo/component/property/BaseAssociationEditor.java b/source/java/org/alfresco/web/ui/repo/component/property/BaseAssociationEditor.java index 3cf4ac6590..4596af1a5d 100644 --- a/source/java/org/alfresco/web/ui/repo/component/property/BaseAssociationEditor.java +++ b/source/java/org/alfresco/web/ui/repo/component/property/BaseAssociationEditor.java @@ -36,6 +36,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.service.cmr.dictionary.AssociationDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; @@ -914,8 +915,31 @@ public abstract class BaseAssociationEditor extends UIInput } } + int maxResults = Application.getClientConfig(context).getSelectorsSearchMaxResults(); + if (logger.isDebugEnabled()) + { logger.debug("Query: " + query.toString()); + logger.debug("Max results size: " + maxResults); + } + + SearchParameters searchParams = new SearchParameters(); + searchParams.addStore(Repository.getStoreRef()); + searchParams.setLanguage(SearchService.LANGUAGE_LUCENE); + searchParams.setQuery(query.toString()); + if (maxResults > 0) + { + searchParams.setLimit(maxResults); + searchParams.setLimitBy(LimitBy.FINAL_SIZE); + } + + if (type.equals(ContentModel.TYPE_PERSON.toString())) + { + searchParams.addSort("@" + ContentModel.PROP_LASTNAME, true); + + if (logger.isDebugEnabled()) + logger.debug("Added lastname as sort column to query for people"); + } SearchParameters searchParams = new SearchParameters(); searchParams.addStore(Repository.getStoreRef()); diff --git a/source/java/org/alfresco/web/ui/repo/component/property/UIProperty.java b/source/java/org/alfresco/web/ui/repo/component/property/UIProperty.java index d6b4b7c09c..b3677bbf73 100644 --- a/source/java/org/alfresco/web/ui/repo/component/property/UIProperty.java +++ b/source/java/org/alfresco/web/ui/repo/component/property/UIProperty.java @@ -176,10 +176,11 @@ public class UIProperty extends PropertySheetItem // if we're in edit mode ensure that we don't allow editing of system properties or scenarios we don't support if (propSheet.inEditMode()) { - // if we are trying to edit a NodeRef or Path property type set it to read-only as - // these are internal properties that shouldn't be edited. + // if we are trying to edit a system property type set it to read-only as these are internal + // properties that shouldn't be edited. if (typeName.equals(DataTypeDefinition.NODE_REF) || typeName.equals(DataTypeDefinition.PATH) || - typeName.equals(DataTypeDefinition.CONTENT)) + typeName.equals(DataTypeDefinition.CONTENT) || typeName.equals(DataTypeDefinition.QNAME) || + typeName.equals(DataTypeDefinition.CHILD_ASSOC_REF) || typeName.equals(DataTypeDefinition.ASSOC_REF)) { logger.warn("Setting property " + propDef.getName().toString() + " to read-only as it can not be edited"); control.getAttributes().put("disabled", Boolean.TRUE); diff --git a/source/java/org/alfresco/web/ui/repo/tag/JBPMProcessImageTag.java b/source/java/org/alfresco/web/ui/repo/tag/JBPMProcessImageTag.java new file mode 100644 index 0000000000..90faf788e8 --- /dev/null +++ b/source/java/org/alfresco/web/ui/repo/tag/JBPMProcessImageTag.java @@ -0,0 +1,254 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2005, JBoss Inc., and individual contributors as indicated + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.alfresco.web.ui.repo.tag; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.tagext.TagSupport; + +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.XPath; +import org.dom4j.xpath.DefaultXPath; +import org.jbpm.JbpmContext; +import org.jbpm.file.def.FileDefinition; +import org.jbpm.graph.def.ProcessDefinition; +import org.jbpm.graph.exe.Token; +import org.jbpm.taskmgmt.exe.TaskInstance; + + +// +// +// TODO: DC - Tidy up +// +// + + + + +public class JBPMProcessImageTag extends TagSupport { + + private static final long serialVersionUID = 1L; + private long taskInstanceId = -1; + private long tokenInstanceId = -1; + + private byte[] gpdBytes = null; + private byte[] imageBytes = null; + private Token currentToken = null; + private ProcessDefinition processDefinition = null; + + static String currentTokenColor = "red"; + static String childTokenColor = "blue"; + static String tokenNameColor = "blue"; + + + public void release() { + taskInstanceId = -1; + gpdBytes = null; + imageBytes = null; + currentToken = null; + } + + public int doEndTag() throws JspException { + try { + initialize(); + retrieveByteArrays(); + if (gpdBytes != null && imageBytes != null) { + writeTable(); + } + } catch (IOException e) { + e.printStackTrace(); + throw new JspException("table couldn't be displayed", e); + } catch (DocumentException e) { + e.printStackTrace(); + throw new JspException("table couldn't be displayed", e); + } + release(); + return EVAL_PAGE; + } + + private void retrieveByteArrays() { + try { + FileDefinition fileDefinition = processDefinition.getFileDefinition(); + gpdBytes = fileDefinition.getBytes("gpd.xml"); + imageBytes = fileDefinition.getBytes("processimage.jpg"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void writeTable() throws IOException, DocumentException { + + int borderWidth = 4; + Element rootDiagramElement = DocumentHelper.parseText(new String(gpdBytes)).getRootElement(); + int[] boxConstraint; + int[] imageDimension = extractImageDimension(rootDiagramElement); + String imageLink = "/alfresco/processimage?definitionId=" + processDefinition.getId(); + JspWriter jspOut = pageContext.getOut(); + + if (tokenInstanceId > 0) { + + List allTokens = new ArrayList(); + walkTokens(currentToken, allTokens); + + jspOut.println("

"); + + for (int i = 0; i < allTokens.size(); i++) + { + Token token = (Token) allTokens.get(i); + + //check how many tokens are on teh same level (= having the same parent) + int offset = i; + if(i > 0) { + while(offset > 0 && ((Token) allTokens.get(offset - 1)).getParent().equals(token.getParent())) { + offset--; + } + } + boxConstraint = extractBoxConstraint(rootDiagramElement, token); + + //Adjust for borders + //boxConstraint[2]-=borderWidth*2; + //boxConstraint[3]-=borderWidth*2; + + jspOut.println("
"); + + if(token.getName()!=null) + { + jspOut.println(" " + token.getName() +""); + } + + jspOut.println("
"); + } + jspOut.println("
"); + } + else + { + boxConstraint = extractBoxConstraint(rootDiagramElement); + + jspOut.println(""); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println("
"); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println(" "); + jspOut.println("
 
"); + jspOut.println("
"); + } + } + + private int[] extractBoxConstraint(Element root) { + int[] result = new int[4]; + String nodeName = currentToken.getNode().getName(); + XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']"); + Element node = (Element) xPath.selectSingleNode(root); + result[0] = Integer.valueOf(node.attribute("x").getValue()).intValue(); + result[1] = Integer.valueOf(node.attribute("y").getValue()).intValue(); + result[2] = Integer.valueOf(node.attribute("width").getValue()).intValue(); + result[3] = Integer.valueOf(node.attribute("height").getValue()).intValue(); + return result; + } + + private int[] extractBoxConstraint(Element root, Token token) { + int[] result = new int[4]; + String nodeName = token.getNode().getName(); + XPath xPath = new DefaultXPath("//node[@name='" + nodeName + "']"); + Element node = (Element) xPath.selectSingleNode(root); + result[0] = Integer.valueOf(node.attribute("x").getValue()).intValue(); + result[1] = Integer.valueOf(node.attribute("y").getValue()).intValue(); + result[2] = Integer.valueOf(node.attribute("width").getValue()).intValue(); + result[3] = Integer.valueOf(node.attribute("height").getValue()).intValue(); + return result; + } + + private int[] extractImageDimension(Element root) { + int[] result = new int[2]; + result[0] = Integer.valueOf(root.attribute("width").getValue()).intValue(); + result[1] = Integer.valueOf(root.attribute("height").getValue()).intValue(); + return result; + } + + private void initialize() { + JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext(); + if (this.taskInstanceId > 0) { + TaskInstance taskInstance = jbpmContext.getTaskMgmtSession().loadTaskInstance(taskInstanceId); + currentToken = taskInstance.getToken(); + } + else + { + if (this.tokenInstanceId > 0) + currentToken = jbpmContext.getGraphSession().loadToken(this.tokenInstanceId); + } + processDefinition = currentToken.getProcessInstance().getProcessDefinition(); + } + + private void walkTokens(Token parent, List allTokens) + { + Map children = parent.getChildren(); + if(children != null && children.size() > 0) + { + Collection childTokens = children.values(); + for (Iterator iterator = childTokens.iterator(); iterator.hasNext();) + { + Token child = (Token) iterator.next(); + walkTokens(child, allTokens); + } + } + + allTokens.add(parent); + } + + public void setTask(long id) { + this.taskInstanceId = id; + } + + public void setToken(long id) { + this.tokenInstanceId = id; + } + +} diff --git a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java index 633258fcff..d94d7a7eab 100644 --- a/source/java/org/alfresco/web/ui/repo/tag/PageTag.java +++ b/source/java/org/alfresco/web/ui/repo/tag/PageTag.java @@ -47,7 +47,7 @@ public class PageTag extends TagSupport */ private final static String ALF_URL = "http://www.alfresco.com"; - private final static String ALF_LOGO = "http://www.alfresco.com/images/alfresco_community_horizont.gif"; + private final static String ALF_LOGO = "http://www.alfresco.com/images/alfresco_community_horiz14.gif"; private final static String SF_LOGO = "/images/logo/sflogo.php.png"; private final static String ALF_TEXT = "Alfresco Community"; private final static String ALF_COPY = "Supplied free of charge with " + diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index ca01284f82..85c2f87319 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -1952,7 +1952,7 @@ WorkflowBean org.alfresco.web.bean.workflow.WorkflowBean - session + request nodeService #{NodeService} @@ -1962,6 +1962,18 @@ #{WorkflowService} + + + + Backing bean used for the Workflow Console + WorkflowConsoleBean + org.alfresco.web.bean.workflow.WorkflowConsoleBean + session + + workflowInterpreter + #{workflowInterpreter} + + @@ -2790,3 +2802,4 @@ session + diff --git a/source/web/WEB-INF/faces-config-navigation.xml b/source/web/WEB-INF/faces-config-navigation.xml index bff45ad3f5..d8d72340f1 100644 --- a/source/web/WEB-INF/faces-config-navigation.xml +++ b/source/web/WEB-INF/faces-config-navigation.xml @@ -1,3 +1,4 @@ +<<<<<<< .working @@ -943,3 +944,892 @@ +======= + + + + + + + + + + The decision rule used by the NavigationHandler to + determine which view must be displayed after the + current view, login.jsp is processed. + + /jsp/login.jsp + + + Indicates to the NavigationHandler that the browse.jsp + view must be displayed if the Action referenced by a + UICommand component on the login.jsp view returns + the outcome "success". + + success + /jsp/browse/browse.jsp + + + + + + /jsp/* + + browse + /jsp/browse/browse.jsp + + + myalfresco + /jsp/dashboards/container.jsp + + + about + /jsp/dialog/about.jsp + + + + + + /jsp/* + + showDocDetails + /jsp/dialog/document-details.jsp + + + showSpaceDetails + /jsp/dialog/space-details.jsp + + + dashboard + /jsp/browse/dashboard.jsp + + + addContent + /jsp/content/add-content-dialog.jsp + + + + + + /jsp/* + + advSearch + /jsp/dialog/advanced-search.jsp + + + + + + /jsp/* + + logout + /jsp/login.jsp + + + relogin + /jsp/relogin.jsp + + + + + + /jsp/* + + adminConsole + /jsp/admin/admin-console.jsp + + + userConsole + /jsp/users/user-console.jsp + + + + + + /jsp/* + + checkoutFile + /jsp/dialog/checkout-file.jsp + + + checkinFile + /jsp/dialog/checkin-file.jsp + + + undoCheckoutFile + /jsp/dialog/undocheckout-file.jsp + + + updateFile + /jsp/dialog/update-file.jsp + + + editFile + /jsp/dialog/edit-file.jsp + + + editHtmlInline + /jsp/dialog/edit-html-inline.jsp + + + editTextInline + /jsp/dialog/edit-text-inline.jsp + + + + + + /jsp/browse/browse.jsp + + + + manageInvitedUsers + /jsp/roles/manage-invited-users.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + manageRules + /jsp/dialog/rules.jsp + + + previewContent + /jsp/dialog/preview-file.jsp + + + previewSpace + /jsp/dialog/preview-space.jsp + + + startDiscussion + /jsp/forums/create-topic.jsp + + + showForum + /jsp/forums/forum.jsp + + + showTopic + /jsp/forums/topic.jsp + + + saveNewSearch + /jsp/dialog/save-search.jsp + + + saveEditSearch + /jsp/dialog/edit-search.jsp + + + manageDeletedItems + /jsp/trashcan/trash-list.jsp + + + + + /jsp/content/add-content-dialog.jsp + + cancel + /jsp/browse/browse.jsp + + + + + + /jsp/admin/admin-console.jsp + + manageCategories + /jsp/categories/categories.jsp + + + manageUsers + /jsp/users/users.jsp + + + manageGroups + /jsp/groups/groups.jsp + + + showSystemInfo + /jsp/dialog/system-info.jsp + + + showNodeBrowser + /jsp/admin/store-browser.jsp + + + import + /jsp/dialog/import.jsp + + + export + /jsp/dialog/export.jsp + + + + + /jsp/dialog/edit-file.jsp + + checkoutFile + /jsp/dialog/checkout-file.jsp + + + + + /jsp/dialog/edit-text-inline.jsp + + checkoutFile + /jsp/dialog/checkout-file.jsp + + + + + /jsp/dialog/edit-html-inline.jsp + + checkoutFile + /jsp/dialog/checkout-file.jsp + + + + + /jsp/dialog/checkout-file.jsp + + checkoutFileLink + /jsp/dialog/checkout-file-link.jsp + + + + + /jsp/dialog/space-details.jsp + + manageInvitedUsers + /jsp/roles/manage-invited-users.jsp + + + manageRules + /jsp/dialog/rules.jsp + + + import + /jsp/dialog/import.jsp + + + export + /jsp/dialog/export.jsp + + + applyTemplate + /jsp/dialog/apply-space-template.jsp + + + applyRSSTemplate + /jsp/dialog/apply-rss-template.jsp + + + previewSpace + /jsp/dialog/preview-space.jsp + + + showForum + /jsp/forums/forum.jsp + + + editCategories + /jsp/dialog/edit-space-category.jsp + + + editSimpleWorkflow + /jsp/dialog/edit-space-simple-workflow.jsp + + + + + /jsp/dialog/apply-rss-template.jsp + + manageInvitedUsers + /jsp/roles/manage-invited-users.jsp + + + + + /jsp/dialog/document-details.jsp + + editSimpleWorkflow + /jsp/dialog/edit-simple-workflow.jsp + + + editCategories + /jsp/dialog/edit-category.jsp + + + previewContent + /jsp/dialog/preview-file.jsp + + + showForum + /jsp/forums/forum.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + applyTemplate + /jsp/dialog/apply-doc-template.jsp + + + + + /jsp/dialog/edit-simple-workflow.jsp + + cancel + /jsp/dialog/document-details.jsp + + + finish + /jsp/dialog/document-details.jsp + + + + + /jsp/dialog/edit-space-simple-workflow.jsp + + cancel + /jsp/dialog/space-details.jsp + + + finish + /jsp/dialog/space-details.jsp + + + + + /jsp/dialog/edit-category.jsp + + cancel + /jsp/dialog/document-details.jsp + + + finish + /jsp/dialog/document-details.jsp + + + + + /jsp/dialog/edit-space-category.jsp + + cancel + /jsp/dialog/space-details.jsp + + + finish + /jsp/dialog/space-details.jsp + + + + + /jsp/dialog/rules.jsp + + deleteRule + /jsp/dialog/delete-rule.jsp + + + + + /jsp/dialog/delete-rule.jsp + + manageRules + /jsp/dialog/rules.jsp + + + cancel + /jsp/dialog/rules.jsp + + + browse + /jsp/dialog/rules.jsp + + + + + + /jsp/dialog/filelink-details.jsp + + editLinkProperties + /jsp/dialog/edit-link-properties.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + + + + /jsp/dialog/spacelink-details.jsp + + editLinkProperties + /jsp/dialog/edit-link-properties.jsp + + + manageContentUsers + /jsp/roles/manage-content-users.jsp + + + + + + /jsp/dialog/edit-link-properties.jsp + + cancelEdit + /jsp/dialog/filelink-details.jsp + + + finishEdit + /jsp/dialog/filelink-details.jsp + + + + + + /jsp/roles/manage-invited-users.jsp + + inviteUsers + /jsp/wizard/invite-users/invite.jsp + + + editRoles + /jsp/roles/edit-user-roles.jsp + + + removeUser + /jsp/roles/remove-invited-user.jsp + + + + + /jsp/roles/edit-user-roles.jsp + + cancel + /jsp/roles/manage-invited-users.jsp + + + finish + /jsp/roles/manage-invited-users.jsp + + + + + /jsp/roles/remove-invited-user.jsp + + cancel + /jsp/roles/manage-invited-users.jsp + + + finish + /jsp/roles/manage-invited-users.jsp + + + + + /jsp/roles/manage-content-users.jsp + + inviteUsers + /jsp/wizard/invite-content-users/invite.jsp + + + editRoles + /jsp/roles/edit-content-user-roles.jsp + + + removeUser + /jsp/roles/remove-content-user.jsp + + + + + /jsp/roles/edit-content-user-roles.jsp + + cancel + /jsp/roles/manage-content-users.jsp + + + finish + /jsp/roles/manage-content-users.jsp + + + + + /jsp/roles/remove-content-user.jsp + + cancel + /jsp/roles/manage-content-users.jsp + + + finish + /jsp/roles/manage-content-users.jsp + + + + + + /jsp/wizard/invite-users/* + + invite + /jsp/wizard/invite-users/invite.jsp + + + notify + /jsp/wizard/invite-users/notify.jsp + + + cancel + /jsp/roles/manage-invited-users.jsp + + + finish + /jsp/roles/manage-invited-users.jsp + + + + + + /jsp/wizard/invite-content-users/* + + invite + /jsp/wizard/invite-content-users/invite.jsp + + + notify + /jsp/wizard/invite-content-users/notify.jsp + + + cancel + /jsp/roles/manage-content-users.jsp + + + finish + /jsp/roles/manage-content-users.jsp + + + + + + /jsp/users/* + + manageUsers + /jsp/users/users.jsp + + + cancel + /jsp/users/users.jsp + + + + + /jsp/users/users.jsp + + createUser + /jsp/wizard/new-user/person-properties.jsp + + + editUser + /jsp/wizard/new-user/person-properties.jsp + + + deleteUser + /jsp/users/delete-user.jsp + + + changePassword + /jsp/users/change-password.jsp + + + + + + /jsp/users/user-console.jsp + + changePassword + /jsp/users/change-my-password.jsp + + + editUserDetails + /jsp/users/edit-user-details.jsp + + + + + + /jsp/wizard/new-user/* + + cancel + /jsp/users/users.jsp + + + finish + /jsp/users/users.jsp + + + person-properties + /jsp/wizard/new-user/person-properties.jsp + + + user-properties + /jsp/wizard/new-user/user-properties.jsp + + + summary + /jsp/wizard/new-user/summary.jsp + + + + + + /jsp/groups/* + + newGroup + /jsp/groups/new-group.jsp + + + deleteGroup + /jsp/groups/delete-group.jsp + + + addUser + /jsp/groups/add-user.jsp + + + deleteUser + /jsp/groups/delete-user.jsp + + + finish + /jsp/groups/groups.jsp + + + cancel + /jsp/groups/groups.jsp + + + + + + /jsp/categories/* + + addCategory + /jsp/categories/new-category.jsp + + + editCategory + /jsp/categories/edit-category.jsp + + + deleteCategory + /jsp/categories/delete-category.jsp + + + finish + /jsp/categories/categories.jsp + + + cancel + /jsp/categories/categories.jsp + + + + + + /jsp/wizard/* + + cancel + /jsp/browse/browse.jsp + + + finish + /jsp/browse/browse.jsp + + + + + + /jsp/admin/* + + #{AdminNodeBrowseBean.selectStores} + success + /jsp/admin/store-browser.jsp + + + nodeBrowser + /jsp/admin/node-browser.jsp + + + + + /jsp/admin/store-browser.jsp + + #{AdminNodeBrowseBean.selectStore} + success + /jsp/admin/node-browser.jsp + + + + + /jsp/admin/node-browser.jsp + + #{AdminNodeBrowseBean.selectChild} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.selectPrimaryPath} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.selectPrimaryParent} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.selectParent} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.selectToNode} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.selectNodeProperty} + success + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.submitSearch} + error + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.submitSearch} + node + /jsp/admin/node-browser.jsp + + + #{AdminNodeBrowseBean.submitSearch} + search + /jsp/admin/search-results.jsp + + + + + /jsp/admin/search-results.jsp + + #{AdminNodeBrowseBean.selectResultNode} + success + /jsp/admin/node-browser.jsp + + + + + + /jsp/workflow/workflow-console.jsp + + #{WorkflowConsoleBean.submitCommand} + success + /jsp/workflow/workflow-console.jsp + + + + + + /jsp/forums/* + + + + showForumsDetails + /jsp/forums/forums-details.jsp + + + showForumDetails + /jsp/forums/forum-details.jsp + + + showTopicDetails + /jsp/forums/topic-details.jsp + + + manageInvitedUsers + /jsp/roles/manage-invited-users.jsp + + + import + /jsp/dialog/import.jsp + + + export + /jsp/dialog/export.jsp + + + + + + /jsp/trashcan/* + + deleteItem + /jsp/trashcan/delete-item.jsp + + + recoverItem + /jsp/trashcan/recover-item.jsp + + + recoverAllItems + /jsp/trashcan/recover-all.jsp + + + deleteAllItems + /jsp/trashcan/delete-all.jsp + + + recoverListedItems + /jsp/trashcan/recover-listed.jsp + + + deleteListedItems + /jsp/trashcan/delete-listed.jsp + + + itemDetails + /jsp/trashcan/item-details.jsp + + + recoveryReport + /jsp/trashcan/recovery-report.jsp + + + + + /jsp/dialog/container.jsp + + + + forumsDeleted + /jsp/forums/forums.jsp + + + forumDeleted + /jsp/forums/forums.jsp + + + topicDeleted + /jsp/forums/forum.jsp + + + + +>>>>>>> .merge-right.r4305 diff --git a/source/web/WEB-INF/faces-config-repo.xml b/source/web/WEB-INF/faces-config-repo.xml index a798a656ee..d8f8d9c2f7 100644 --- a/source/web/WEB-INF/faces-config-repo.xml +++ b/source/web/WEB-INF/faces-config-repo.xml @@ -1,3 +1,4 @@ +<<<<<<< .working @@ -228,3 +229,235 @@ +======= + + + + + + + org.alfresco.faces.PropertySheet + org.alfresco.web.ui.repo.component.property.UIPropertySheet + + + + org.alfresco.faces.Property + org.alfresco.web.ui.repo.component.property.UIProperty + + + + org.alfresco.faces.Separator + org.alfresco.web.ui.repo.component.property.UISeparator + + + + org.alfresco.faces.Association + org.alfresco.web.ui.repo.component.property.UIAssociation + + + + org.alfresco.faces.AssociationEditor + org.alfresco.web.ui.repo.component.property.UIAssociationEditor + + + + org.alfresco.faces.ChildAssociation + org.alfresco.web.ui.repo.component.property.UIChildAssociation + + + + org.alfresco.faces.ChildAssociationEditor + org.alfresco.web.ui.repo.component.property.UIChildAssociationEditor + + + + org.alfresco.faces.NodeDescendants + org.alfresco.web.ui.repo.component.UINodeDescendants + + + + org.alfresco.faces.NodePath + org.alfresco.web.ui.repo.component.UINodePath + + + + org.alfresco.faces.SpaceSelector + org.alfresco.web.ui.repo.component.UISpaceSelector + + + + org.alfresco.faces.ContentSelector + org.alfresco.web.ui.repo.component.UIContentSelector + + + + org.alfresco.faces.CategorySelector + org.alfresco.web.ui.repo.component.UICategorySelector + + + + org.alfresco.faces.MimeTypeSelector + org.alfresco.web.ui.repo.component.UIMimeTypeSelector + + + + org.alfresco.faces.SimpleSearch + org.alfresco.web.ui.repo.component.UISimpleSearch + + + + org.alfresco.faces.AdvancedSearch + org.alfresco.web.ui.repo.component.UISearchCustomProperties + + + + org.alfresco.faces.Shelf + org.alfresco.web.ui.repo.component.shelf.UIShelf + + + + org.alfresco.faces.ShelfGroup + org.alfresco.web.ui.repo.component.shelf.UIShelfGroup + + + + org.alfresco.faces.ShelfItem + org.alfresco.web.ui.repo.component.shelf.UIShelfItem + + + + org.alfresco.faces.ClipboardShelfItem + org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem + + + + org.alfresco.faces.RecentSpacesShelfItem + org.alfresco.web.ui.repo.component.shelf.UIRecentSpacesShelfItem + + + + org.alfresco.faces.ShortcutsShelfItem + org.alfresco.web.ui.repo.component.shelf.UIShortcutsShelfItem + + + + org.alfresco.faces.LockIcon + org.alfresco.web.ui.repo.component.UILockIcon + + + + org.alfresco.faces.Template + org.alfresco.web.ui.repo.component.template.UITemplate + + + + org.alfresco.faces.MultiValueEditor + org.alfresco.web.ui.repo.component.UIMultiValueEditor + + + + org.alfresco.faces.Actions + org.alfresco.web.ui.repo.component.UIActions + + + + org.alfresco.faces.ActionInstanceEvaluator + org.alfresco.web.ui.repo.component.evaluator.ActionInstanceEvaluator + + + + org.alfresco.faces.NodeInfo + org.alfresco.web.ui.repo.component.UINodeInfo + + + + org.alfresco.faces.DialogButtons + org.alfresco.web.ui.repo.component.UIDialogButtons + + + + org.alfresco.faces.UserGroupPicker + org.alfresco.web.ui.repo.component.UIUserGroupPicker + + + + org.alfresco.faces.WorkflowSummary + org.alfresco.web.ui.repo.component.UIWorkflowSummary + + + + org.alfresco.faces.NodeWorkflowInfo + org.alfresco.web.ui.repo.component.UINodeWorkflowInfo + + + + + org.alfresco.faces.PermissionEvaluator + org.alfresco.web.ui.repo.component.evaluator.PermissionEvaluator + + + + org.alfresco.faces.MimeTypeConverter + org.alfresco.web.ui.repo.converter.MimeTypeConverter + + + + org.alfresco.faces.DisplayPathConverter + org.alfresco.web.ui.repo.converter.DisplayPathConverter + + + + + + + org.alfresco.faces.NodeDescendants + org.alfresco.faces.NodeDescendantsLinkRenderer + org.alfresco.web.ui.repo.renderer.NodeDescendantsLinkRenderer + + + + org.alfresco.faces.NodePath + org.alfresco.faces.NodePathLinkRenderer + org.alfresco.web.ui.repo.renderer.NodePathLinkRenderer + + + + org.alfresco.faces.Property + org.alfresco.faces.PropertyRenderer + org.alfresco.web.ui.repo.renderer.property.PropertyRenderer + + + + org.alfresco.faces.Separator + org.alfresco.faces.SeparatorRenderer + org.alfresco.web.ui.repo.renderer.property.SeparatorRenderer + + + + org.alfresco.faces.Association + org.alfresco.faces.AssociationRenderer + org.alfresco.web.ui.repo.renderer.property.AssociationRenderer + + + + org.alfresco.faces.ChildAssociation + org.alfresco.faces.ChildAssociationRenderer + org.alfresco.web.ui.repo.renderer.property.ChildAssociationRenderer + + + + org.alfresco.faces.MultiValueEditor + org.alfresco.faces.Selector + org.alfresco.web.ui.repo.renderer.MultiValueSelectorRenderer + + + + org.alfresco.faces.MultiValueEditor + org.alfresco.faces.Field + org.alfresco.web.ui.repo.renderer.MultiValueFieldRenderer + + + + +>>>>>>> .merge-right.r4305 diff --git a/source/web/WEB-INF/repo.tld b/source/web/WEB-INF/repo.tld index 5455de2c2f..101e1f9a36 100644 --- a/source/web/WEB-INF/repo.tld +++ b/source/web/WEB-INF/repo.tld @@ -1,1758 +1,1758 @@ - - - - - - 1.0 - 1.2 - r - Alfresco Repository JSF Components - Tag library consisting of Alfresco repository JSF components i.e. those that can only be used in Alfresco based projects - - - propertySheetGrid - org.alfresco.web.ui.repo.tag.property.PropertySheetGridTag - JSP - Property Sheet - Displays the current properties for a node in the repository - - - id - false - true - The component identifier for this component - - - - value - true - true - A NodeRef object representing the node to show the properties of - - - - binding - false - true - The value binding expression linking this component to a property in a backing bean - - - - rendered - false - true - - - - readOnly - false - true - - - - validationEnabled - false - true - - - - finishButtonId - false - true - - - - nextButtonId - false - true - - - - var - false - true - - - - columns - false - true - - - - mode - false - true - Whether the property sheet is in read-only mode or edit mode, values can be "view" or "edit" - - - - labelStyleClass - false - true - - - - cellpadding - false - true - - - - cellspacing - false - true - - - - externalConfig - false - true - - - - configArea - false - true - - - - - property - org.alfresco.web.ui.repo.tag.property.PropertyTag - JSP - - - id - false - true - - - - name - true - true - - - - rendered - false - true - - - - displayLabel - false - true - - - - readOnly - false - true - - - - mode - false - true - - - - converter - false - true - - - - - association - org.alfresco.web.ui.repo.tag.property.AssociationTag - JSP - - - id - false - true - - - - name - true - true - - - - rendered - false - true - - - - displayLabel - false - true - - - - readOnly - false - true - - - - mode - false - true - - - - converter - false - true - - - - - associationEditor - org.alfresco.web.ui.repo.tag.property.AssociationEditorTag - JSP - - - value - true - true - - - - associationName - true - true - - - - availableOptionsSize - false - true - - - - selectItemMsg - false - true - - - - selectItemsMsg - false - true - - - - selectedItemsMsg - false - true - - - - noSelectedItemsMsg - false - true - - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - childAssociation - org.alfresco.web.ui.repo.tag.property.ChildAssociationTag - JSP - - - id - false - true - - - - name - true - true - - - - rendered - false - true - - - - displayLabel - false - true - - - - readOnly - false - true - - - - mode - false - true - - - - converter - false - true - - - - - childAssociationEditor - org.alfresco.web.ui.repo.tag.property.ChildAssociationEditorTag - JSP - - - value - true - true - - - - associationName - true - true - - - - availableOptionsSize - false - true - - - - selectItemMsg - false - true - - - - selectItemsMsg - false - true - - - - selectedItemsMsg - false - true - - - - noSelectedItemsMsg - false - true - - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - nodeDescendants - org.alfresco.web.ui.repo.tag.NodeDescendantsTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - maxChildren - false - true - - - - separator - false - true - - - - showEllipses - false - true - - - - action - false - true - - - - actionListener - false - true - - - - value - true - true - - - - - nodePath - org.alfresco.web.ui.repo.tag.NodePathTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - disabled - false - true - - - - showLeaf - false - true - - - - action - false - true - - - - actionListener - false - true - - - - breadcrumb - false - true - - - - value - true - true - - - - - simpleSearch - org.alfresco.web.ui.repo.tag.SimpleSearchTag - JSP - - - Displays controls and icons as the simple search controls needed for the repo client UI. - - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - action - false - true - - - - actionListener - false - true - - - - - systemError - org.alfresco.web.ui.repo.tag.SystemErrorTag - JSP - - - styleClass - false - true - - - - detailsStyleClass - false - true - - - - showDetails - false - true - - - - - page - org.alfresco.web.ui.repo.tag.PageTag - JSP - - - title - false - true - - - - titleId - false - true - - - - - uploadForm - org.alfresco.web.ui.repo.tag.UploadFormTag - JSP - - - - spaceSelector - org.alfresco.web.ui.repo.tag.SpaceSelectorTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - nodeStyle - false - true - - - - nodeStyleClass - false - true - - - - value - false - true - - - - label - true - true - - - - spacing - false - true - - - - initialSelection - false - true - - - - disabled - false - true - - - - - contentSelector - org.alfresco.web.ui.repo.tag.ContentSelectorTag - JSP - - - value - true - true - - - - availableOptionsSize - false - true - - - - multiSelect - false - true - - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - categorySelector - org.alfresco.web.ui.repo.tag.CategorySelectorTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - nodeStyle - false - true - - - - nodeStyleClass - false - true - - - - value - false - true - - - - label - true - true - - - - spacing - false - true - - - - initialSelection - false - true - - - - disabled - false - true - - - - - mimeTypeSelector - org.alfresco.web.ui.repo.tag.MimeTypeSelectorTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - value - false - true - - - - disabled - false - true - - - - - shelf - org.alfresco.web.ui.repo.tag.shelf.ShelfTag - JSP - - - id - true - true - - - - binding - false - true - - - - rendered - false - true - - - - groupPanel - false - true - - - - groupBgcolor - false - true - - - - selectedGroupPanel - false - true - - - - selectedGroupBgcolor - false - true - - - - innerGroupPanel - false - true - - - - innerGroupBgcolor - false - true - - - - groupExpandedActionListener - false - true - - - - - shelfGroup - org.alfresco.web.ui.repo.tag.shelf.ShelfGroupTag - JSP - - - id - true - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - label - true - true - - - - expanded - false - true - - - - - shelfItem - org.alfresco.web.ui.repo.tag.shelf.ShelfItemTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - tooltip - false - true - - - - - clipboardShelfItem - org.alfresco.web.ui.repo.tag.shelf.ClipboardShelfItemTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - collections - true - true - - - - pasteActionListener - true - true - - - - - recentSpacesShelfItem - org.alfresco.web.ui.repo.tag.shelf.RecentSpacesShelfItemTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - value - true - true - - - - navigateActionListener - true - true - - - - - shortcutsShelfItem - org.alfresco.web.ui.repo.tag.shelf.ShortcutsShelfItemTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - value - true - true - - - - clickActionListener - true - true - - - - removeActionListener - true - true - - - - - lockIcon - org.alfresco.web.ui.repo.tag.LockIconTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - lockImage - false - true - - - - lockOwnerImage - false - true - - - - align - false - true - - - - width - false - true - - - - height - false - true - - - - lockedOwnerTooltip - false - true - - - - lockedUserTooltip - false - true - - - - value - true - true - - - - - template - org.alfresco.web.ui.repo.tag.TemplateTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - engine - false - true - - - - template - true - true - - - - model - false - true - - - - - permissionEvaluator - org.alfresco.web.ui.repo.tag.evaluator.PermissionEvaluatorTag - JSP - - - id - false - true - - - - value - true - true - - - - binding - false - true - - - - allow - false - true - - - - deny - false - true - - - - - multiValueSelector - org.alfresco.web.ui.repo.tag.MultiValueSelectorTag - JSP - - - value - true - true - - - - lastItemAdded - true - true - - - - id - false - true - - - - rendered - false - true - - - - readOnly - false - true - - - - selectItemMsg - false - true - - - - selectedItemsMsg - false - true - - - - noSelectedItemsMsg - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - multiValueField - org.alfresco.web.ui.repo.tag.MultiValueFieldTag - JSP - - - value - true - true - - - - lastItemAdded - true - true - - - - id - false - true - - - - rendered - false - true - - - - readOnly - false - true - - - - selectItemMsg - false - true - - - - selectedItemsMsg - false - true - - - - noSelectedItemsMsg - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - searchCustomProperties - org.alfresco.web.ui.repo.tag.SearchCustomPropertiesTag - JSP - - - id - false - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - bean - true - true - - - - var - true - true - - - - - actions - org.alfresco.web.ui.repo.tag.ActionsTag - JSP - - - The actions component renders a group of actionLink components as defined by an Action Group - in the web-client-config-actions.xml config file. Each action groups can contain many actions - which are individually rendered as ActionLink components. The action group uses a Node object - as the context for the various actions defined in config. - - - - id - false - true - - - - value - true - true - - - - context - true - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - verticalSpacing - false - true - - - - showLink - false - true - - - - - nodeInfo - org.alfresco.web.ui.repo.tag.NodeInfoTag - JSP - - - The nodeInfo component wraps another component, typically an - action link, to provide a floating pop up panel containing - information on a particular node. - - - - id - false - true - - - - value - true - true - - - - - nodeWorkflowInfo - org.alfresco.web.ui.repo.tag.NodeWorkflowInfoTag - JSP - - - The nodeWorkflowInfo component displays information about the workflows - a node is currently involved in. - - - - id - false - true - - - - value - true - true - - - - - dialogButtons - org.alfresco.web.ui.repo.tag.DialogButtonsTag - JSP - - - The dialogButtons component displays the buttons for a dialog. - - - - id - false - true - - - - styleClass - false - true - - - - - userGroupPicker - org.alfresco.web.ui.repo.tag.UserGroupPickerTag - JSP - - - The userGroupPicker component renders a multi-select hierarchical list of groups - and users. The groups and be expanded to show the child users and groups for individual - selection and deselection. - - - - id - false - true - - - - value - true - true - - - - binding - false - true - - - - rendered - false - true - - - - actionListener - false - true - - - - style - false - true - - - - styleClass - false - true - - - - - workflowSummary - org.alfresco.web.ui.repo.tag.WorkflowSummaryTag - JSP - - - Shows summary information of a workflow instance. - - - - id - false - true - - - - value - true - true - - - - binding - false - true - - - - rendered - false - true - - - - style - false - true - - - - styleClass - false - true - - - - + + + + + + 1.0 + 1.2 + r + Alfresco Repository JSF Components + Tag library consisting of Alfresco repository JSF components i.e. those that can only be used in Alfresco based projects + + + propertySheetGrid + org.alfresco.web.ui.repo.tag.property.PropertySheetGridTag + JSP + Property Sheet + Displays the current properties for a node in the repository + + + id + false + true + The component identifier for this component + + + + value + true + true + A NodeRef object representing the node to show the properties of + + + + binding + false + true + The value binding expression linking this component to a property in a backing bean + + + + rendered + false + true + + + + readOnly + false + true + + + + validationEnabled + false + true + + + + finishButtonId + false + true + + + + nextButtonId + false + true + + + + var + false + true + + + + columns + false + true + + + + mode + false + true + Whether the property sheet is in read-only mode or edit mode, values can be "view" or "edit" + + + + labelStyleClass + false + true + + + + cellpadding + false + true + + + + cellspacing + false + true + + + + externalConfig + false + true + + + + configArea + false + true + + + + + property + org.alfresco.web.ui.repo.tag.property.PropertyTag + JSP + + + id + false + true + + + + name + true + true + + + + rendered + false + true + + + + displayLabel + false + true + + + + readOnly + false + true + + + + mode + false + true + + + + converter + false + true + + + + + association + org.alfresco.web.ui.repo.tag.property.AssociationTag + JSP + + + id + false + true + + + + name + true + true + + + + rendered + false + true + + + + displayLabel + false + true + + + + readOnly + false + true + + + + mode + false + true + + + + converter + false + true + + + + + associationEditor + org.alfresco.web.ui.repo.tag.property.AssociationEditorTag + JSP + + + value + true + true + + + + associationName + true + true + + + + availableOptionsSize + false + true + + + + selectItemMsg + false + true + + + + selectItemsMsg + false + true + + + + selectedItemsMsg + false + true + + + + noSelectedItemsMsg + false + true + + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + childAssociation + org.alfresco.web.ui.repo.tag.property.ChildAssociationTag + JSP + + + id + false + true + + + + name + true + true + + + + rendered + false + true + + + + displayLabel + false + true + + + + readOnly + false + true + + + + mode + false + true + + + + converter + false + true + + + + + childAssociationEditor + org.alfresco.web.ui.repo.tag.property.ChildAssociationEditorTag + JSP + + + value + true + true + + + + associationName + true + true + + + + availableOptionsSize + false + true + + + + selectItemMsg + false + true + + + + selectItemsMsg + false + true + + + + selectedItemsMsg + false + true + + + + noSelectedItemsMsg + false + true + + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + nodeDescendants + org.alfresco.web.ui.repo.tag.NodeDescendantsTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + maxChildren + false + true + + + + separator + false + true + + + + showEllipses + false + true + + + + action + false + true + + + + actionListener + false + true + + + + value + true + true + + + + + nodePath + org.alfresco.web.ui.repo.tag.NodePathTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + disabled + false + true + + + + showLeaf + false + true + + + + action + false + true + + + + actionListener + false + true + + + + breadcrumb + false + true + + + + value + true + true + + + + + simpleSearch + org.alfresco.web.ui.repo.tag.SimpleSearchTag + JSP + + + Displays controls and icons as the simple search controls needed for the repo client UI. + + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + action + false + true + + + + actionListener + false + true + + + + + systemError + org.alfresco.web.ui.repo.tag.SystemErrorTag + JSP + + + styleClass + false + true + + + + detailsStyleClass + false + true + + + + showDetails + false + true + + + + + page + org.alfresco.web.ui.repo.tag.PageTag + JSP + + + title + false + true + + + + titleId + false + true + + + + + uploadForm + org.alfresco.web.ui.repo.tag.UploadFormTag + JSP + + + + spaceSelector + org.alfresco.web.ui.repo.tag.SpaceSelectorTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + nodeStyle + false + true + + + + nodeStyleClass + false + true + + + + value + false + true + + + + label + true + true + + + + spacing + false + true + + + + initialSelection + false + true + + + + disabled + false + true + + + + + contentSelector + org.alfresco.web.ui.repo.tag.ContentSelectorTag + JSP + + + value + true + true + + + + availableOptionsSize + false + true + + + + multiSelect + false + true + + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + categorySelector + org.alfresco.web.ui.repo.tag.CategorySelectorTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + nodeStyle + false + true + + + + nodeStyleClass + false + true + + + + value + false + true + + + + label + true + true + + + + spacing + false + true + + + + initialSelection + false + true + + + + disabled + false + true + + + + + mimeTypeSelector + org.alfresco.web.ui.repo.tag.MimeTypeSelectorTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + value + false + true + + + + disabled + false + true + + + + + shelf + org.alfresco.web.ui.repo.tag.shelf.ShelfTag + JSP + + + id + true + true + + + + binding + false + true + + + + rendered + false + true + + + + groupPanel + false + true + + + + groupBgcolor + false + true + + + + selectedGroupPanel + false + true + + + + selectedGroupBgcolor + false + true + + + + innerGroupPanel + false + true + + + + innerGroupBgcolor + false + true + + + + groupExpandedActionListener + false + true + + + + + shelfGroup + org.alfresco.web.ui.repo.tag.shelf.ShelfGroupTag + JSP + + + id + true + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + label + true + true + + + + expanded + false + true + + + + + shelfItem + org.alfresco.web.ui.repo.tag.shelf.ShelfItemTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + tooltip + false + true + + + + + clipboardShelfItem + org.alfresco.web.ui.repo.tag.shelf.ClipboardShelfItemTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + collections + true + true + + + + pasteActionListener + true + true + + + + + recentSpacesShelfItem + org.alfresco.web.ui.repo.tag.shelf.RecentSpacesShelfItemTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + value + true + true + + + + navigateActionListener + true + true + + + + + shortcutsShelfItem + org.alfresco.web.ui.repo.tag.shelf.ShortcutsShelfItemTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + value + true + true + + + + clickActionListener + true + true + + + + removeActionListener + true + true + + + + + lockIcon + org.alfresco.web.ui.repo.tag.LockIconTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + lockImage + false + true + + + + lockOwnerImage + false + true + + + + align + false + true + + + + width + false + true + + + + height + false + true + + + + lockedOwnerTooltip + false + true + + + + lockedUserTooltip + false + true + + + + value + true + true + + + + + template + org.alfresco.web.ui.repo.tag.TemplateTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + engine + false + true + + + + template + true + true + + + + model + false + true + + + + + permissionEvaluator + org.alfresco.web.ui.repo.tag.evaluator.PermissionEvaluatorTag + JSP + + + id + false + true + + + + value + true + true + + + + binding + false + true + + + + allow + false + true + + + + deny + false + true + + + + + multiValueSelector + org.alfresco.web.ui.repo.tag.MultiValueSelectorTag + JSP + + + value + true + true + + + + lastItemAdded + true + true + + + + id + false + true + + + + rendered + false + true + + + + readOnly + false + true + + + + selectItemMsg + false + true + + + + selectedItemsMsg + false + true + + + + noSelectedItemsMsg + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + multiValueField + org.alfresco.web.ui.repo.tag.MultiValueFieldTag + JSP + + + value + true + true + + + + lastItemAdded + true + true + + + + id + false + true + + + + rendered + false + true + + + + readOnly + false + true + + + + selectItemMsg + false + true + + + + selectedItemsMsg + false + true + + + + noSelectedItemsMsg + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + searchCustomProperties + org.alfresco.web.ui.repo.tag.SearchCustomPropertiesTag + JSP + + + id + false + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + bean + true + true + + + + var + true + true + + + + + actions + org.alfresco.web.ui.repo.tag.ActionsTag + JSP + + + The actions component renders a group of actionLink components as defined by an Action Group + in the web-client-config-actions.xml config file. Each action groups can contain many actions + which are individually rendered as ActionLink components. The action group uses a Node object + as the context for the various actions defined in config. + + + + id + false + true + + + + value + true + true + + + + context + true + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + verticalSpacing + false + true + + + + showLink + false + true + + + + + nodeInfo + org.alfresco.web.ui.repo.tag.NodeInfoTag + JSP + + + The nodeInfo component wraps another component, typically an + action link, to provide a floating pop up panel containing + information on a particular node. + + + + id + false + true + + + + value + true + true + + + + + nodeWorkflowInfo + org.alfresco.web.ui.repo.tag.NodeWorkflowInfoTag + JSP + + + The nodeWorkflowInfo component displays information about the workflows + a node is currently involved in. + + + + id + false + true + + + + value + true + true + + + + + dialogButtons + org.alfresco.web.ui.repo.tag.DialogButtonsTag + JSP + + + The dialogButtons component displays the buttons for a dialog. + + + + id + false + true + + + + styleClass + false + true + + + + + userGroupPicker + org.alfresco.web.ui.repo.tag.UserGroupPickerTag + JSP + + + The userGroupPicker component renders a multi-select hierarchical list of groups + and users. The groups and be expanded to show the child users and groups for individual + selection and deselection. + + + + id + false + true + + + + value + true + true + + + + binding + false + true + + + + rendered + false + true + + + + actionListener + false + true + + + + style + false + true + + + + styleClass + false + true + + + + + workflowSummary + org.alfresco.web.ui.repo.tag.WorkflowSummaryTag + JSP + + + Shows summary information of a workflow instance. + + + + id + false + true + + + + value + true + true + + + + binding + false + true + + + + rendered + false + true + + + + style + false + true + + + + styleClass + false + true + + + + diff --git a/source/web/WEB-INF/web.xml b/source/web/WEB-INF/web.xml index 17f6ca3b75..7d857b89c4 100644 --- a/source/web/WEB-INF/web.xml +++ b/source/web/WEB-INF/web.xml @@ -201,6 +201,11 @@ org.alfresco.web.app.servlet.GuestDownloadContentServlet + + guestTemplateContent + org.alfresco.web.app.servlet.GuestTemplateContentServlet + + externalAccess org.alfresco.web.app.servlet.ExternalAccessServlet @@ -266,6 +271,11 @@ /guestDownload/* + + guestTemplateContent + /guestTemplate/* + + externalAccess /navigate/* diff --git a/source/web/css/main.css b/source/web/css/main.css index ca47a41ab1..07afece7a9 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -559,25 +559,3 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl { padding-bottom: 8px; } - -.selectListTable -{ - border: 1px solid #999999; - padding-top: 2px; - padding-left: 2px; - padding-right: 2px; -} - -.selectListItem -{ - background-color: #eeeeee; - border-bottom: 2px solid #ffffff; -} - -.modifiedItemsList -{ - background-color: #EEEEEE; - border-width: 1px; - border-style: dashed; - border-color: #AAAAAA; -} diff --git a/source/web/index.jsp b/source/web/index.jsp index 699051315b..a9b2e386ec 100644 --- a/source/web/index.jsp +++ b/source/web/index.jsp @@ -16,6 +16,7 @@ License. --%> <%@ page import="org.springframework.web.context.support.WebApplicationContextUtils" %> +<%@ page import="org.alfresco.service.cmr.security.PermissionService" %> <%@ page import="org.alfresco.config.ConfigService" %> <%@ page import="org.alfresco.web.app.servlet.AuthenticationHelper" %> <%@ page import="org.alfresco.web.bean.NavigationBean" %> @@ -32,7 +33,7 @@ String location = configElement.getInitialLocation(); // override with the users preference if they have one User user = (User)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER); -if (user != null) +if (user != null && (user.getUserName().equals(PermissionService.GUEST_AUTHORITY) == false)) { String preference = (String)PreferencesService.getPreferences(user).getValue("start-location"); if (preference != null) diff --git a/source/web/jsp/admin/admin-console.jsp b/source/web/jsp/admin/admin-console.jsp index ae88d603fc..1afb36f029 100644 --- a/source/web/jsp/admin/admin-console.jsp +++ b/source/web/jsp/admin/admin-console.jsp @@ -126,12 +126,6 @@ - - - - - - <% PanelGenerator.generatePanelEnd(out, request.getContextPath(), "ballongrey"); %> diff --git a/source/web/jsp/admin/workflow-console.jsp b/source/web/jsp/admin/workflow-console.jsp new file mode 100644 index 0000000000..37b4e9e181 --- /dev/null +++ b/source/web/jsp/admin/workflow-console.jsp @@ -0,0 +1,102 @@ +<%-- + Copyright (C) 2005 Alfresco, Inc. + + Licensed under the Mozilla Public License version 1.1 + with a permitted attribution clause. You may obtain a + copy of the License at + + http://www.alfresco.org/legal/license.txt + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + either express or implied. See the License for the specific + language governing permissions and limitations under the + License. +--%> +<%@ 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:
Workflow Definition:
+ +
+ + + + + + + + + +
+ + + +
+
+ + + + + + + + +
+
+
+ ----- +
+
+
+ +
+ +
+ + diff --git a/source/web/jsp/roles/manage-content-users.jsp b/source/web/jsp/roles/manage-content-users.jsp index 4d59c638bc..701d910702 100644 --- a/source/web/jsp/roles/manage-content-users.jsp +++ b/source/web/jsp/roles/manage-content-users.jsp @@ -85,13 +85,14 @@ + <%-- View mode settings - <%-- View mode settings --%> + --%> diff --git a/source/web/jsp/roles/manage-invited-users.jsp b/source/web/jsp/roles/manage-invited-users.jsp index 2010add406..73d0306f24 100644 --- a/source/web/jsp/roles/manage-invited-users.jsp +++ b/source/web/jsp/roles/manage-invited-users.jsp @@ -85,13 +85,14 @@ + <%-- View mode settings - <%-- View mode settings --%> + --%> diff --git a/source/web/jsp/workflow/tasks-completed-dashlet.jsp b/source/web/jsp/workflow/tasks-completed-dashlet.jsp index 87b422232c..49245d5c8e 100644 --- a/source/web/jsp/workflow/tasks-completed-dashlet.jsp +++ b/source/web/jsp/workflow/tasks-completed-dashlet.jsp @@ -43,52 +43,41 @@ - - <%-- Source column --%> - - - - - - - - <%-- Created Date column --%> - + - + - + <%-- Completed date column --%> - + - + - + <%-- Outcome column --%> - + - + - + <%-- Actions column --%> - + - + - diff --git a/source/web/jsp/workflow/tasks-todo-dashlet.jsp b/source/web/jsp/workflow/tasks-todo-dashlet.jsp index be2f84d44c..a225ec347e 100644 --- a/source/web/jsp/workflow/tasks-todo-dashlet.jsp +++ b/source/web/jsp/workflow/tasks-todo-dashlet.jsp @@ -44,59 +44,48 @@ - <%-- Source column --%> + <%-- Created Date column --%> - + - - - - - - <%-- Created Date column --%> - - - - - + <%-- Due date column --%> - + - + - + <%-- Status column --%> - + - + - + <%-- Priority column --%> - + - + - + <%-- Actions column --%> - + - + -