Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)

125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.1.N/root@125605 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-04-20 10:30:21 +00:00
parent 1ce8e6fa1d
commit 73ffa91a49
265 changed files with 44099 additions and 44099 deletions

View File

@@ -1,38 +1,38 @@
package org.alfresco.web.action;
import java.io.Serializable;
import org.alfresco.web.bean.repository.Node;
/**
* Contract supported by all classes that provide dynamic evaluation for a UI action.
* <p>
* Evaluators are supplied with a Node instance context object.
* <p>
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the properties etc. of the Node context and return the result.
*
* @author Kevin Roast
*/
public interface ActionEvaluator extends Serializable
{
/**
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the properties etc. of the Node context and return the result.
*
* @param node Node context for the action
*
* @return result of whether the action can proceed.
*/
public boolean evaluate(Node node);
/**
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the state etc. of the given object and return the result.
*
* @param obj The object the action is for
*
* @return result of whether the action can proceed.
*/
public boolean evaluate(Object obj);
}
package org.alfresco.web.action;
import java.io.Serializable;
import org.alfresco.web.bean.repository.Node;
/**
* Contract supported by all classes that provide dynamic evaluation for a UI action.
* <p>
* Evaluators are supplied with a Node instance context object.
* <p>
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the properties etc. of the Node context and return the result.
*
* @author Kevin Roast
*/
public interface ActionEvaluator extends Serializable
{
/**
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the properties etc. of the Node context and return the result.
*
* @param node Node context for the action
*
* @return result of whether the action can proceed.
*/
public boolean evaluate(Node node);
/**
* The evaluator should decide if the action precondition is valid based on the appropriate
* logic and the state etc. of the given object and return the result.
*
* @param obj The object the action is for
*
* @return result of whether the action can proceed.
*/
public boolean evaluate(Object obj);
}

View File

@@ -1,34 +1,34 @@
package org.alfresco.web.action.evaluator;
import java.util.Map;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - 'Approve' workflow step for document or space.
*
* @author Kevin Roast
*/
public class ApproveDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 2958297435415449179L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
Map<String,Object> properties = node.getProperties();
Boolean approveMove = (Boolean) properties.get("app:approveMove");
boolean isMove = approveMove == null ? false : approveMove;
boolean canProceed = (properties.get("app:approveStep") != null) && !node.isLocked();
//If this approval is going to result in a move of the node then we check whether the user
//has permission. The delete permission is required in order to move a node (odd, perhaps, but true).
canProceed &= (!isMove || node.hasPermission(PermissionService.DELETE));
return canProceed;
}
}
package org.alfresco.web.action.evaluator;
import java.util.Map;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - 'Approve' workflow step for document or space.
*
* @author Kevin Roast
*/
public class ApproveDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 2958297435415449179L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
Map<String,Object> properties = node.getProperties();
Boolean approveMove = (Boolean) properties.get("app:approveMove");
boolean isMove = approveMove == null ? false : approveMove;
boolean canProceed = (properties.get("app:approveStep") != null) && !node.isLocked();
//If this approval is going to result in a move of the node then we check whether the user
//has permission. The delete permission is required in order to move a node (odd, perhaps, but true).
canProceed &= (!isMove || node.hasPermission(PermissionService.DELETE));
return canProceed;
}
}

View File

@@ -1,25 +1,25 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Cancel checkout document.
*
* @author Kevin Roast
*/
public class CancelCheckoutDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -9015403093449070254L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null &&
node.hasPermission(PermissionService.CANCEL_CHECK_OUT));
}
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Cancel checkout document.
*
* @author Kevin Roast
*/
public class CancelCheckoutDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -9015403093449070254L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null &&
node.hasPermission(PermissionService.CANCEL_CHECK_OUT));
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.action.evaluator;
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.WorkflowTask;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.User;
/**
* UI Action Evaluator for cancel workflow action. The action
* is only allowed if the workflow the task belongs to was
* started by the current user.
*
* @author gavinc
*/
public class CancelWorkflowEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 7663087149225546333L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = false;
FacesContext context = FacesContext.getCurrentInstance();
// get the task from the node
WorkflowTask task = (WorkflowTask)node.getProperties().get("workflowTask");
if (task != null)
{
NodeRef initiator = task.path.instance.initiator;
if (initiator != null)
{
// find the current username
User user = Application.getCurrentUser(context);
String currentUserName = 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;
}
}
}
return result;
}
}
package org.alfresco.web.action.evaluator;
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.WorkflowTask;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.User;
/**
* UI Action Evaluator for cancel workflow action. The action
* is only allowed if the workflow the task belongs to was
* started by the current user.
*
* @author gavinc
*/
public class CancelWorkflowEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 7663087149225546333L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = false;
FacesContext context = FacesContext.getCurrentInstance();
// get the task from the node
WorkflowTask task = (WorkflowTask)node.getProperties().get("workflowTask");
if (task != null)
{
NodeRef initiator = task.path.instance.initiator;
if (initiator != null)
{
// find the current username
User user = Application.getCurrentUser(context);
String currentUserName = 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;
}
}
}
return result;
}
}

View File

@@ -1,25 +1,25 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Checkin document.
*
* @author Kevin Roast
*/
public class CheckinDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5398249535631219663L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null &&
node.hasPermission(PermissionService.CHECK_IN));
}
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Checkin document.
*
* @author Kevin Roast
*/
public class CheckinDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5398249535631219663L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null &&
node.hasPermission(PermissionService.CHECK_IN));
}
}

View File

@@ -1,34 +1,34 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Checkout document.
*
* @author Kevin Roast
*/
public class CheckoutDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5510366635124591353L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
DictionaryService dd = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getDictionaryService();
return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) &&
((node.hasPermission(PermissionService.CHECK_OUT) &&
(node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false) &&
node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) == false));
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Checkout document.
*
* @author Kevin Roast
*/
public class CheckoutDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5510366635124591353L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
DictionaryService dd = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getDictionaryService();
return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) &&
((node.hasPermission(PermissionService.CHECK_OUT) &&
(node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false) &&
node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) == false));
}
}

View File

@@ -1,23 +1,23 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ForumModel;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Create a forum around a node.
*
* @author Kevin Roast
*/
public class CreateForumNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -5132048668011887505L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE) == false &&
node.isLocked() == false);
}
}
package org.alfresco.web.action.evaluator;
import org.alfresco.model.ForumModel;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Create a forum around a node.
*
* @author Kevin Roast
*/
public class CreateForumNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -5132048668011887505L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE) == false &&
node.isLocked() == false);
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Delete document.
*
* @author Kevin Roast
*/
public class DeleteDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5742287199692844685L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
// the node to delete is a ml container, test if the user has enought right on each translation
if(node.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
return MultilingualUtils.canDeleteEachTranslation(node, fc);
}
boolean isPivot = false;
// special case for multilingual documents
if (node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
MultilingualContentService mlservice =
(MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
// if the translation is the last translation, user can delete it
if (mlservice.getTranslations(node.getNodeRef()).size() == 1)
{
isPivot = false;
}
// Else if the node is the pivot language, user can't delete it
else if (mlservice.getPivotTranslation(node.getNodeRef()).getId()
.equalsIgnoreCase(node.getNodeRef().getId()))
{
isPivot = true;
}
// finally, the node is not the pivot translation, user can delete it
}
return (node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false &&
isPivot == false);
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.ml.MultilingualUtils;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Delete document.
*
* @author Kevin Roast
*/
public class DeleteDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 5742287199692844685L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
// the node to delete is a ml container, test if the user has enought right on each translation
if(node.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
return MultilingualUtils.canDeleteEachTranslation(node, fc);
}
boolean isPivot = false;
// special case for multilingual documents
if (node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
MultilingualContentService mlservice =
(MultilingualContentService) FacesHelper.getManagedBean(fc, "MultilingualContentService");
// if the translation is the last translation, user can delete it
if (mlservice.getTranslations(node.getNodeRef()).size() == 1)
{
isPivot = false;
}
// Else if the node is the pivot language, user can't delete it
else if (mlservice.getPivotTranslation(node.getNodeRef()).getId()
.equalsIgnoreCase(node.getNodeRef().getId()))
{
isPivot = true;
}
// finally, the node is not the pivot translation, user can delete it
}
return (node.isLocked() == false &&
node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false &&
isPivot == false);
}
}

View File

@@ -1,47 +1,47 @@
package org.alfresco.web.action.evaluator;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Discuss a node.
*
* @author Kevin Roast
*/
public class DiscussNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 8754174908349998903L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = false;
if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE))
{
NodeService nodeService = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getNodeService();
List<ChildAssociationRef> children = nodeService.getChildAssocs(
node.getNodeRef(), ForumModel.ASSOC_DISCUSSION,
RegexQNamePattern.MATCH_ALL);
// make sure there is one visible child association for the node
if (children.size() == 1)
{
result = true;
}
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Discuss a node.
*
* @author Kevin Roast
*/
public class DiscussNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 8754174908349998903L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = false;
if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE))
{
NodeService nodeService = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getNodeService();
List<ChildAssociationRef> children = nodeService.getChildAssocs(
node.getNodeRef(), ForumModel.ASSOC_DISCUSSION,
RegexQNamePattern.MATCH_ALL);
// make sure there is one visible child association for the node
if (children.size() == 1)
{
result = true;
}
}
return result;
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* Evaluates whether the copy action should be visible.
*
* If the node is a discussion don't allow the action.
*
* @author gavinc
*/
public class DiscussionCopyEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -4080878553011296677L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = true;
// if the node in question is a forum...
if (node.getType().equals(ForumModel.TYPE_FORUM))
{
// get the association type
FacesContext context = FacesContext.getCurrentInstance();
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(node.getNodeRef());
QName assocType = parentAssoc.getTypeQName();
// only allow the action if the association type is not the discussion assoc
result = (assocType.equals(ForumModel.ASSOC_DISCUSSION) == false);
}
// impossible to copy a translation without content.
if (result && node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
result = false;
}
if (!node.hasPermission(PermissionService.READ))
{
result = false;
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* Evaluates whether the copy action should be visible.
*
* If the node is a discussion don't allow the action.
*
* @author gavinc
*/
public class DiscussionCopyEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -4080878553011296677L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = true;
// if the node in question is a forum...
if (node.getType().equals(ForumModel.TYPE_FORUM))
{
// get the association type
FacesContext context = FacesContext.getCurrentInstance();
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(node.getNodeRef());
QName assocType = parentAssoc.getTypeQName();
// only allow the action if the association type is not the discussion assoc
result = (assocType.equals(ForumModel.ASSOC_DISCUSSION) == false);
}
// impossible to copy a translation without content.
if (result && node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
result = false;
}
if (!node.hasPermission(PermissionService.READ))
{
result = false;
}
return result;
}
}

View File

@@ -1,46 +1,46 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* Evaluates whether the cut action should be visible.
*
* If the node is a discussion don't allow the action.
*
* @author gavinc
*/
public class DiscussionCutEvaluator extends CutNodeEvaluator
{
private static final long serialVersionUID = 7260556874788184200L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = super.evaluate(node);
// if the node in question is a forum...
if (result && node.getType().equals(ForumModel.TYPE_FORUM))
{
// get the association type
FacesContext context = FacesContext.getCurrentInstance();
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(node.getNodeRef());
QName assocType = parentAssoc.getTypeQName();
// only allow the action if the association type is not the discussion assoc
result = (assocType.equals(ForumModel.ASSOC_DISCUSSION) == false);
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* Evaluates whether the cut action should be visible.
*
* If the node is a discussion don't allow the action.
*
* @author gavinc
*/
public class DiscussionCutEvaluator extends CutNodeEvaluator
{
private static final long serialVersionUID = 7260556874788184200L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean result = super.evaluate(node);
// if the node in question is a forum...
if (result && node.getType().equals(ForumModel.TYPE_FORUM))
{
// get the association type
FacesContext context = FacesContext.getCurrentInstance();
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(node.getNodeRef());
QName assocType = parentAssoc.getTypeQName();
// only allow the action if the association type is not the discussion assoc
result = (assocType.equals(ForumModel.ASSOC_DISCUSSION) == false);
}
return result;
}
}

View File

@@ -1,51 +1,51 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via CIFS.
*
* @author Kevin Roast
*/
public class EditDocCIFSEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -8988276140748731926L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// if the node is inline editable, the default http behaviour should always be used
if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == false &&
"cifs".equals(Application.getClientConfig(fc).getEditLinkType()))
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) != null &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING))||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via CIFS.
*
* @author Kevin Roast
*/
public class EditDocCIFSEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -8988276140748731926L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// if the node is inline editable, the default http behaviour should always be used
if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == false &&
"cifs".equals(Application.getClientConfig(fc).getEditLinkType()))
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) != null &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING))||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via HTTP or inline edit.
*
* @author Kevin Roast
*/
public class EditDocHttpEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -3694679925715830430L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// Since the reader returned of an empty translation is the reader of it's pivot translation, it makes
// no sens to edit it on-line.
if(node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
//result = false
}
// if the node is inline editable, the default http behaviour should
// always be used otherwise the configured approach is used
else if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == true &&
node.getProperties().get(ApplicationModel.PROP_EDITINLINE) != null &&
((Boolean)node.getProperties().get(ApplicationModel.PROP_EDITINLINE)).booleanValue() == true)
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) != null &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING)) ||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via HTTP or inline edit.
*
* @author Kevin Roast
*/
public class EditDocHttpEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -3694679925715830430L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// Since the reader returned of an empty translation is the reader of it's pivot translation, it makes
// no sens to edit it on-line.
if(node.getAspects().contains(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
//result = false
}
// if the node is inline editable, the default http behaviour should
// always be used otherwise the configured approach is used
else if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == true &&
node.getProperties().get(ApplicationModel.PROP_EDITINLINE) != null &&
((Boolean)node.getProperties().get(ApplicationModel.PROP_EDITINLINE)).booleanValue() == true)
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) != null &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING)) ||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}

View File

@@ -1,50 +1,50 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via Webdav.
*
* @author Kevin Roast
*/
public class EditDocWebDavEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 293342561997588700L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// if the node is inline editable, the default http behaviour should always be used
if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == false &&
"webdav".equals(Application.getClientConfig(fc).getEditLinkType()))
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING)) ||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.coci.EditOnlineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Edit document via Webdav.
*
* @author Kevin Roast
*/
public class EditDocWebDavEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 293342561997588700L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext fc = FacesContext.getCurrentInstance();
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
boolean result = false;
// if the node is inline editable, the default http behaviour should always be used
if (dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT))
{
if (node.hasAspect(ApplicationModel.ASPECT_INLINEEDITABLE) == false &&
"webdav".equals(Application.getClientConfig(fc).getEditLinkType()))
{
if ((node.isWorkingCopyOwner() == true && node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE).equals(EditOnlineDialog.ONLINE_EDITING)) ||
(node.hasAspect(ContentModel.ASPECT_WORKING_COPY) && node.hasPermission(PermissionService.WRITE)) ||
(node.isLocked() == false && node.hasAspect(ContentModel.ASPECT_WORKING_COPY) == false))
{
result = true;
}
}
}
return result;
}
}

View File

@@ -1,54 +1,54 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Checkin a document with potentially a Forum attached.
*
* @author Kevin Roast
*/
public class ForumsCheckinDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -924897450989526336L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean allow = false;
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null)
{
if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE))
{
CheckOutCheckInService checkOutCheckInService =
Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCheckOutCheckInService();
// get the original locked node (via the copiedfrom aspect)
NodeRef lockedNodeRef = checkOutCheckInService.getCheckedOut(node.getNodeRef());
if (lockedNodeRef != null)
{
Node lockedNode = new Node(lockedNodeRef);
allow = (node.hasPermission(PermissionService.CHECK_IN) &&
lockedNode.hasPermission(PermissionService.CONTRIBUTOR));
}
}
else
{
// there is no discussion so just check they have checkin permission for the node
allow = node.hasPermission(PermissionService.CHECK_IN);
}
}
return allow;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Checkin a document with potentially a Forum attached.
*
* @author Kevin Roast
*/
public class ForumsCheckinDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -924897450989526336L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
boolean allow = false;
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY) &&
node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE) == null)
{
if (node.hasAspect(ForumModel.ASPECT_DISCUSSABLE))
{
CheckOutCheckInService checkOutCheckInService =
Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCheckOutCheckInService();
// get the original locked node (via the copiedfrom aspect)
NodeRef lockedNodeRef = checkOutCheckInService.getCheckedOut(node.getNodeRef());
if (lockedNodeRef != null)
{
Node lockedNode = new Node(lockedNodeRef);
allow = (node.hasPermission(PermissionService.CHECK_IN) &&
lockedNode.hasPermission(PermissionService.CONTRIBUTOR));
}
}
else
{
// there is no discussion so just check they have checkin permission for the node
allow = node.hasPermission(PermissionService.CHECK_IN);
}
}
return allow;
}
}

View File

@@ -1,22 +1,22 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - 'Reject' workflow step for document or space.
*
* @author Kevin Roast
*/
public class RejectDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -7733947744617999298L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.getProperties().get("app:rejectStep") != null &&
node.isLocked() == false);
}
}
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - 'Reject' workflow step for document or space.
*
* @author Kevin Roast
*/
public class RejectDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -7733947744617999298L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.getProperties().get("app:rejectStep") != null &&
node.isLocked() == false);
}
}

View File

@@ -1,27 +1,27 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Create a shortcut to a node.
*
* @author Kevin Roast
*/
public class ShortcutNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 8768692540125721144L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
NavigationBean nav =
(NavigationBean)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), NavigationBean.BEAN_NAME);
return (nav.getIsGuest() == false);
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Create a shortcut to a node.
*
* @author Kevin Roast
*/
public class ShortcutNodeEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 8768692540125721144L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
NavigationBean nav =
(NavigationBean)FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), NavigationBean.BEAN_NAME);
return (nav.getIsGuest() == false);
}
}

View File

@@ -1,45 +1,45 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Node;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;
/**
* UI Action Evaluator - Start workflow on a node.
*
* @author gavinc
*/
public class StartWorkflowEvaluator extends BaseActionEvaluator
{
private static final String BPM_ENGINE_BEAN_NAME = "bpm_engineRegistry";
private static final long serialVersionUID = 3110333488835027710L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
NavigationBean nav =
(NavigationBean)FacesHelper.getManagedBean(facesContext, NavigationBean.BEAN_NAME);
// determine whether the workflow services are active
boolean workflowPresent = false;
WebApplicationContext springContext = FacesContextUtils.getRequiredWebApplicationContext(facesContext);
BPMEngineRegistry bpmReg = (BPMEngineRegistry)springContext.getBean(BPM_ENGINE_BEAN_NAME);
if (bpmReg != null)
{
String[] components = bpmReg.getWorkflowComponents();
workflowPresent = (components != null && components.length > 0);
}
return (workflowPresent && nav.getIsGuest() == false &&
node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) == false);
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.workflow.BPMEngineRegistry;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Node;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;
/**
* UI Action Evaluator - Start workflow on a node.
*
* @author gavinc
*/
public class StartWorkflowEvaluator extends BaseActionEvaluator
{
private static final String BPM_ENGINE_BEAN_NAME = "bpm_engineRegistry";
private static final long serialVersionUID = 3110333488835027710L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
NavigationBean nav =
(NavigationBean)FacesHelper.getManagedBean(facesContext, NavigationBean.BEAN_NAME);
// determine whether the workflow services are active
boolean workflowPresent = false;
WebApplicationContext springContext = FacesContextUtils.getRequiredWebApplicationContext(facesContext);
BPMEngineRegistry bpmReg = (BPMEngineRegistry)springContext.getBean(BPM_ENGINE_BEAN_NAME);
if (bpmReg != null)
{
String[] components = bpmReg.getWorkflowComponents();
workflowPresent = (components != null && components.length > 0);
}
return (workflowPresent && nav.getIsGuest() == false &&
node.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION) == false);
}
}

View File

@@ -1,21 +1,21 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Take ownership of a document.
*
* @author Kevin Roast
*/
public class TakeOwnershipDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 3966463533922521230L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.isLocked() == false);
}
}
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Take ownership of a document.
*
* @author Kevin Roast
*/
public class TakeOwnershipDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 3966463533922521230L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.isLocked() == false);
}
}

View File

@@ -1,35 +1,35 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Unlock a locked document.
*
* @author Kevin Roast
*/
public class UnlockDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -7056759932698306087L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
if (node.isLocked())
{
FacesContext fc = FacesContext.getCurrentInstance();
CheckOutCheckInService checkOutCheckInService = (CheckOutCheckInService) FacesHelper.getManagedBean(fc, "CheckoutCheckinService");
if (checkOutCheckInService.getWorkingCopy(node.getNodeRef()) == null)
{
return true;
}
}
return false;
}
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Unlock a locked document.
*
* @author Kevin Roast
*/
public class UnlockDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -7056759932698306087L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
if (node.isLocked())
{
FacesContext fc = FacesContext.getCurrentInstance();
CheckOutCheckInService checkOutCheckInService = (CheckOutCheckInService) FacesHelper.getManagedBean(fc, "CheckoutCheckinService");
if (checkOutCheckInService.getWorkingCopy(node.getNodeRef()) == null)
{
return true;
}
}
return false;
}
}

View File

@@ -1,21 +1,21 @@
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Proceed if the document is not locked.
*
* @author Kevin Roast
*/
public class UnlockedDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -3216759932698306123L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.isLocked() == false);
}
package org.alfresco.web.action.evaluator;
import org.alfresco.web.bean.repository.Node;
/**
* UI Action Evaluator - Proceed if the document is not locked.
*
* @author Kevin Roast
*/
public class UnlockedDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = -3216759932698306123L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
return (node.isLocked() == false);
}
}

View File

@@ -1,35 +1,35 @@
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.web.bean.coci.EditOfflineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Update document content.
*
* @author Kevin Roast
*/
public class UpdateDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 6030963610213633893L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
DictionaryService dd = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getDictionaryService();
boolean isOfflineEditing =
(EditOfflineDialog.OFFLINE_EDITING.equals(node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE)));
return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) &&
((node.isWorkingCopyOwner() && !isOfflineEditing) ||
(!node.isLocked() && !node.hasAspect(ContentModel.ASPECT_WORKING_COPY)));
}
package org.alfresco.web.action.evaluator;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.web.bean.coci.EditOfflineDialog;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
/**
* UI Action Evaluator - Update document content.
*
* @author Kevin Roast
*/
public class UpdateDocEvaluator extends BaseActionEvaluator
{
private static final long serialVersionUID = 6030963610213633893L;
/**
* @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(Node node)
{
DictionaryService dd = Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getDictionaryService();
boolean isOfflineEditing =
(EditOfflineDialog.OFFLINE_EDITING.equals(node.getProperties().get(ContentModel.PROP_WORKING_COPY_MODE)));
return dd.isSubClass(node.getType(), ContentModel.TYPE_CONTENT) &&
((node.isWorkingCopyOwner() && !isOfflineEditing) ||
(!node.isLocked() && !node.hasAspect(ContentModel.ASPECT_WORKING_COPY)));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,152 +1,152 @@
package org.alfresco.web.app;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.jsf.DelegatingVariableResolver;
/**
* JSF VariableResolver that first delegates to the Spring JSF variable
* resolver. The sole purpose of this variable resolver is to look out
* for the <code>Container</code> variable. If this variable is encountered
* the current viewId is examined. If the current viewId matches a
* configured dialog or wizard container the appropriate manager object is
* returned i.e. DialogManager or WizardManager.
*
* <p>Configure this resolver in your <code>faces-config.xml</code> file as follows:
*
* <pre>
* &lt;application&gt;
* ...
* &lt;variable-resolver&gt;org.alfresco.web.app.AlfrescoVariableResolver&lt;/variable-resolver&gt;
* &lt;/application&gt;</pre>
*
* @see org.alfresco.web.bean.dialog.DialogManager
* @see org.alfresco.web.bean.wizard.WizardManager
* @author gavinc
*/
public class AlfrescoVariableResolver extends DelegatingVariableResolver
{
protected List<String> dialogContainers = null;
protected List<String> wizardContainers = null;
private static final String CONTAINER = "Container";
private static final Log logger = LogFactory.getLog(AlfrescoVariableResolver.class);
/**
* Creates a new VariableResolver.
*
* @param originalVariableResolver The original variable resolver
*/
public AlfrescoVariableResolver(VariableResolver originalVariableResolver)
{
super(originalVariableResolver);
}
/**
* Resolves the variable with the given name.
* <p>
* This implementation will first delegate to the Spring variable resolver.
* If the variable is not found by the Spring resolver and the variable name
* is <code>Container</code> the current viewId is examined.
* If the current viewId matches a configured dialog or wizard container
* the appropriate manager object is returned i.e. DialogManager or WizardManager.
*
* @param context FacesContext
* @param name The name of the variable to resolve
*/
public Object resolveVariable(FacesContext context, String name)
throws EvaluationException
{
Object variable = super.resolveVariable(context, name);
if (variable == null)
{
// if the variable was not resolved see if the name is "Container"
if (name.equals(CONTAINER))
{
// get the current view id and the configured dialog and wizard
// container pages
String viewId = context.getViewRoot().getViewId();
List<String> dialogContainers = getDialogContainers(context);
List<String> wizardContainers = getWizardContainers(context);
// see if we are currently in a wizard or a dialog
if (dialogContainers.contains(viewId))
{
variable = Application.getDialogManager();
}
else if (wizardContainers.contains(viewId))
{
variable = Application.getWizardManager();
}
if (variable != null && logger.isDebugEnabled())
{
logger.debug("Resolved 'Container' variable to: " + variable);
}
}
}
return variable;
}
/**
* Retrieves the list of configured dialog container pages
*
* @param context FacesContext
* @return The container pages
*/
protected List<String> getDialogContainers(FacesContext context)
{
if ((this.dialogContainers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.dialogContainers = new ArrayList<String>(2);
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.dialogContainers.add(globalConfig.getConfigElement("dialog-container").getValue());
this.dialogContainers.add(globalConfig.getConfigElement("plain-dialog-container").getValue());
}
}
return this.dialogContainers;
}
/**
* Retrieves the list of configured wizard container pages
*
* @param context FacesContext
* @return The container page
*/
protected List<String> getWizardContainers(FacesContext context)
{
if ((this.wizardContainers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.wizardContainers = new ArrayList<String>(2);
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.wizardContainers.add(globalConfig.getConfigElement("wizard-container").getValue());
this.wizardContainers.add(globalConfig.getConfigElement("plain-wizard-container").getValue());
}
}
return this.wizardContainers;
}
}
package org.alfresco.web.app;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.jsf.DelegatingVariableResolver;
/**
* JSF VariableResolver that first delegates to the Spring JSF variable
* resolver. The sole purpose of this variable resolver is to look out
* for the <code>Container</code> variable. If this variable is encountered
* the current viewId is examined. If the current viewId matches a
* configured dialog or wizard container the appropriate manager object is
* returned i.e. DialogManager or WizardManager.
*
* <p>Configure this resolver in your <code>faces-config.xml</code> file as follows:
*
* <pre>
* &lt;application&gt;
* ...
* &lt;variable-resolver&gt;org.alfresco.web.app.AlfrescoVariableResolver&lt;/variable-resolver&gt;
* &lt;/application&gt;</pre>
*
* @see org.alfresco.web.bean.dialog.DialogManager
* @see org.alfresco.web.bean.wizard.WizardManager
* @author gavinc
*/
public class AlfrescoVariableResolver extends DelegatingVariableResolver
{
protected List<String> dialogContainers = null;
protected List<String> wizardContainers = null;
private static final String CONTAINER = "Container";
private static final Log logger = LogFactory.getLog(AlfrescoVariableResolver.class);
/**
* Creates a new VariableResolver.
*
* @param originalVariableResolver The original variable resolver
*/
public AlfrescoVariableResolver(VariableResolver originalVariableResolver)
{
super(originalVariableResolver);
}
/**
* Resolves the variable with the given name.
* <p>
* This implementation will first delegate to the Spring variable resolver.
* If the variable is not found by the Spring resolver and the variable name
* is <code>Container</code> the current viewId is examined.
* If the current viewId matches a configured dialog or wizard container
* the appropriate manager object is returned i.e. DialogManager or WizardManager.
*
* @param context FacesContext
* @param name The name of the variable to resolve
*/
public Object resolveVariable(FacesContext context, String name)
throws EvaluationException
{
Object variable = super.resolveVariable(context, name);
if (variable == null)
{
// if the variable was not resolved see if the name is "Container"
if (name.equals(CONTAINER))
{
// get the current view id and the configured dialog and wizard
// container pages
String viewId = context.getViewRoot().getViewId();
List<String> dialogContainers = getDialogContainers(context);
List<String> wizardContainers = getWizardContainers(context);
// see if we are currently in a wizard or a dialog
if (dialogContainers.contains(viewId))
{
variable = Application.getDialogManager();
}
else if (wizardContainers.contains(viewId))
{
variable = Application.getWizardManager();
}
if (variable != null && logger.isDebugEnabled())
{
logger.debug("Resolved 'Container' variable to: " + variable);
}
}
}
return variable;
}
/**
* Retrieves the list of configured dialog container pages
*
* @param context FacesContext
* @return The container pages
*/
protected List<String> getDialogContainers(FacesContext context)
{
if ((this.dialogContainers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.dialogContainers = new ArrayList<String>(2);
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.dialogContainers.add(globalConfig.getConfigElement("dialog-container").getValue());
this.dialogContainers.add(globalConfig.getConfigElement("plain-dialog-container").getValue());
}
}
return this.dialogContainers;
}
/**
* Retrieves the list of configured wizard container pages
*
* @param context FacesContext
* @return The container page
*/
protected List<String> getWizardContainers(FacesContext context)
{
if ((this.wizardContainers == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.wizardContainers = new ArrayList<String>(2);
ConfigService configSvc = Application.getConfigService(context);
Config globalConfig = configSvc.getGlobalConfig();
if (globalConfig != null)
{
this.wizardContainers.add(globalConfig.getConfigElement("wizard-container").getValue());
this.wizardContainers.add(globalConfig.getConfigElement("plain-wizard-container").getValue());
}
}
return this.wizardContainers;
}
}

View File

@@ -1,99 +1,99 @@
package org.alfresco.web.app;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Debug phase listener that simply logs when each phase is entered and exited.
*
* @author gavinc
*/
public class DebugPhaseListener implements PhaseListener
{
private static final Log logger = LogFactory.getLog(DebugPhaseListener.class);
public int indent = 0;
public static final String INDENT = " ";
/**
* @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
*/
public void afterPhase(PhaseEvent event)
{
if (logger.isDebugEnabled())
{
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE)
{
printComponentTree(FacesContext.getCurrentInstance().getViewRoot());
}
logger.debug("********** Exiting phase: " + event.getPhaseId().toString());
}
}
/**
* @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
*/
public void beforePhase(PhaseEvent event)
{
if (logger.isDebugEnabled())
logger.debug("********** Entering phase: " + event.getPhaseId().toString());
}
/**
* @see javax.faces.event.PhaseListener#getPhaseId()
*/
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
public void printComponentTree(UIComponent comp)
{
printComponentInfo(comp);
List complist = comp.getChildren();
if (complist.size()>0)
indent++;
for (int i = 0; i < complist.size(); i++)
{
UIComponent uicom = (UIComponent) complist.get(i);
printComponentTree(uicom);
if (i+1 == complist.size())
indent--;
}
}
public void printComponentInfo(UIComponent comp)
{
if (comp.getId() == null)
{
logger.debug("UIViewRoot" + " " + "(" + comp.getClass().getName() + ")");
}
else
{
logger.debug(getIndent() + "|");
logger.debug(getIndent() + comp.getId() + " " + "(" + comp.getClass().getName() + ")");
}
}
public String getIndent()
{
String indent = "";
for (int i=0; i<this.indent; i++)
{
indent += INDENT;
}
return indent;
}
}
package org.alfresco.web.app;
import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Debug phase listener that simply logs when each phase is entered and exited.
*
* @author gavinc
*/
public class DebugPhaseListener implements PhaseListener
{
private static final Log logger = LogFactory.getLog(DebugPhaseListener.class);
public int indent = 0;
public static final String INDENT = " ";
/**
* @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
*/
public void afterPhase(PhaseEvent event)
{
if (logger.isDebugEnabled())
{
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE)
{
printComponentTree(FacesContext.getCurrentInstance().getViewRoot());
}
logger.debug("********** Exiting phase: " + event.getPhaseId().toString());
}
}
/**
* @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
*/
public void beforePhase(PhaseEvent event)
{
if (logger.isDebugEnabled())
logger.debug("********** Entering phase: " + event.getPhaseId().toString());
}
/**
* @see javax.faces.event.PhaseListener#getPhaseId()
*/
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
public void printComponentTree(UIComponent comp)
{
printComponentInfo(comp);
List complist = comp.getChildren();
if (complist.size()>0)
indent++;
for (int i = 0; i < complist.size(); i++)
{
UIComponent uicom = (UIComponent) complist.get(i);
printComponentTree(uicom);
if (i+1 == complist.size())
indent--;
}
}
public void printComponentInfo(UIComponent comp)
{
if (comp.getId() == null)
{
logger.debug("UIViewRoot" + " " + "(" + comp.getClass().getName() + ")");
}
else
{
logger.debug(getIndent() + "|");
logger.debug(getIndent() + comp.getId() + " " + "(" + comp.getClass().getName() + ")");
}
}
public String getIndent()
{
String indent = "";
for (int i=0; i<this.indent; i++)
{
indent += INDENT;
}
return indent;
}
}

View File

@@ -1,43 +1,43 @@
package org.alfresco.web.app.portlet;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.User;
import org.apache.myfaces.portlet.DefaultViewSelector;
/**
* @author Kevin Roast
*/
public class AlfrescoDefaultViewSelector implements DefaultViewSelector
{
/**
* Select the appropriate view ID
*/
public String selectViewId(RenderRequest request, RenderResponse response) throws PortletException
{
User user = (User) request.getPortletSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER,
PortletSession.APPLICATION_SCOPE);
if (user != null && user.getUserName().equals(AuthenticationUtil.getGuestUserName()))
{
return FacesHelper.BROWSE_VIEW_ID;
}
else
{
return null;
}
}
/**
* @see org.apache.myfaces.portlet.DefaultViewSelector#setPortletContext(javax.portlet.PortletContext)
*/
public void setPortletContext(PortletContext portletContext)
{
}
}
package org.alfresco.web.app.portlet;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.User;
import org.apache.myfaces.portlet.DefaultViewSelector;
/**
* @author Kevin Roast
*/
public class AlfrescoDefaultViewSelector implements DefaultViewSelector
{
/**
* Select the appropriate view ID
*/
public String selectViewId(RenderRequest request, RenderResponse response) throws PortletException
{
User user = (User) request.getPortletSession().getAttribute(AuthenticationHelper.AUTHENTICATION_USER,
PortletSession.APPLICATION_SCOPE);
if (user != null && user.getUserName().equals(AuthenticationUtil.getGuestUserName()))
{
return FacesHelper.BROWSE_VIEW_ID;
}
else
{
return null;
}
}
/**
* @see org.apache.myfaces.portlet.DefaultViewSelector#setPortletContext(javax.portlet.PortletContext)
*/
public void setPortletContext(PortletContext portletContext)
{
}
}

View File

@@ -1,97 +1,97 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.bean.repository.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This servlet filter is used to restrict direct URL access to administration
* resource in the web client, for example the admin and jBPM consoles.
*
* @author gavinc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class AdminAuthenticationFilter implements Filter
{
private static final Log logger = LogFactory.getLog(AdminAuthenticationFilter.class);
private FilterConfig config;
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest)req;
HttpServletResponse httpResponse = (HttpServletResponse)res;
// The fact that this filter is being called means a request for a protected
// resource has taken place, check that the current user is in fact an
// administrator.
if (logger.isDebugEnabled())
logger.debug("Authorising request for protected resource: " + httpRequest.getRequestURI());
// there should be a user at this point so retrieve it
User user = AuthenticationHelper.getUser(this.config.getServletContext(), httpRequest, httpResponse);
// if the user is present check to see whether it is an admin user
boolean isAdmin = (user != null && user.isAdmin());
if (isAdmin)
{
if (logger.isDebugEnabled())
logger.debug("Current user has admin authority, allowing access.");
// continue filter chaining if current user is admin user
chain.doFilter(req, res);
}
else
{
// return the 401 Forbidden error as the current user is not an administrator
// if the response has already been committed there's nothing we can do but
// print out a warning
if (httpResponse.isCommitted() == false)
{
if (logger.isDebugEnabled())
logger.debug("Current user does not have admin authority, returning 401 Forbidden error...");
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
}
else
{
if (logger.isWarnEnabled())
logger.warn("Access denied to '" + httpRequest.getRequestURI() +
"'. The response has already been committed so a 401 Forbidden error could not be sent!");
}
}
}
/**
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig config) throws ServletException
{
this.config = config;
}
/**
* @see javax.servlet.Filter#destroy()
*/
public void destroy()
{
// nothing to do
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.bean.repository.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This servlet filter is used to restrict direct URL access to administration
* resource in the web client, for example the admin and jBPM consoles.
*
* @author gavinc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class AdminAuthenticationFilter implements Filter
{
private static final Log logger = LogFactory.getLog(AdminAuthenticationFilter.class);
private FilterConfig config;
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest)req;
HttpServletResponse httpResponse = (HttpServletResponse)res;
// The fact that this filter is being called means a request for a protected
// resource has taken place, check that the current user is in fact an
// administrator.
if (logger.isDebugEnabled())
logger.debug("Authorising request for protected resource: " + httpRequest.getRequestURI());
// there should be a user at this point so retrieve it
User user = AuthenticationHelper.getUser(this.config.getServletContext(), httpRequest, httpResponse);
// if the user is present check to see whether it is an admin user
boolean isAdmin = (user != null && user.isAdmin());
if (isAdmin)
{
if (logger.isDebugEnabled())
logger.debug("Current user has admin authority, allowing access.");
// continue filter chaining if current user is admin user
chain.doFilter(req, res);
}
else
{
// return the 401 Forbidden error as the current user is not an administrator
// if the response has already been committed there's nothing we can do but
// print out a warning
if (httpResponse.isCommitted() == false)
{
if (logger.isDebugEnabled())
logger.debug("Current user does not have admin authority, returning 401 Forbidden error...");
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
}
else
{
if (logger.isWarnEnabled())
logger.warn("Access denied to '" + httpRequest.getRequestURI() +
"'. The response has already been committed so a 401 Forbidden error could not be sent!");
}
}
}
/**
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig config) throws ServletException
{
this.config = config;
}
/**
* @see javax.servlet.Filter#destroy()
*/
public void destroy()
{
// nothing to do
}
}

View File

@@ -1,56 +1,56 @@
package org.alfresco.web.app.servlet;
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;
import org.alfresco.web.scripts.servlet.X509ServletFilterBase;
import javax.servlet.*;
import java.io.IOException;
import java.util.Properties;
/**
* The AlfrescoX509ServletFilter implements the checkEnforce method of the X509ServletFilterBase.
* This allows the configuration of X509 authentication to be toggled on/off through a
* configuration outside of the web.xml.
**/
public class AlfrescoX509ServletFilter extends X509ServletFilterBase
{
private static final String BEAN_GLOBAL_PROPERTIES = "global-properties";
private static final String SECURE_COMMS = "solr.secureComms";
private static Log logger = LogFactory.getLog(AlfrescoX509ServletFilter.class);
@Override
protected boolean checkEnforce(ServletContext servletContext) throws IOException
{
/*
* Get the secureComms setting from the global properties bean.
*/
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
Properties globalProperties = (Properties) wc.getBean(BEAN_GLOBAL_PROPERTIES);
String prop = globalProperties.getProperty(SECURE_COMMS);
if(logger.isDebugEnabled())
{
logger.debug("secureComms:"+prop);
}
/*
* Return true or false based on the property. This will switch on/off X509 enforcement in the X509ServletFilterBase.
*/
if (prop == null || "none".equals(prop))
{
return false;
}
else
{
return true;
}
}
package org.alfresco.web.app.servlet;
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;
import org.alfresco.web.scripts.servlet.X509ServletFilterBase;
import javax.servlet.*;
import java.io.IOException;
import java.util.Properties;
/**
* The AlfrescoX509ServletFilter implements the checkEnforce method of the X509ServletFilterBase.
* This allows the configuration of X509 authentication to be toggled on/off through a
* configuration outside of the web.xml.
**/
public class AlfrescoX509ServletFilter extends X509ServletFilterBase
{
private static final String BEAN_GLOBAL_PROPERTIES = "global-properties";
private static final String SECURE_COMMS = "solr.secureComms";
private static Log logger = LogFactory.getLog(AlfrescoX509ServletFilter.class);
@Override
protected boolean checkEnforce(ServletContext servletContext) throws IOException
{
/*
* Get the secureComms setting from the global properties bean.
*/
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
Properties globalProperties = (Properties) wc.getBean(BEAN_GLOBAL_PROPERTIES);
String prop = globalProperties.getProperty(SECURE_COMMS);
if(logger.isDebugEnabled())
{
logger.debug("secureComms:"+prop);
}
/*
* Return true or false based on the property. This will switch on/off X509 enforcement in the X509ServletFilterBase.
*/
if (prop == null || "none".equals(prop))
{
return false;
}
else
{
return true;
}
}
}

View File

@@ -1,9 +1,9 @@
package org.alfresco.web.app.servlet;
/**
* @author Kevin Roast
*/
public enum AuthenticationStatus
{
Success, Failure, Guest;
}
package org.alfresco.web.app.servlet;
/**
* @author Kevin Roast
*/
public enum AuthenticationStatus
{
Success, Failure, Guest;
}

View File

@@ -1,430 +1,430 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.net.SocketException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.web.util.HttpRangeProcessor;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.MimetypeService;
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.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.apache.commons.logging.Log;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.extensions.surf.util.URLEncoder;
import org.springframework.extensions.webscripts.ui.common.StringUtils;
/**
* Base class for the download content servlets. Provides common
* processing for the request.
*
* @see org.alfresco.web.app.servlet.DownloadContentServlet
* @see org.alfresco.web.app.servlet.GuestDownloadContentServlet
*
* @author Kevin Roast
* @author gavinc
*/
public abstract class BaseDownloadContentServlet extends BaseServlet
{
private static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
private static final long serialVersionUID = -4558907921887235967L;
private static final String POWER_POINT_DOCUMENT_MIMETYPE = "application/vnd.ms-powerpoint";
private static final String POWER_POINT_2007_DOCUMENT_MIMETYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
private static final String HEADER_CONTENT_RANGE = "Content-Range";
private static final String HEADER_CONTENT_LENGTH = "Content-Length";
private static final String HEADER_ACCEPT_RANGES = "Accept-Ranges";
private static final String HEADER_RANGE = "Range";
private static final String HEADER_ETAG = "ETag";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
private static final String HEADER_LAST_MODIFIED = "Last-Modified";
private static final String HEADER_USER_AGENT = "User-Agent";
private static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
protected static final String MIMETYPE_OCTET_STREAM = "application/octet-stream";
protected static final String MSG_ERROR_CONTENT_MISSING = "error_content_missing";
protected static final String MSG_ERROR_NOT_FOUND = "error_not_found";
protected static final String URL_DIRECT = "d";
protected static final String URL_DIRECT_LONG = "direct";
protected static final String URL_ATTACH = "a";
protected static final String URL_ATTACH_LONG = "attach";
protected static final String ARG_PROPERTY = "property";
protected static final String ARG_PATH = "path";
/**
* Gets the logger to use for this request.
* <p>
* This will show all debug entries from this class as though they
* came from the subclass.
*
* @return The logger
*/
protected abstract Log getLogger();
/**
* Processes the download 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 allowLogIn
* Indicates whether guest users without access to the content should be redirected to the log in page. If
* <code>false</code>, a status 403 forbidden page is displayed instead.
*/
protected void processDownloadRequest(HttpServletRequest req, HttpServletResponse res,
boolean allowLogIn, boolean transmitContent)
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
// attachment mode (either 'attach' or 'direct')
String attachToken = t.nextToken();
boolean attachment = URL_ATTACH.equals(attachToken) || URL_ATTACH_LONG.equals(attachToken);
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
// get or calculate the noderef and filename to download as
NodeRef nodeRef;
String filename;
// do we have a path parameter instead of a NodeRef?
String path = req.getParameter(ARG_PATH);
if (path != null && path.length() != 0)
{
// process the name based path to resolve the NodeRef and the Filename element
try
{
PathRefInfo pathInfo = resolveNamePath(getServletContext(), path);
nodeRef = pathInfo.NodeRef;
filename = pathInfo.Filename;
}
catch (IllegalArgumentException e)
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
}
else
{
// a NodeRef must have been specified if no path has been found
if (tokenCount < 6)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
// assume 'workspace' or other NodeRef based protocol for remaining URL elements
StoreRef storeRef = new StoreRef(URLDecoder.decode(t.nextToken()), URLDecoder.decode(t.nextToken()));
String id = URLDecoder.decode(t.nextToken());
// build noderef from the appropriate URL elements
nodeRef = new NodeRef(storeRef, id);
if (tokenCount > 6)
{
// found additional relative path elements i.e. noderefid/images/file.txt
// this allows a url to reference siblings nodes via a cm:name based relative path
// solves the issue with opening HTML content containing relative URLs in HREF or IMG tags etc.
List<String> paths = new ArrayList<String>(tokenCount - 5);
while (t.hasMoreTokens())
{
paths.add(URLDecoder.decode(t.nextToken()));
}
filename = paths.get(paths.size() - 1);
try
{
NodeRef parentRef = serviceRegistry.getNodeService().getPrimaryParent(nodeRef).getParentRef();
FileInfo fileInfo = serviceRegistry.getFileFolderService().resolveNamePath(parentRef, paths);
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
}
else
{
// filename is last remaining token
filename = t.nextToken();
}
}
// get qualified of the property to get content from - default to ContentModel.PROP_CONTENT
QName propertyQName = ContentModel.PROP_CONTENT;
String property = req.getParameter(ARG_PROPERTY);
if (property != null && property.length() != 0)
{
propertyQName = QName.createQName(property);
}
if (logger.isDebugEnabled())
{
logger.debug("Found NodeRef: " + nodeRef);
logger.debug("Will use filename: " + filename);
logger.debug("For property: " + propertyQName);
logger.debug("With attachment mode: " + attachment);
}
// get the services we need to retrieve the content
NodeService nodeService = serviceRegistry.getNodeService();
ContentService contentService = serviceRegistry.getContentService();
// Check that the node still exists
if (!nodeService.exists(nodeRef))
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
try
{
// check that the user has at least READ_CONTENT access - else redirect to an error or login page
if (!checkAccess(req, res, nodeRef, PermissionService.READ_CONTENT, allowLogIn))
{
return;
}
// check If-Modified-Since header and set Last-Modified header as appropriate
Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
if (modified != null)
{
long modifiedSince = req.getDateHeader(HEADER_IF_MODIFIED_SINCE);
if (modifiedSince > 0L)
{
// round the date to the ignore millisecond value which is not supplied by header
long modDate = (modified.getTime() / 1000L) * 1000L;
if (modDate <= modifiedSince)
{
if (logger.isDebugEnabled())
logger.debug("Returning 304 Not Modified.");
res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
}
res.setDateHeader(HEADER_LAST_MODIFIED, modified.getTime());
res.setHeader(HEADER_CACHE_CONTROL, "must-revalidate, max-age=0");
res.setHeader(HEADER_ETAG, "\"" + Long.toString(modified.getTime()) + "\"");
}
if (attachment == true)
{
setHeaderContentDisposition(req, res, filename);
}
// get the content reader
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
// ensure that it is safe to use
reader = FileContentReader.getSafeContentReader(
reader,
Application.getMessage(req.getSession(), MSG_ERROR_CONTENT_MISSING),
nodeRef, reader);
String mimetype = reader.getMimetype();
// fall back if unable to resolve mimetype property
if (mimetype == null || mimetype.length() == 0)
{
MimetypeService mimetypeMap = serviceRegistry.getMimetypeService();
mimetype = MIMETYPE_OCTET_STREAM;
int extIndex = filename.lastIndexOf('.');
if (extIndex != -1)
{
String ext = filename.substring(extIndex + 1);
mimetype = mimetypeMap.getMimetype(ext);
}
}
// explicitly set the content disposition header if the content is powerpoint
if (!attachment && (mimetype.equals(POWER_POINT_2007_DOCUMENT_MIMETYPE) ||
mimetype.equals(POWER_POINT_DOCUMENT_MIMETYPE)))
{
setHeaderContentDisposition(req, res, filename);
}
// get the content and stream 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.
res.setHeader(HEADER_ACCEPT_RANGES, "bytes");
// for a GET request, transmit the content else just the headers are sent
if (transmitContent)
{
try
{
boolean processedRange = false;
String range = req.getHeader(HEADER_CONTENT_RANGE);
if (range == null)
{
range = req.getHeader(HEADER_RANGE);
}
if (range != null)
{
if (logger.isDebugEnabled())
logger.debug("Found content range header: " + range);
// ensure the range header is starts with "bytes=" and process the range(s)
if (range.length() > 6)
{
HttpRangeProcessor rangeProcessor = new HttpRangeProcessor(contentService);
processedRange = rangeProcessor.processRange(
res, reader, range.substring(6), nodeRef, propertyQName,
mimetype, req.getHeader(HEADER_USER_AGENT));
}
}
if (processedRange == false)
{
if (logger.isDebugEnabled())
logger.debug("Sending complete file content...");
// set mimetype for the content and the character encoding for the stream
res.setContentType(mimetype);
res.setCharacterEncoding(reader.getEncoding());
// MNT-10642 Alfresco Explorer has javascript vulnerability opening HTML files
if (req.getRequestURI().contains("/d/d/") && (mimetype.equals("text/html") || mimetype.equals("application/xhtml+xml") || mimetype.equals("text/xml")))
{
String content = reader.getContentString();
if (mimetype.equals("text/html") || mimetype.equals("application/xhtml+xml"))
{
// process with HTML stripper
content = StringUtils.stripUnsafeHTMLTags(content, false);
}
else if (mimetype.equals("text/xml") && mimetype.equals("text/x-component"))
{
// IE supports "behaviour" which means that css can load a .htc file that could
// contain XSS code in the form of jscript, vbscript etc, to stop it form being
// evaluated we set the contient type to text/plain
res.setContentType("text/plain");
}
String encoding = reader.getEncoding();
byte[] bytes = encoding != null ? content.getBytes(encoding) : content.getBytes();
res.setContentLength(bytes.length);
res.getOutputStream().write(bytes);
return;
}
// return the complete entity range
long size = reader.getSize();
res.setHeader(HEADER_CONTENT_RANGE, "bytes 0-" + Long.toString(size-1L) + "/" + Long.toString(size));
res.setHeader(HEADER_CONTENT_LENGTH, Long.toString(size));
reader.getContent( res.getOutputStream() );
}
}
catch (SocketException e1)
{
// the client cut the connection - our mission was accomplished apart from a little error message
if (logger.isDebugEnabled())
logger.debug("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
}
catch (ContentIOException e2)
{
if (logger.isInfoEnabled())
logger.info("Failed stream read:\n\tnode: " + nodeRef + " due to: " + e2.getMessage());
}
catch (Throwable err)
{
if (err.getCause() instanceof SocketException)
{
// the client cut the connection - our mission was accomplished apart from a little error message
if (logger.isDebugEnabled())
logger.debug("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
}
else throw err;
}
}
else
{
if (logger.isDebugEnabled())
logger.debug("HEAD request processed - no content sent.");
res.getOutputStream().close();
}
}
catch (Throwable err)
{
throw new AlfrescoRuntimeException("Error during download content servlet processing: " + err.getMessage(), err);
}
}
private void setHeaderContentDisposition(HttpServletRequest req, HttpServletResponse res, String filename)
{
// set header based on filename - will force a Save As from the browse if it doesn't recognise it
// this is better than the default response of the browser trying to display the contents
// IE requires that "Content-Disposition" header in case of "attachment" type should include
// "filename" part. See MNT-9900
String userAgent = req.getHeader(HEADER_USER_AGENT);
if (userAgent != null && (userAgent.toLowerCase().contains("firefox") || userAgent.toLowerCase().contains("safari")))
{
res.setHeader(HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + URLDecoder.decode(filename) + "\"");
}
else
{
res.setHeader(HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"");
}
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
*
* @param pattern The pattern to use for the URL
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
protected final static String generateUrl(String pattern, NodeRef ref, String name)
{
return MessageFormat.format(pattern, new Object[] {
ref.getStoreRef().getProtocol(),
ref.getStoreRef().getIdentifier(),
ref.getId(),
URLEncoder.encode(name) } );
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.net.SocketException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.web.util.HttpRangeProcessor;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.MimetypeService;
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.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.apache.commons.logging.Log;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.extensions.surf.util.URLEncoder;
import org.springframework.extensions.webscripts.ui.common.StringUtils;
/**
* Base class for the download content servlets. Provides common
* processing for the request.
*
* @see org.alfresco.web.app.servlet.DownloadContentServlet
* @see org.alfresco.web.app.servlet.GuestDownloadContentServlet
*
* @author Kevin Roast
* @author gavinc
*/
public abstract class BaseDownloadContentServlet extends BaseServlet
{
private static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
private static final long serialVersionUID = -4558907921887235967L;
private static final String POWER_POINT_DOCUMENT_MIMETYPE = "application/vnd.ms-powerpoint";
private static final String POWER_POINT_2007_DOCUMENT_MIMETYPE = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
private static final String HEADER_CONTENT_RANGE = "Content-Range";
private static final String HEADER_CONTENT_LENGTH = "Content-Length";
private static final String HEADER_ACCEPT_RANGES = "Accept-Ranges";
private static final String HEADER_RANGE = "Range";
private static final String HEADER_ETAG = "ETag";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
private static final String HEADER_LAST_MODIFIED = "Last-Modified";
private static final String HEADER_USER_AGENT = "User-Agent";
private static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
protected static final String MIMETYPE_OCTET_STREAM = "application/octet-stream";
protected static final String MSG_ERROR_CONTENT_MISSING = "error_content_missing";
protected static final String MSG_ERROR_NOT_FOUND = "error_not_found";
protected static final String URL_DIRECT = "d";
protected static final String URL_DIRECT_LONG = "direct";
protected static final String URL_ATTACH = "a";
protected static final String URL_ATTACH_LONG = "attach";
protected static final String ARG_PROPERTY = "property";
protected static final String ARG_PATH = "path";
/**
* Gets the logger to use for this request.
* <p>
* This will show all debug entries from this class as though they
* came from the subclass.
*
* @return The logger
*/
protected abstract Log getLogger();
/**
* Processes the download 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 allowLogIn
* Indicates whether guest users without access to the content should be redirected to the log in page. If
* <code>false</code>, a status 403 forbidden page is displayed instead.
*/
protected void processDownloadRequest(HttpServletRequest req, HttpServletResponse res,
boolean allowLogIn, boolean transmitContent)
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
// attachment mode (either 'attach' or 'direct')
String attachToken = t.nextToken();
boolean attachment = URL_ATTACH.equals(attachToken) || URL_ATTACH_LONG.equals(attachToken);
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
// get or calculate the noderef and filename to download as
NodeRef nodeRef;
String filename;
// do we have a path parameter instead of a NodeRef?
String path = req.getParameter(ARG_PATH);
if (path != null && path.length() != 0)
{
// process the name based path to resolve the NodeRef and the Filename element
try
{
PathRefInfo pathInfo = resolveNamePath(getServletContext(), path);
nodeRef = pathInfo.NodeRef;
filename = pathInfo.Filename;
}
catch (IllegalArgumentException e)
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
}
else
{
// a NodeRef must have been specified if no path has been found
if (tokenCount < 6)
{
throw new IllegalArgumentException("Download URL did not contain all required args: " + uri);
}
// assume 'workspace' or other NodeRef based protocol for remaining URL elements
StoreRef storeRef = new StoreRef(URLDecoder.decode(t.nextToken()), URLDecoder.decode(t.nextToken()));
String id = URLDecoder.decode(t.nextToken());
// build noderef from the appropriate URL elements
nodeRef = new NodeRef(storeRef, id);
if (tokenCount > 6)
{
// found additional relative path elements i.e. noderefid/images/file.txt
// this allows a url to reference siblings nodes via a cm:name based relative path
// solves the issue with opening HTML content containing relative URLs in HREF or IMG tags etc.
List<String> paths = new ArrayList<String>(tokenCount - 5);
while (t.hasMoreTokens())
{
paths.add(URLDecoder.decode(t.nextToken()));
}
filename = paths.get(paths.size() - 1);
try
{
NodeRef parentRef = serviceRegistry.getNodeService().getPrimaryParent(nodeRef).getParentRef();
FileInfo fileInfo = serviceRegistry.getFileFolderService().resolveNamePath(parentRef, paths);
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
}
else
{
// filename is last remaining token
filename = t.nextToken();
}
}
// get qualified of the property to get content from - default to ContentModel.PROP_CONTENT
QName propertyQName = ContentModel.PROP_CONTENT;
String property = req.getParameter(ARG_PROPERTY);
if (property != null && property.length() != 0)
{
propertyQName = QName.createQName(property);
}
if (logger.isDebugEnabled())
{
logger.debug("Found NodeRef: " + nodeRef);
logger.debug("Will use filename: " + filename);
logger.debug("For property: " + propertyQName);
logger.debug("With attachment mode: " + attachment);
}
// get the services we need to retrieve the content
NodeService nodeService = serviceRegistry.getNodeService();
ContentService contentService = serviceRegistry.getContentService();
// Check that the node still exists
if (!nodeService.exists(nodeRef))
{
Application.handleSystemError(getServletContext(), req, res, MSG_ERROR_NOT_FOUND,
HttpServletResponse.SC_NOT_FOUND, logger);
return;
}
try
{
// check that the user has at least READ_CONTENT access - else redirect to an error or login page
if (!checkAccess(req, res, nodeRef, PermissionService.READ_CONTENT, allowLogIn))
{
return;
}
// check If-Modified-Since header and set Last-Modified header as appropriate
Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
if (modified != null)
{
long modifiedSince = req.getDateHeader(HEADER_IF_MODIFIED_SINCE);
if (modifiedSince > 0L)
{
// round the date to the ignore millisecond value which is not supplied by header
long modDate = (modified.getTime() / 1000L) * 1000L;
if (modDate <= modifiedSince)
{
if (logger.isDebugEnabled())
logger.debug("Returning 304 Not Modified.");
res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
}
res.setDateHeader(HEADER_LAST_MODIFIED, modified.getTime());
res.setHeader(HEADER_CACHE_CONTROL, "must-revalidate, max-age=0");
res.setHeader(HEADER_ETAG, "\"" + Long.toString(modified.getTime()) + "\"");
}
if (attachment == true)
{
setHeaderContentDisposition(req, res, filename);
}
// get the content reader
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
// ensure that it is safe to use
reader = FileContentReader.getSafeContentReader(
reader,
Application.getMessage(req.getSession(), MSG_ERROR_CONTENT_MISSING),
nodeRef, reader);
String mimetype = reader.getMimetype();
// fall back if unable to resolve mimetype property
if (mimetype == null || mimetype.length() == 0)
{
MimetypeService mimetypeMap = serviceRegistry.getMimetypeService();
mimetype = MIMETYPE_OCTET_STREAM;
int extIndex = filename.lastIndexOf('.');
if (extIndex != -1)
{
String ext = filename.substring(extIndex + 1);
mimetype = mimetypeMap.getMimetype(ext);
}
}
// explicitly set the content disposition header if the content is powerpoint
if (!attachment && (mimetype.equals(POWER_POINT_2007_DOCUMENT_MIMETYPE) ||
mimetype.equals(POWER_POINT_DOCUMENT_MIMETYPE)))
{
setHeaderContentDisposition(req, res, filename);
}
// get the content and stream 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.
res.setHeader(HEADER_ACCEPT_RANGES, "bytes");
// for a GET request, transmit the content else just the headers are sent
if (transmitContent)
{
try
{
boolean processedRange = false;
String range = req.getHeader(HEADER_CONTENT_RANGE);
if (range == null)
{
range = req.getHeader(HEADER_RANGE);
}
if (range != null)
{
if (logger.isDebugEnabled())
logger.debug("Found content range header: " + range);
// ensure the range header is starts with "bytes=" and process the range(s)
if (range.length() > 6)
{
HttpRangeProcessor rangeProcessor = new HttpRangeProcessor(contentService);
processedRange = rangeProcessor.processRange(
res, reader, range.substring(6), nodeRef, propertyQName,
mimetype, req.getHeader(HEADER_USER_AGENT));
}
}
if (processedRange == false)
{
if (logger.isDebugEnabled())
logger.debug("Sending complete file content...");
// set mimetype for the content and the character encoding for the stream
res.setContentType(mimetype);
res.setCharacterEncoding(reader.getEncoding());
// MNT-10642 Alfresco Explorer has javascript vulnerability opening HTML files
if (req.getRequestURI().contains("/d/d/") && (mimetype.equals("text/html") || mimetype.equals("application/xhtml+xml") || mimetype.equals("text/xml")))
{
String content = reader.getContentString();
if (mimetype.equals("text/html") || mimetype.equals("application/xhtml+xml"))
{
// process with HTML stripper
content = StringUtils.stripUnsafeHTMLTags(content, false);
}
else if (mimetype.equals("text/xml") && mimetype.equals("text/x-component"))
{
// IE supports "behaviour" which means that css can load a .htc file that could
// contain XSS code in the form of jscript, vbscript etc, to stop it form being
// evaluated we set the contient type to text/plain
res.setContentType("text/plain");
}
String encoding = reader.getEncoding();
byte[] bytes = encoding != null ? content.getBytes(encoding) : content.getBytes();
res.setContentLength(bytes.length);
res.getOutputStream().write(bytes);
return;
}
// return the complete entity range
long size = reader.getSize();
res.setHeader(HEADER_CONTENT_RANGE, "bytes 0-" + Long.toString(size-1L) + "/" + Long.toString(size));
res.setHeader(HEADER_CONTENT_LENGTH, Long.toString(size));
reader.getContent( res.getOutputStream() );
}
}
catch (SocketException e1)
{
// the client cut the connection - our mission was accomplished apart from a little error message
if (logger.isDebugEnabled())
logger.debug("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
}
catch (ContentIOException e2)
{
if (logger.isInfoEnabled())
logger.info("Failed stream read:\n\tnode: " + nodeRef + " due to: " + e2.getMessage());
}
catch (Throwable err)
{
if (err.getCause() instanceof SocketException)
{
// the client cut the connection - our mission was accomplished apart from a little error message
if (logger.isDebugEnabled())
logger.debug("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
}
else throw err;
}
}
else
{
if (logger.isDebugEnabled())
logger.debug("HEAD request processed - no content sent.");
res.getOutputStream().close();
}
}
catch (Throwable err)
{
throw new AlfrescoRuntimeException("Error during download content servlet processing: " + err.getMessage(), err);
}
}
private void setHeaderContentDisposition(HttpServletRequest req, HttpServletResponse res, String filename)
{
// set header based on filename - will force a Save As from the browse if it doesn't recognise it
// this is better than the default response of the browser trying to display the contents
// IE requires that "Content-Disposition" header in case of "attachment" type should include
// "filename" part. See MNT-9900
String userAgent = req.getHeader(HEADER_USER_AGENT);
if (userAgent != null && (userAgent.toLowerCase().contains("firefox") || userAgent.toLowerCase().contains("safari")))
{
res.setHeader(HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + URLDecoder.decode(filename) + "\"");
}
else
{
res.setHeader(HEADER_CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"");
}
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
*
* @param pattern The pattern to use for the URL
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
protected final static String generateUrl(String pattern, NodeRef ref, String name)
{
return MessageFormat.format(pattern, new Object[] {
ref.getStoreRef().getProtocol(),
ref.getStoreRef().getIdentifier(),
ref.getId(),
URLEncoder.encode(name) } );
}
}

View File

@@ -1,481 +1,481 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginOutcomeBean;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.jsf.FacesContextUtils;
/**
* Base servlet class containing useful constant values and common methods for Alfresco servlets.
*
* @author Kevin Roast
*/
public abstract class BaseServlet extends HttpServlet
{
private static final long serialVersionUID = -826295358696861789L;
public static final String FACES_SERVLET = "/faces";
public static final String KEY_STORE = "store";
public static final String KEY_ROOT_PATH = "rootPath";
/** an existing Ticket can be passed to most servlet for non-session based authentication */
private static final String ARG_TICKET = "ticket";
/** forcing guess access is available on most servlets */
private static final String ARG_GUEST = "guest";
private static final String MSG_ERROR_PERMISSIONS = "error_permissions";
/** list of valid JSPs for redirect after a clean login */
// TODO: make this list configurable
private static Set<String> validRedirectJSPs = new HashSet<String>();
static
{
validRedirectJSPs.add("/jsp/browse/browse.jsp");
validRedirectJSPs.add("/jsp/admin/admin-console.jsp");
validRedirectJSPs.add("/jsp/admin/avm-console.jsp");
validRedirectJSPs.add("/jsp/admin/node-browser.jsp");
validRedirectJSPs.add("/jsp/admin/store-browser.jsp");
validRedirectJSPs.add("/jsp/users/user-console.jsp");
validRedirectJSPs.add("/jsp/categories/categories.jsp");
validRedirectJSPs.add("/jsp/dialog/about.jsp");
validRedirectJSPs.add("/jsp/search/advanced-search.jsp");
validRedirectJSPs.add("/jsp/admin/system-info.jsp");
validRedirectJSPs.add("/jsp/forums/forums.jsp");
validRedirectJSPs.add("/jsp/users/users.jsp");
validRedirectJSPs.add("/jsp/trashcan/trash-list.jsp");
}
private static Log logger = LogFactory.getLog(BaseServlet.class);
/**
* Return the ServiceRegistry helper instance
*
* @param sc ServletContext
*
* @return ServiceRegistry
*/
public static ServiceRegistry getServiceRegistry(ServletContext sc)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
return (ServiceRegistry)wc.getBean(ServiceRegistry.SERVICE_REGISTRY);
}
/**
* Perform an authentication for the servlet request URI. Processing any "ticket" or
* "guest" URL arguments.
*
* @return AuthenticationStatus
*
* @throws IOException
*/
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res)
throws IOException
{
return servletAuthenticate(req, res, true);
}
/**
* Perform an authentication for the servlet request URI. Processing any "ticket" or
* "guest" URL arguments.
*
* @return AuthenticationStatus
*
* @throws IOException
*/
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res,
boolean redirectToLoginPage) throws IOException
{
AuthenticationStatus status;
// see if a ticket or a force Guest parameter has been supplied
String ticket = req.getParameter(ARG_TICKET);
if (ticket != null && ticket.length() != 0)
{
status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket);
}
else
{
boolean forceGuest = false;
String guest = req.getParameter(ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
}
if (status == AuthenticationStatus.Failure && redirectToLoginPage)
{
// authentication failed - now need to display the login page to the user, if asked to
redirectToLoginPage(req, res, getServletContext());
}
return status;
}
/**
* Check the user has the given permission on the given node. If they do not either force a log on if this is a guest
* user or forward to an error page.
*
* @param req
* the request
* @param res
* the response
* @param nodeRef
* the node in question
* @param allowLogIn
* Indicates whether guest users without access to the node should be redirected to the log in page. If
* <code>false</code>, a status 403 forbidden page is displayed instead.
* @return <code>true</code>, if the user has access
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* On other errors
*/
public boolean checkAccess(HttpServletRequest req, HttpServletResponse res, NodeRef nodeRef, String permission,
boolean allowLogIn) throws IOException, ServletException
{
ServletContext sc = getServletContext();
ServiceRegistry serviceRegistry = getServiceRegistry(sc);
PermissionService permissionService = serviceRegistry.getPermissionService();
// check that the user has the permission
if (permissionService.hasPermission(nodeRef, permission) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled())
logger.debug("User does not have " + permission + " permission for NodeRef: " + nodeRef.toString());
if (allowLogIn && serviceRegistry.getAuthorityService().hasGuestAuthority())
{
if (logger.isDebugEnabled())
logger.debug("Redirecting to login page...");
redirectToLoginPage(req, res, sc);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Forwarding to error page...");
Application
.handleSystemError(sc, req, res, MSG_ERROR_PERMISSIONS, HttpServletResponse.SC_FORBIDDEN, logger);
}
return false;
}
return true;
}
/**
* Redirect to the Login page - saving the current URL which can be redirected back later
* once the user has successfully completed the authentication process.
*/
public static void redirectToLoginPage(HttpServletRequest req, HttpServletResponse res, ServletContext sc)
throws IOException
{
redirectToLoginPage(req, res, sc, AuthenticationHelper.getRemoteUserMapper(sc) == null);
}
/**
* Redirect to the Login page - saving the current URL which can be redirected back later
* once the user has successfully completed the authentication process.
* @param sendRedirect allow a redirect status code to be set? If <code>false</code> redirect
* will be via markup rather than status code (to allow the status code to be used for handshake
* responses etc.
*/
public static void redirectToLoginPage(HttpServletRequest req, HttpServletResponse res, ServletContext sc, boolean sendRedirect)
throws IOException
{
// Pass the full requested URL as a parameter so the login page knows where to redirect to later
final String uri = req.getRequestURI();
String redirectURL = uri;
// authentication failed - so end servlet execution and redirect to login page
if (WebApplicationContextUtils.getRequiredWebApplicationContext(sc).containsBean(Application.BEAN_CONFIG_SERVICE))
{
StringBuilder redirect = new StringBuilder(128)
.append(req.getContextPath()).append(FACES_SERVLET).append(Application.getLoginPage(sc));
// if we find a JSF servlet reference in the URI then we need to check if the rest of the
// JSP specified is valid for a redirect operation after Login has occured.
int jspIndex;
if (uri.indexOf(req.getContextPath() + FACES_SERVLET) == -1
|| uri.length() > (jspIndex = uri.indexOf(BaseServlet.FACES_SERVLET) + BaseServlet.FACES_SERVLET.length())
&& BaseServlet.validRedirectJSP(uri.substring(jspIndex)))
{
if (redirect.indexOf("?") == -1)
{
redirect.append('?');
}
else
{
redirect.append('&');
}
redirect.append(LoginOutcomeBean.PARAM_REDIRECT_URL);
redirect.append('=');
String url = uri;
// Append the query string if necessary
String queryString = req.getQueryString();
if (queryString != null)
{
// Strip out leading ticket arguments
queryString = queryString.replaceAll("(?<=^|&)" + ARG_TICKET + "(=[^&=]*)?&", "");
// Strip out trailing ticket arguments
queryString = queryString.replaceAll("(^|&)" + ARG_TICKET + "(=[^&=]*)?(?=&|$)", "");
if (queryString.length() != 0)
{
url += "?" + queryString;
}
}
redirect.append(URLEncoder.encode(url, "UTF-8"));
}
redirectURL = redirect.toString();
}
// If external authentication isn't in use (e.g. proxied share authentication), it's safe to return a redirect to the client
if (sendRedirect)
{
res.sendRedirect(redirectURL);
}
// Otherwise, we must signal to the client with an unauthorized status code and rely on a browser refresh to do
// the redirect for failover login (as we do with NTLM, Kerberos)
else
{
res.setContentType("text/html; charset=UTF-8");
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final PrintWriter out = res.getWriter();
out.println("<html><head>");
out.println("<meta http-equiv=\"Refresh\" content=\"0; url=" + redirectURL + "\">");
out.println("</head><body><p>Please <a href=\"" + redirectURL + "\">log in</a>.</p>");
out.println("</body></html>");
out.close();
}
}
/**
* Apply the headers required to disallow caching of the response in the browser
*/
public static void setNoCacheHeaders(HttpServletResponse res)
{
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Pragma", "no-cache");
}
/**
* Returns true if the specified JSP file is valid for a redirect after login.
* Only a specific sub-set of the available JSPs are valid to jump directly too after a
* clean login attempt - e.g. those that do not require JSF bean context setup. This is
* a limitation of the JSP architecture. The ExternalAccessServlet provides a mechanism to
* setup the JSF bean context directly for some specific cases.
*
* @param jsp Filename of JSP to check, for example "/jsp/browse/browse.jsp"
*
* @return true if the JSP is in the list of valid direct URLs, false otherwise
*/
public static boolean validRedirectJSP(String jsp)
{
return validRedirectJSPs.contains(jsp);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
*/
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args)
{
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, true);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args, boolean decode)
{
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, decode);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context ServletContext context
* @param args The elements of the path to lookup
*/
public static NodeRef resolveWebDAVPath(ServletContext context, String[] args)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, true);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context ServletContext context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
public static NodeRef resolveWebDAVPath(ServletContext context, String[] args, boolean decode)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, decode);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param wc WebApplicationContext Context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
private static NodeRef resolveWebDAVPath(final WebApplicationContext wc, final String[] args, final boolean decode)
{
return AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
{
public NodeRef doWork() throws Exception
{
NodeRef nodeRef = null;
List<String> paths = new ArrayList<String>(args.length - 1);
FileInfo file = null;
try
{
// create a list of path elements (decode the URL as we go)
for (int x = 1; x < args.length; x++)
{
paths.add(decode ? URLDecoder.decode(args[x]) : args[x]);
}
if (logger.isDebugEnabled())
logger.debug("Attempting to resolve webdav path: " + paths);
// get the company home node to start the search from
nodeRef = new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId());
TenantService tenantService = (TenantService)wc.getBean("tenantService");
if (tenantService != null && tenantService.isEnabled())
{
if (logger.isDebugEnabled())
logger.debug("MT is enabled.");
NodeService nodeService = (NodeService) wc.getBean("NodeService");
SearchService searchService = (SearchService) wc.getBean("SearchService");
NamespaceService namespaceService = (NamespaceService) wc.getBean("NamespaceService");
// TODO: since these constants are used more widely than just the WebDAVServlet,
// they should be defined somewhere other than in that servlet
String rootPath = wc.getServletContext().getInitParameter(BaseServlet.KEY_ROOT_PATH);
// note: rootNodeRef is required (for storeRef part)
nodeRef = tenantService.getRootNode(nodeService, searchService, namespaceService, rootPath, nodeRef);
}
if (paths.size() != 0)
{
FileFolderService ffs = (FileFolderService)wc.getBean("FileFolderService");
file = ffs.resolveNamePath(nodeRef, paths);
nodeRef = file.getNodeRef();
}
if (logger.isDebugEnabled())
logger.debug("Resolved webdav path to NodeRef: " + nodeRef);
}
catch (FileNotFoundException fne)
{
if (logger.isWarnEnabled())
logger.warn("Failed to resolve webdav path", fne);
nodeRef = null;
}
return nodeRef;
}
}, AuthenticationUtil.getSystemUserName());
}
/**
* Resolve a name based into a NodeRef and Filename string
*
* @param sc ServletContext
* @param path 'cm:name' based path using the '/' character as a separator
*
* @return PathRefInfo structure containing the resolved NodeRef and filename
*
* @throws IllegalArgumentException
*/
public final static PathRefInfo resolveNamePath(ServletContext sc, String path)
{
StringTokenizer t = new StringTokenizer(path, "/");
int tokenCount = t.countTokens();
String[] elements = new String[tokenCount];
for (int i=0; i<tokenCount; i++)
{
elements[i] = t.nextToken();
}
// process name based path tokens using the webdav path resolving helper
NodeRef nodeRef = resolveWebDAVPath(sc, elements, false);
if (nodeRef == null)
{
// unable to resolve path - output helpful error to the user
throw new IllegalArgumentException("Unable to resolve item Path: " + path);
}
return new PathRefInfo(nodeRef, elements[tokenCount - 1]);
}
/**
* Simple structure class for returning both a NodeRef and Filename String
* @author Kevin Roast
*/
public static class PathRefInfo
{
PathRefInfo(NodeRef ref, String filename)
{
this.NodeRef = ref;
this.Filename = filename;
}
public NodeRef NodeRef;
public String Filename;
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.LoginOutcomeBean;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.jsf.FacesContextUtils;
/**
* Base servlet class containing useful constant values and common methods for Alfresco servlets.
*
* @author Kevin Roast
*/
public abstract class BaseServlet extends HttpServlet
{
private static final long serialVersionUID = -826295358696861789L;
public static final String FACES_SERVLET = "/faces";
public static final String KEY_STORE = "store";
public static final String KEY_ROOT_PATH = "rootPath";
/** an existing Ticket can be passed to most servlet for non-session based authentication */
private static final String ARG_TICKET = "ticket";
/** forcing guess access is available on most servlets */
private static final String ARG_GUEST = "guest";
private static final String MSG_ERROR_PERMISSIONS = "error_permissions";
/** list of valid JSPs for redirect after a clean login */
// TODO: make this list configurable
private static Set<String> validRedirectJSPs = new HashSet<String>();
static
{
validRedirectJSPs.add("/jsp/browse/browse.jsp");
validRedirectJSPs.add("/jsp/admin/admin-console.jsp");
validRedirectJSPs.add("/jsp/admin/avm-console.jsp");
validRedirectJSPs.add("/jsp/admin/node-browser.jsp");
validRedirectJSPs.add("/jsp/admin/store-browser.jsp");
validRedirectJSPs.add("/jsp/users/user-console.jsp");
validRedirectJSPs.add("/jsp/categories/categories.jsp");
validRedirectJSPs.add("/jsp/dialog/about.jsp");
validRedirectJSPs.add("/jsp/search/advanced-search.jsp");
validRedirectJSPs.add("/jsp/admin/system-info.jsp");
validRedirectJSPs.add("/jsp/forums/forums.jsp");
validRedirectJSPs.add("/jsp/users/users.jsp");
validRedirectJSPs.add("/jsp/trashcan/trash-list.jsp");
}
private static Log logger = LogFactory.getLog(BaseServlet.class);
/**
* Return the ServiceRegistry helper instance
*
* @param sc ServletContext
*
* @return ServiceRegistry
*/
public static ServiceRegistry getServiceRegistry(ServletContext sc)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
return (ServiceRegistry)wc.getBean(ServiceRegistry.SERVICE_REGISTRY);
}
/**
* Perform an authentication for the servlet request URI. Processing any "ticket" or
* "guest" URL arguments.
*
* @return AuthenticationStatus
*
* @throws IOException
*/
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res)
throws IOException
{
return servletAuthenticate(req, res, true);
}
/**
* Perform an authentication for the servlet request URI. Processing any "ticket" or
* "guest" URL arguments.
*
* @return AuthenticationStatus
*
* @throws IOException
*/
public AuthenticationStatus servletAuthenticate(HttpServletRequest req, HttpServletResponse res,
boolean redirectToLoginPage) throws IOException
{
AuthenticationStatus status;
// see if a ticket or a force Guest parameter has been supplied
String ticket = req.getParameter(ARG_TICKET);
if (ticket != null && ticket.length() != 0)
{
status = AuthenticationHelper.authenticate(getServletContext(), req, res, ticket);
}
else
{
boolean forceGuest = false;
String guest = req.getParameter(ARG_GUEST);
if (guest != null)
{
forceGuest = Boolean.parseBoolean(guest);
}
status = AuthenticationHelper.authenticate(getServletContext(), req, res, forceGuest);
}
if (status == AuthenticationStatus.Failure && redirectToLoginPage)
{
// authentication failed - now need to display the login page to the user, if asked to
redirectToLoginPage(req, res, getServletContext());
}
return status;
}
/**
* Check the user has the given permission on the given node. If they do not either force a log on if this is a guest
* user or forward to an error page.
*
* @param req
* the request
* @param res
* the response
* @param nodeRef
* the node in question
* @param allowLogIn
* Indicates whether guest users without access to the node should be redirected to the log in page. If
* <code>false</code>, a status 403 forbidden page is displayed instead.
* @return <code>true</code>, if the user has access
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ServletException
* On other errors
*/
public boolean checkAccess(HttpServletRequest req, HttpServletResponse res, NodeRef nodeRef, String permission,
boolean allowLogIn) throws IOException, ServletException
{
ServletContext sc = getServletContext();
ServiceRegistry serviceRegistry = getServiceRegistry(sc);
PermissionService permissionService = serviceRegistry.getPermissionService();
// check that the user has the permission
if (permissionService.hasPermission(nodeRef, permission) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled())
logger.debug("User does not have " + permission + " permission for NodeRef: " + nodeRef.toString());
if (allowLogIn && serviceRegistry.getAuthorityService().hasGuestAuthority())
{
if (logger.isDebugEnabled())
logger.debug("Redirecting to login page...");
redirectToLoginPage(req, res, sc);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Forwarding to error page...");
Application
.handleSystemError(sc, req, res, MSG_ERROR_PERMISSIONS, HttpServletResponse.SC_FORBIDDEN, logger);
}
return false;
}
return true;
}
/**
* Redirect to the Login page - saving the current URL which can be redirected back later
* once the user has successfully completed the authentication process.
*/
public static void redirectToLoginPage(HttpServletRequest req, HttpServletResponse res, ServletContext sc)
throws IOException
{
redirectToLoginPage(req, res, sc, AuthenticationHelper.getRemoteUserMapper(sc) == null);
}
/**
* Redirect to the Login page - saving the current URL which can be redirected back later
* once the user has successfully completed the authentication process.
* @param sendRedirect allow a redirect status code to be set? If <code>false</code> redirect
* will be via markup rather than status code (to allow the status code to be used for handshake
* responses etc.
*/
public static void redirectToLoginPage(HttpServletRequest req, HttpServletResponse res, ServletContext sc, boolean sendRedirect)
throws IOException
{
// Pass the full requested URL as a parameter so the login page knows where to redirect to later
final String uri = req.getRequestURI();
String redirectURL = uri;
// authentication failed - so end servlet execution and redirect to login page
if (WebApplicationContextUtils.getRequiredWebApplicationContext(sc).containsBean(Application.BEAN_CONFIG_SERVICE))
{
StringBuilder redirect = new StringBuilder(128)
.append(req.getContextPath()).append(FACES_SERVLET).append(Application.getLoginPage(sc));
// if we find a JSF servlet reference in the URI then we need to check if the rest of the
// JSP specified is valid for a redirect operation after Login has occured.
int jspIndex;
if (uri.indexOf(req.getContextPath() + FACES_SERVLET) == -1
|| uri.length() > (jspIndex = uri.indexOf(BaseServlet.FACES_SERVLET) + BaseServlet.FACES_SERVLET.length())
&& BaseServlet.validRedirectJSP(uri.substring(jspIndex)))
{
if (redirect.indexOf("?") == -1)
{
redirect.append('?');
}
else
{
redirect.append('&');
}
redirect.append(LoginOutcomeBean.PARAM_REDIRECT_URL);
redirect.append('=');
String url = uri;
// Append the query string if necessary
String queryString = req.getQueryString();
if (queryString != null)
{
// Strip out leading ticket arguments
queryString = queryString.replaceAll("(?<=^|&)" + ARG_TICKET + "(=[^&=]*)?&", "");
// Strip out trailing ticket arguments
queryString = queryString.replaceAll("(^|&)" + ARG_TICKET + "(=[^&=]*)?(?=&|$)", "");
if (queryString.length() != 0)
{
url += "?" + queryString;
}
}
redirect.append(URLEncoder.encode(url, "UTF-8"));
}
redirectURL = redirect.toString();
}
// If external authentication isn't in use (e.g. proxied share authentication), it's safe to return a redirect to the client
if (sendRedirect)
{
res.sendRedirect(redirectURL);
}
// Otherwise, we must signal to the client with an unauthorized status code and rely on a browser refresh to do
// the redirect for failover login (as we do with NTLM, Kerberos)
else
{
res.setContentType("text/html; charset=UTF-8");
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final PrintWriter out = res.getWriter();
out.println("<html><head>");
out.println("<meta http-equiv=\"Refresh\" content=\"0; url=" + redirectURL + "\">");
out.println("</head><body><p>Please <a href=\"" + redirectURL + "\">log in</a>.</p>");
out.println("</body></html>");
out.close();
}
}
/**
* Apply the headers required to disallow caching of the response in the browser
*/
public static void setNoCacheHeaders(HttpServletResponse res)
{
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Pragma", "no-cache");
}
/**
* Returns true if the specified JSP file is valid for a redirect after login.
* Only a specific sub-set of the available JSPs are valid to jump directly too after a
* clean login attempt - e.g. those that do not require JSF bean context setup. This is
* a limitation of the JSP architecture. The ExternalAccessServlet provides a mechanism to
* setup the JSF bean context directly for some specific cases.
*
* @param jsp Filename of JSP to check, for example "/jsp/browse/browse.jsp"
*
* @return true if the JSP is in the list of valid direct URLs, false otherwise
*/
public static boolean validRedirectJSP(String jsp)
{
return validRedirectJSPs.contains(jsp);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
*/
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args)
{
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, true);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context Faces context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
public static NodeRef resolveWebDAVPath(FacesContext context, String[] args, boolean decode)
{
WebApplicationContext wc = FacesContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, decode);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context ServletContext context
* @param args The elements of the path to lookup
*/
public static NodeRef resolveWebDAVPath(ServletContext context, String[] args)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, true);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param context ServletContext context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
public static NodeRef resolveWebDAVPath(ServletContext context, String[] args, boolean decode)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
return resolveWebDAVPath(wc, args, decode);
}
/**
* Resolves the given path elements to a NodeRef in the current repository
*
* @param wc WebApplicationContext Context
* @param args The elements of the path to lookup
* @param decode True to decode the arg from UTF-8 format, false for no decoding
*/
private static NodeRef resolveWebDAVPath(final WebApplicationContext wc, final String[] args, final boolean decode)
{
return AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
{
public NodeRef doWork() throws Exception
{
NodeRef nodeRef = null;
List<String> paths = new ArrayList<String>(args.length - 1);
FileInfo file = null;
try
{
// create a list of path elements (decode the URL as we go)
for (int x = 1; x < args.length; x++)
{
paths.add(decode ? URLDecoder.decode(args[x]) : args[x]);
}
if (logger.isDebugEnabled())
logger.debug("Attempting to resolve webdav path: " + paths);
// get the company home node to start the search from
nodeRef = new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId());
TenantService tenantService = (TenantService)wc.getBean("tenantService");
if (tenantService != null && tenantService.isEnabled())
{
if (logger.isDebugEnabled())
logger.debug("MT is enabled.");
NodeService nodeService = (NodeService) wc.getBean("NodeService");
SearchService searchService = (SearchService) wc.getBean("SearchService");
NamespaceService namespaceService = (NamespaceService) wc.getBean("NamespaceService");
// TODO: since these constants are used more widely than just the WebDAVServlet,
// they should be defined somewhere other than in that servlet
String rootPath = wc.getServletContext().getInitParameter(BaseServlet.KEY_ROOT_PATH);
// note: rootNodeRef is required (for storeRef part)
nodeRef = tenantService.getRootNode(nodeService, searchService, namespaceService, rootPath, nodeRef);
}
if (paths.size() != 0)
{
FileFolderService ffs = (FileFolderService)wc.getBean("FileFolderService");
file = ffs.resolveNamePath(nodeRef, paths);
nodeRef = file.getNodeRef();
}
if (logger.isDebugEnabled())
logger.debug("Resolved webdav path to NodeRef: " + nodeRef);
}
catch (FileNotFoundException fne)
{
if (logger.isWarnEnabled())
logger.warn("Failed to resolve webdav path", fne);
nodeRef = null;
}
return nodeRef;
}
}, AuthenticationUtil.getSystemUserName());
}
/**
* Resolve a name based into a NodeRef and Filename string
*
* @param sc ServletContext
* @param path 'cm:name' based path using the '/' character as a separator
*
* @return PathRefInfo structure containing the resolved NodeRef and filename
*
* @throws IllegalArgumentException
*/
public final static PathRefInfo resolveNamePath(ServletContext sc, String path)
{
StringTokenizer t = new StringTokenizer(path, "/");
int tokenCount = t.countTokens();
String[] elements = new String[tokenCount];
for (int i=0; i<tokenCount; i++)
{
elements[i] = t.nextToken();
}
// process name based path tokens using the webdav path resolving helper
NodeRef nodeRef = resolveWebDAVPath(sc, elements, false);
if (nodeRef == null)
{
// unable to resolve path - output helpful error to the user
throw new IllegalArgumentException("Unable to resolve item Path: " + path);
}
return new PathRefInfo(nodeRef, elements[tokenCount - 1]);
}
/**
* Simple structure class for returning both a NodeRef and Filename String
* @author Kevin Roast
*/
public static class PathRefInfo
{
PathRefInfo(NodeRef ref, String filename)
{
this.NodeRef = ref;
this.Filename = filename;
}
public NodeRef NodeRef;
public String Filename;
}
}

View File

@@ -1,363 +1,363 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.faces.context.FacesContext;
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.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
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.TemplateService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
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
*/
@SuppressWarnings("serial")
public abstract class BaseTemplateContentServlet extends BaseServlet
{
private static final String MIMETYPE_HTML = "text/html;charset=utf-8";
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.
* <p>
* 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<String, Object> 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;
try
{
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());
}
}
catch (AccessDeniedException err)
{
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;
}
// 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
Map<String, 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(
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;
}
}
finally
{
res.getWriter().close();
}
}
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.
* <p>
* 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
* @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 Map<String, Object> getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef)
{
// build FreeMarker default model and merge
Map<String, Object> root = buildModel(services, req, templateRef);
// put the current NodeRef in as "space" and "document"
root.put("space", nodeRef);
root.put("document", nodeRef);
// add URL arguments as a map called 'args' to the root of the model
Map<String, String> args = new HashMap<String, String>(8, 1.0f);
Enumeration names = req.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
try
{
args.put(name, new String(req.getParameter(name).getBytes(), "UTF-8"));
}
catch (UnsupportedEncodingException err) {}
}
root.put("args", args);
// Add the image resolver
root.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver);
// method to allow client urls to be generated
root.put("url", new URLHelper(req));
return root;
}
/** Template Image resolver helper */
protected TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(getServletContext(), filename, size);
}
};
/**
* Helper to return context path for generating urls
*/
public static class URLHelper
{
String contextPath;
String serverPath;
public URLHelper(HttpServletRequest request)
{
this.contextPath = request.getContextPath();
this.serverPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
}
public URLHelper(FacesContext context)
{
this.contextPath = context.getExternalContext().getRequestContextPath();
final Object request = context.getExternalContext().getRequest();
if (request instanceof HttpServletRequest)
{
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
this.serverPath = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + ":" + httpServletRequest.getServerPort();
}
}
public String getContext()
{
return this.contextPath;
}
public String getServerPath()
{
return this.serverPath;
}
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.faces.context.FacesContext;
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.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
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.TemplateService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
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
*/
@SuppressWarnings("serial")
public abstract class BaseTemplateContentServlet extends BaseServlet
{
private static final String MIMETYPE_HTML = "text/html;charset=utf-8";
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.
* <p>
* 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<String, Object> 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;
try
{
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());
}
}
catch (AccessDeniedException err)
{
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;
}
// 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
Map<String, 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(
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;
}
}
finally
{
res.getWriter().close();
}
}
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.
* <p>
* 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
* @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 Map<String, Object> getModel(ServiceRegistry services, HttpServletRequest req, NodeRef templateRef, NodeRef nodeRef)
{
// build FreeMarker default model and merge
Map<String, Object> root = buildModel(services, req, templateRef);
// put the current NodeRef in as "space" and "document"
root.put("space", nodeRef);
root.put("document", nodeRef);
// add URL arguments as a map called 'args' to the root of the model
Map<String, String> args = new HashMap<String, String>(8, 1.0f);
Enumeration names = req.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
try
{
args.put(name, new String(req.getParameter(name).getBytes(), "UTF-8"));
}
catch (UnsupportedEncodingException err) {}
}
root.put("args", args);
// Add the image resolver
root.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver);
// method to allow client urls to be generated
root.put("url", new URLHelper(req));
return root;
}
/** Template Image resolver helper */
protected TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(getServletContext(), filename, size);
}
};
/**
* Helper to return context path for generating urls
*/
public static class URLHelper
{
String contextPath;
String serverPath;
public URLHelper(HttpServletRequest request)
{
this.contextPath = request.getContextPath();
this.serverPath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
}
public URLHelper(FacesContext context)
{
this.contextPath = context.getExternalContext().getRequestContextPath();
final Object request = context.getExternalContext().getRequest();
if (request instanceof HttpServletRequest)
{
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
this.serverPath = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + ":" + httpServletRequest.getServerPort();
}
}
public String getContext()
{
return this.contextPath;
}
public String getServerPath()
{
return this.serverPath;
}
}
}

View File

@@ -1,248 +1,248 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
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.springframework.extensions.config.Config;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.command.CommandFactory;
import org.alfresco.web.app.servlet.command.CommandProcessor;
import org.alfresco.web.app.servlet.command.ExtCommandProcessor;
import org.alfresco.web.config.CommandServletConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for executing commands upon node(s).
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/command/processor-name/command-name/args/...</pre>
* <p>
* The 'processor-name' identifies the command processor to execute the command. For example the
* 'workflow' processor will execute workflow commands upon a node (e.g. "approve" or "reject").
* For example:
* <pre>/alfresco/command/workflow/approve/workspace/SpacesStore/0000-0000-0000-0000</pre>
* The store protocol, followed by the store ID, followed by the content Node Id used to
* identify the node to execute the workflow action upon.
* <p>
* A 'return-page' URL argument can be specified as the redirect page to navigate too after processing.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* And/or also followed by the "?guest=true" argument to force guest access login for the URL.
*
* @author Kevin Roast
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class CommandServlet extends BaseServlet
{
private static final long serialVersionUID = -5432407921038376133L;
private static Log logger = LogFactory.getLog(CommandServlet.class);
private static CommandFactory commandfactory = CommandFactory.getInstance();
public static final String ARG_RETURNPAGE = "return-page";
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
AuthenticationStatus status = servletAuthenticate(req, res);
if (status == AuthenticationStatus.Failure)
{
return;
}
setNoCacheHeaders(res);
uri = uri.substring(req.getContextPath().length());
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
if (tokenCount < 3)
{
throw new IllegalArgumentException("Command Servlet URL did not contain all required args: " + uri);
}
t.nextToken(); // skip servlet name
// get the command processor to execute the command e.g. "workflow"
String procName = t.nextToken();
// get the command to perform
String command = t.nextToken();
// get any remaining uri elements to pass to the processor
String[] urlElements = new String[tokenCount - 3];
for (int i=0; i<tokenCount-3; i++)
{
urlElements[i] = t.nextToken();
}
// retrieve the URL arguments to pass to the processor
Map<String, String> args = new HashMap<String, String>(8, 1.0f);
Enumeration names = req.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
args.put(name, req.getParameter(name));
}
try
{
// get configured command processor by name from Config Service
CommandProcessor processor = createCommandProcessor(procName);
// validate that the processor has everything it needs to run the command
if (processor.validateArguments(getServletContext(), command, args, urlElements) == false)
{
redirectToLoginPage(req, res, getServletContext());
return;
}
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
UserTransaction txn = null;
try
{
txn = serviceRegistry.getTransactionService().getUserTransaction();
txn.begin();
// inform the processor to execute the specified command
if (processor instanceof ExtCommandProcessor)
{
((ExtCommandProcessor)processor).process(serviceRegistry, req, res, command);
}
else
{
processor.process(serviceRegistry, req, command);
}
// commit the transaction
txn.commit();
}
catch (Throwable txnErr)
{
try { if (txn != null) {txn.rollback();} } catch (Exception tex) {}
throw txnErr;
}
String returnPage = req.getParameter(ARG_RETURNPAGE);
if (returnPage != null && returnPage.length() != 0)
{
validateReturnPage(returnPage, req);
if (logger.isDebugEnabled())
logger.debug("Redirecting to specified return page: " + returnPage);
res.sendRedirect(returnPage);
}
else
{
if (logger.isDebugEnabled())
logger.debug("No return page specified, displaying status output.");
if (res.getContentType() == null && !res.isCommitted())
{
res.setContentType("text/html");
// request that the processor output a useful status message
PrintWriter out = res.getWriter();
processor.outputStatus(out);
out.close();
}
}
}
catch (Throwable err)
{
throw new AlfrescoRuntimeException("Error during command servlet processing: " + err.getMessage(), err);
}
}
/**
* ALF-9113 CommandServlet.java, line 179 (Header Manipulation)
*
* Validates that the redirect page is within the current context.
*
* Examples of valid redirect pages:
* <ul>
* <li>/alfresco/faces/jsp/browse/browse.jsp</li>
* <li>../../browse/browse.jsp</li>
* </ul>
*
* @param pageUrl
* @param req
* @throws MalformedURLException
* @throws IllegalArgumentException
*/
private void validateReturnPage(String pageUrl, HttpServletRequest req) throws MalformedURLException
{
if (pageUrl.indexOf(':') != -1)
{
// ':' only allowed in a URL as part of a scheme prefix
throw new IllegalArgumentException("The redirect URL doesn't support absolute URls");
}
// Evaluate it relative to the request URL and strip out .. and .
pageUrl = new URL(new URL(req.getRequestURL().toString()), pageUrl).getPath();
if (!pageUrl.startsWith(req.getContextPath()))
{
throw new IllegalArgumentException("The redirect URL must be in the same context.");
}
}
/**
* Created the specified CommandProcessor instance. The name of the processor is looked up
* in the client config, it should find a valid class impl and then create it.
*
* @param procName Name of the CommandProcessor to lookup in the client config.
*
* @return CommandProcessor
*
* @throws InstantiationException
* @throws IllegalAccessException
*/
private CommandProcessor createCommandProcessor(String procName)
throws InstantiationException, IllegalAccessException
{
Config config = Application.getConfigService(getServletContext()).getConfig("Command Servlet");
if (config == null)
{
throw new AlfrescoRuntimeException("No command processors configured - unable to process any commands.");
}
CommandServletConfigElement configElement = (CommandServletConfigElement)
config.getConfigElement(CommandServletConfigElement.CONFIG_ELEMENT_ID);
if (configElement == null)
{
throw new AlfrescoRuntimeException("No command processors configured - unable to process any commands.");
}
Class clazz = configElement.getCommandProcessor(procName);
Object obj = clazz.newInstance();
if (obj instanceof CommandProcessor == false)
{
throw new AlfrescoRuntimeException("Configured command processor '" + procName + "' is does not implement interface CommandProcessor!");
}
return (CommandProcessor)obj;
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
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.springframework.extensions.config.Config;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.command.CommandFactory;
import org.alfresco.web.app.servlet.command.CommandProcessor;
import org.alfresco.web.app.servlet.command.ExtCommandProcessor;
import org.alfresco.web.config.CommandServletConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for executing commands upon node(s).
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/command/processor-name/command-name/args/...</pre>
* <p>
* The 'processor-name' identifies the command processor to execute the command. For example the
* 'workflow' processor will execute workflow commands upon a node (e.g. "approve" or "reject").
* For example:
* <pre>/alfresco/command/workflow/approve/workspace/SpacesStore/0000-0000-0000-0000</pre>
* The store protocol, followed by the store ID, followed by the content Node Id used to
* identify the node to execute the workflow action upon.
* <p>
* A 'return-page' URL argument can be specified as the redirect page to navigate too after processing.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* And/or also followed by the "?guest=true" argument to force guest access login for the URL.
*
* @author Kevin Roast
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class CommandServlet extends BaseServlet
{
private static final long serialVersionUID = -5432407921038376133L;
private static Log logger = LogFactory.getLog(CommandServlet.class);
private static CommandFactory commandfactory = CommandFactory.getInstance();
public static final String ARG_RETURNPAGE = "return-page";
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
String uri = req.getRequestURI();
if (logger.isDebugEnabled())
logger.debug("Processing URL: " + uri + (req.getQueryString() != null ? ("?" + req.getQueryString()) : ""));
AuthenticationStatus status = servletAuthenticate(req, res);
if (status == AuthenticationStatus.Failure)
{
return;
}
setNoCacheHeaders(res);
uri = uri.substring(req.getContextPath().length());
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
if (tokenCount < 3)
{
throw new IllegalArgumentException("Command Servlet URL did not contain all required args: " + uri);
}
t.nextToken(); // skip servlet name
// get the command processor to execute the command e.g. "workflow"
String procName = t.nextToken();
// get the command to perform
String command = t.nextToken();
// get any remaining uri elements to pass to the processor
String[] urlElements = new String[tokenCount - 3];
for (int i=0; i<tokenCount-3; i++)
{
urlElements[i] = t.nextToken();
}
// retrieve the URL arguments to pass to the processor
Map<String, String> args = new HashMap<String, String>(8, 1.0f);
Enumeration names = req.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
args.put(name, req.getParameter(name));
}
try
{
// get configured command processor by name from Config Service
CommandProcessor processor = createCommandProcessor(procName);
// validate that the processor has everything it needs to run the command
if (processor.validateArguments(getServletContext(), command, args, urlElements) == false)
{
redirectToLoginPage(req, res, getServletContext());
return;
}
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
UserTransaction txn = null;
try
{
txn = serviceRegistry.getTransactionService().getUserTransaction();
txn.begin();
// inform the processor to execute the specified command
if (processor instanceof ExtCommandProcessor)
{
((ExtCommandProcessor)processor).process(serviceRegistry, req, res, command);
}
else
{
processor.process(serviceRegistry, req, command);
}
// commit the transaction
txn.commit();
}
catch (Throwable txnErr)
{
try { if (txn != null) {txn.rollback();} } catch (Exception tex) {}
throw txnErr;
}
String returnPage = req.getParameter(ARG_RETURNPAGE);
if (returnPage != null && returnPage.length() != 0)
{
validateReturnPage(returnPage, req);
if (logger.isDebugEnabled())
logger.debug("Redirecting to specified return page: " + returnPage);
res.sendRedirect(returnPage);
}
else
{
if (logger.isDebugEnabled())
logger.debug("No return page specified, displaying status output.");
if (res.getContentType() == null && !res.isCommitted())
{
res.setContentType("text/html");
// request that the processor output a useful status message
PrintWriter out = res.getWriter();
processor.outputStatus(out);
out.close();
}
}
}
catch (Throwable err)
{
throw new AlfrescoRuntimeException("Error during command servlet processing: " + err.getMessage(), err);
}
}
/**
* ALF-9113 CommandServlet.java, line 179 (Header Manipulation)
*
* Validates that the redirect page is within the current context.
*
* Examples of valid redirect pages:
* <ul>
* <li>/alfresco/faces/jsp/browse/browse.jsp</li>
* <li>../../browse/browse.jsp</li>
* </ul>
*
* @param pageUrl
* @param req
* @throws MalformedURLException
* @throws IllegalArgumentException
*/
private void validateReturnPage(String pageUrl, HttpServletRequest req) throws MalformedURLException
{
if (pageUrl.indexOf(':') != -1)
{
// ':' only allowed in a URL as part of a scheme prefix
throw new IllegalArgumentException("The redirect URL doesn't support absolute URls");
}
// Evaluate it relative to the request URL and strip out .. and .
pageUrl = new URL(new URL(req.getRequestURL().toString()), pageUrl).getPath();
if (!pageUrl.startsWith(req.getContextPath()))
{
throw new IllegalArgumentException("The redirect URL must be in the same context.");
}
}
/**
* Created the specified CommandProcessor instance. The name of the processor is looked up
* in the client config, it should find a valid class impl and then create it.
*
* @param procName Name of the CommandProcessor to lookup in the client config.
*
* @return CommandProcessor
*
* @throws InstantiationException
* @throws IllegalAccessException
*/
private CommandProcessor createCommandProcessor(String procName)
throws InstantiationException, IllegalAccessException
{
Config config = Application.getConfigService(getServletContext()).getConfig("Command Servlet");
if (config == null)
{
throw new AlfrescoRuntimeException("No command processors configured - unable to process any commands.");
}
CommandServletConfigElement configElement = (CommandServletConfigElement)
config.getConfigElement(CommandServletConfigElement.CONFIG_ELEMENT_ID);
if (configElement == null)
{
throw new AlfrescoRuntimeException("No command processors configured - unable to process any commands.");
}
Class clazz = configElement.getCommandProcessor(procName);
Object obj = clazz.newInstance();
if (obj instanceof CommandProcessor == false)
{
throw new AlfrescoRuntimeException("Configured command processor '" + procName + "' is does not implement interface CommandProcessor!");
}
return (CommandProcessor)obj;
}
}

View File

@@ -1,320 +1,320 @@
package org.alfresco.web.app.servlet;
import javax.faces.FactoryFinder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.el.EvaluationException;
import javax.faces.el.ValueBinding;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.bean.generator.IComponentGenerator;
import org.alfresco.web.ui.repo.RepoConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Kevin Roast
*/
public final class FacesHelper
{
/** Root browse screen JSF view ID */
public static final String BROWSE_VIEW_ID = "/jsp/browse/browse.jsp";
private static Log logger = LogFactory.getLog(FacesHelper.class);
/**
* Mask for hex encoding
*/
private static final int MASK = (1 << 4) - 1;
/**
* Digits used for hex string encoding
*/
private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Private constructor
*/
private FacesHelper()
{
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context ServletContext
* @param request ServletRequest
* @param response ServletReponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response, ServletContext context)
{
return getFacesContextImpl(request, response, context, null);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context ServletContext
* @param request ServletRequest
* @param response ServletReponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response, ServletContext context, String viewRoot)
{
return getFacesContextImpl(request, response, context, viewRoot);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context PortletContext
* @param request PortletRequest
* @param response PortletResponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(Object request, Object response, Object context)
{
return getFacesContextImpl(request, response, context, null);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet and Portlet use.
*
* @param context ServletContext or PortletContext
* @param request ServletRequest or PortletRequest
* @param response ServletReponse or PortletResponse
*
* @return FacesContext
*/
private static FacesContext getFacesContextImpl(Object request, Object response, Object context, String viewRoot)
{
FacesContextFactory contextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Doesn't set this instance as the current instance of FacesContext.getCurrentInstance
FacesContext facesContext = contextFactory.getFacesContext(context, request, response, lifecycle);
// Set using our inner class
InnerFacesContext.setFacesContextAsCurrent(facesContext);
// set a new viewRoot, otherwise context.getViewRoot returns null
if (viewRoot == null)
{
viewRoot = FacesHelper.BROWSE_VIEW_ID;
}
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, viewRoot);
facesContext.setViewRoot(view);
return facesContext;
}
/**
* Return a JSF managed bean reference.
*
* @param fc FacesContext
* @param name Name of the managed bean to return
*
* @return the managed bean or null if not found
*/
public static Object getManagedBean(FacesContext fc, String name)
{
Object obj = null;
try
{
ValueBinding vb = fc.getApplication().createValueBinding("#{" + name + "}");
obj = vb.getValue(fc);
}
catch (EvaluationException ee)
{
// catch exception to resolve ADB-158/ACT-7343
// not much we can do here, just make sure return is null
if (logger.isDebugEnabled())
logger.debug("Failed to resolve managed bean: " + name, ee);
obj = null;
}
return obj;
}
/**
* Sets up the id for the given component, if the id is null a unique one
* is generated using the standard Faces algorithm. If an id is present it
* is checked for illegal characters.
*
* @param context FacesContext
* @param component The component to set the id for
* @param id The id to set
*/
public static void setupComponentId(FacesContext context, UIComponent component, String id)
{
if (id == null)
{
id = context.getViewRoot().createUniqueId();
}
else
{
// make sure we do not have illegal characters in the id
id = makeLegalId(id);
}
component.setId(id);
}
/**
* Makes the given id a legal JSF component id by replacing illegal characters
* with ISO9075 encoding - which itself a subset of valid HTML ID characters.
*
* @param id The id to make legal
*
* @return the legalised id
*/
public static String makeLegalId(String id)
{
return (id != null ? validFacesId(id) : null);
}
/**
* Retrieves the named component generator implementation.
* If the named generator is not found the TextFieldGenerator is looked up
* as a default, if this is also not found an AlfrescoRuntimeException is thrown.
*
* @param context FacesContext
* @param generatorName The name of the component generator to retrieve
* @return The component generator instance
*/
public static IComponentGenerator getComponentGenerator(FacesContext context, String generatorName)
{
IComponentGenerator generator = lookupComponentGenerator(context, generatorName);
if (generator == null)
{
// create a text field if we can't find a component generator (a warning should have already been
// displayed on the appserver console)
logger.warn("Attempting to find default component generator '" + RepoConstants.GENERATOR_TEXT_FIELD + "'");
generator = lookupComponentGenerator(context, RepoConstants.GENERATOR_TEXT_FIELD);
}
// if we still don't have a component generator we should abort as vital configuration is missing
if (generator == null)
{
throw new AlfrescoRuntimeException("Failed to find a component generator, please ensure the '" +
RepoConstants.GENERATOR_TEXT_FIELD + "' bean is present in your configuration");
}
return generator;
}
private static IComponentGenerator lookupComponentGenerator(FacesContext context, String generatorName)
{
IComponentGenerator generator = null;
Object obj = FacesHelper.getManagedBean(context, generatorName);
if (obj != null)
{
if (obj instanceof IComponentGenerator)
{
generator = (IComponentGenerator)obj;
if (logger.isDebugEnabled())
logger.debug("Found component generator for '" + generatorName + "': " + generator);
}
else
{
logger.warn("Bean '" + generatorName + "' does not implement IComponentGenerator");
}
}
else
{
logger.warn("Failed to find component generator with name of '" + generatorName + "'");
}
return generator;
}
/**
* We need an inner class to be able to call FacesContext.setCurrentInstance
* since it's a protected method
*/
private abstract static class InnerFacesContext extends FacesContext
{
protected static void setFacesContextAsCurrent(FacesContext facesContext)
{
FacesContext.setCurrentInstance(facesContext);
}
}
/**
* Helper to ensure only valid and acceptable characters are output as Faces component IDs.
* Based on ISO9075 encoding - which itself a subset of valid HTML ID characters.
*/
private static String validFacesId(String id)
{
int len = id.length();
StringBuilder buf = new StringBuilder(len + (len>>1));
for (int i = 0; i<len; i++)
{
char c = id.charAt(i);
int ci = (int)c;
if (i == 0)
{
if ((ci >= 65 && ci <= 90) || // A-Z
(ci >= 97 && ci <= 122)) // a-z
{
buf.append(c);
}
else
{
encode(c, buf);
}
}
else
{
if ((ci >= 65 && ci <= 90) || // A-Z
(ci >= 97 && ci <= 122) || // a-z
(ci >= 48 && ci <= 57) || // 0-9
ci == 45 || ci == 95) // - and _
{
buf.append(c);
}
else
{
encode(c, buf);
}
}
}
return buf.toString();
}
private static void encode(char c, StringBuilder builder)
{
char[] buf = new char[] { 'x', '0', '0', '0', '0', '_' };
int charPos = 5;
do
{
buf[--charPos] = DIGITS[c & MASK];
c >>>= 4;
}
while (c != 0);
builder.append(buf);
}
}
package org.alfresco.web.app.servlet;
import javax.faces.FactoryFinder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.el.EvaluationException;
import javax.faces.el.ValueBinding;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.bean.generator.IComponentGenerator;
import org.alfresco.web.ui.repo.RepoConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Kevin Roast
*/
public final class FacesHelper
{
/** Root browse screen JSF view ID */
public static final String BROWSE_VIEW_ID = "/jsp/browse/browse.jsp";
private static Log logger = LogFactory.getLog(FacesHelper.class);
/**
* Mask for hex encoding
*/
private static final int MASK = (1 << 4) - 1;
/**
* Digits used for hex string encoding
*/
private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Private constructor
*/
private FacesHelper()
{
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context ServletContext
* @param request ServletRequest
* @param response ServletReponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response, ServletContext context)
{
return getFacesContextImpl(request, response, context, null);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context ServletContext
* @param request ServletRequest
* @param response ServletReponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(ServletRequest request, ServletResponse response, ServletContext context, String viewRoot)
{
return getFacesContextImpl(request, response, context, viewRoot);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet use.
*
* @param context PortletContext
* @param request PortletRequest
* @param response PortletResponse
*
* @return FacesContext
*/
public static FacesContext getFacesContext(Object request, Object response, Object context)
{
return getFacesContextImpl(request, response, context, null);
}
/**
* Return a valid FacesContext for the specific context, request and response.
* The FacesContext can be constructor for Servlet and Portlet use.
*
* @param context ServletContext or PortletContext
* @param request ServletRequest or PortletRequest
* @param response ServletReponse or PortletResponse
*
* @return FacesContext
*/
private static FacesContext getFacesContextImpl(Object request, Object response, Object context, String viewRoot)
{
FacesContextFactory contextFactory = (FacesContextFactory)FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Doesn't set this instance as the current instance of FacesContext.getCurrentInstance
FacesContext facesContext = contextFactory.getFacesContext(context, request, response, lifecycle);
// Set using our inner class
InnerFacesContext.setFacesContextAsCurrent(facesContext);
// set a new viewRoot, otherwise context.getViewRoot returns null
if (viewRoot == null)
{
viewRoot = FacesHelper.BROWSE_VIEW_ID;
}
UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, viewRoot);
facesContext.setViewRoot(view);
return facesContext;
}
/**
* Return a JSF managed bean reference.
*
* @param fc FacesContext
* @param name Name of the managed bean to return
*
* @return the managed bean or null if not found
*/
public static Object getManagedBean(FacesContext fc, String name)
{
Object obj = null;
try
{
ValueBinding vb = fc.getApplication().createValueBinding("#{" + name + "}");
obj = vb.getValue(fc);
}
catch (EvaluationException ee)
{
// catch exception to resolve ADB-158/ACT-7343
// not much we can do here, just make sure return is null
if (logger.isDebugEnabled())
logger.debug("Failed to resolve managed bean: " + name, ee);
obj = null;
}
return obj;
}
/**
* Sets up the id for the given component, if the id is null a unique one
* is generated using the standard Faces algorithm. If an id is present it
* is checked for illegal characters.
*
* @param context FacesContext
* @param component The component to set the id for
* @param id The id to set
*/
public static void setupComponentId(FacesContext context, UIComponent component, String id)
{
if (id == null)
{
id = context.getViewRoot().createUniqueId();
}
else
{
// make sure we do not have illegal characters in the id
id = makeLegalId(id);
}
component.setId(id);
}
/**
* Makes the given id a legal JSF component id by replacing illegal characters
* with ISO9075 encoding - which itself a subset of valid HTML ID characters.
*
* @param id The id to make legal
*
* @return the legalised id
*/
public static String makeLegalId(String id)
{
return (id != null ? validFacesId(id) : null);
}
/**
* Retrieves the named component generator implementation.
* If the named generator is not found the TextFieldGenerator is looked up
* as a default, if this is also not found an AlfrescoRuntimeException is thrown.
*
* @param context FacesContext
* @param generatorName The name of the component generator to retrieve
* @return The component generator instance
*/
public static IComponentGenerator getComponentGenerator(FacesContext context, String generatorName)
{
IComponentGenerator generator = lookupComponentGenerator(context, generatorName);
if (generator == null)
{
// create a text field if we can't find a component generator (a warning should have already been
// displayed on the appserver console)
logger.warn("Attempting to find default component generator '" + RepoConstants.GENERATOR_TEXT_FIELD + "'");
generator = lookupComponentGenerator(context, RepoConstants.GENERATOR_TEXT_FIELD);
}
// if we still don't have a component generator we should abort as vital configuration is missing
if (generator == null)
{
throw new AlfrescoRuntimeException("Failed to find a component generator, please ensure the '" +
RepoConstants.GENERATOR_TEXT_FIELD + "' bean is present in your configuration");
}
return generator;
}
private static IComponentGenerator lookupComponentGenerator(FacesContext context, String generatorName)
{
IComponentGenerator generator = null;
Object obj = FacesHelper.getManagedBean(context, generatorName);
if (obj != null)
{
if (obj instanceof IComponentGenerator)
{
generator = (IComponentGenerator)obj;
if (logger.isDebugEnabled())
logger.debug("Found component generator for '" + generatorName + "': " + generator);
}
else
{
logger.warn("Bean '" + generatorName + "' does not implement IComponentGenerator");
}
}
else
{
logger.warn("Failed to find component generator with name of '" + generatorName + "'");
}
return generator;
}
/**
* We need an inner class to be able to call FacesContext.setCurrentInstance
* since it's a protected method
*/
private abstract static class InnerFacesContext extends FacesContext
{
protected static void setFacesContextAsCurrent(FacesContext facesContext)
{
FacesContext.setCurrentInstance(facesContext);
}
}
/**
* Helper to ensure only valid and acceptable characters are output as Faces component IDs.
* Based on ISO9075 encoding - which itself a subset of valid HTML ID characters.
*/
private static String validFacesId(String id)
{
int len = id.length();
StringBuilder buf = new StringBuilder(len + (len>>1));
for (int i = 0; i<len; i++)
{
char c = id.charAt(i);
int ci = (int)c;
if (i == 0)
{
if ((ci >= 65 && ci <= 90) || // A-Z
(ci >= 97 && ci <= 122)) // a-z
{
buf.append(c);
}
else
{
encode(c, buf);
}
}
else
{
if ((ci >= 65 && ci <= 90) || // A-Z
(ci >= 97 && ci <= 122) || // a-z
(ci >= 48 && ci <= 57) || // 0-9
ci == 45 || ci == 95) // - and _
{
buf.append(c);
}
else
{
encode(c, buf);
}
}
}
return buf.toString();
}
private static void encode(char c, StringBuilder builder)
{
char[] buf = new char[] { 'x', '0', '0', '0', '0', '_' };
int charPos = 5;
do
{
buf[--charPos] = DIGITS[c & MASK];
c >>>= 4;
}
while (c != 0);
builder.append(buf);
}
}

View File

@@ -1,130 +1,130 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for streaming node content from the repo directly to the response stream.
* The appropriate mimetype is calculated based on filename extension.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/guestDownload/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/guestDownload/direct/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/guestDownload/[direct|attach]?path=/Company%20Home/MyFolder/myfile.pdf</pre>
* The protocol, followed by either the store and Id (NodeRef) or instead specify a name based
* encoded Path to the content, note that the filename element is used for mimetype lookup and
* as the returning filename for the response stream.
* <p>
* The 'attach' or 'direct' element is used to indicate whether to display the stream directly
* in the browser or download it as a file attachment.
* <p>
* By default, the download assumes that the content is on the
* {@link org.alfresco.model.ContentModel#PROP_CONTENT content property}.<br>
* To retrieve the content of a specific model property, use a 'property' arg, providing the workspace,
* node ID AND the qualified name of the property.
* <p>
* This servlet only accesses content available to the guest user. If the guest user does not
* have access to the requested a 403 Forbidden response is returned to the caller.
* <p>
* 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 GuestDownloadContentServlet extends BaseDownloadContentServlet
{
private static final long serialVersionUID = -5258137503339817457L;
private static Log logger = LogFactory.getLog(GuestDownloadContentServlet.class);
private static final String DOWNLOAD_URL = "/gd/" + URL_ATTACH + "/{0}/{1}/{2}/{3}";
private static final String BROWSER_URL = "/gd/" + URL_DIRECT + "/{0}/{1}/{2}/{3}";
@Override
protected Log getLogger()
{
return logger;
}
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doGet(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) : ""));
}
DownloadContentWork dcw = new DownloadContentWork(req, res);
AuthenticationUtil.runAs(dcw, AuthenticationUtil.getGuestUserName());
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
* The content is supplied as an HTTP1.1 attachment to the response. This generally means
* a browser should prompt the user to save the content to specified location.
*
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
public final static String generateDownloadURL(NodeRef ref, String name)
{
return generateUrl(DOWNLOAD_URL, ref, name);
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
* The content is supplied directly in the reponse. This generally means a browser will
* attempt to open the content directly if possible, else it will prompt to save the file.
*
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
public final static String generateBrowserURL(NodeRef ref, String name)
{
return generateUrl(BROWSER_URL, ref, name);
}
/**
* Class to wrap the call to processDownloadRequest.
*
* @author gavinc
*/
public class DownloadContentWork implements RunAsWork<Object>
{
private HttpServletRequest req = null;
private HttpServletResponse res = null;
public DownloadContentWork(HttpServletRequest req, HttpServletResponse res)
{
this.req = req;
this.res = res;
}
public Object doWork() throws Exception
{
processDownloadRequest(this.req, this.res, false, true);
return null;
}
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for streaming node content from the repo directly to the response stream.
* The appropriate mimetype is calculated based on filename extension.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/guestDownload/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/guestDownload/direct/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/guestDownload/[direct|attach]?path=/Company%20Home/MyFolder/myfile.pdf</pre>
* The protocol, followed by either the store and Id (NodeRef) or instead specify a name based
* encoded Path to the content, note that the filename element is used for mimetype lookup and
* as the returning filename for the response stream.
* <p>
* The 'attach' or 'direct' element is used to indicate whether to display the stream directly
* in the browser or download it as a file attachment.
* <p>
* By default, the download assumes that the content is on the
* {@link org.alfresco.model.ContentModel#PROP_CONTENT content property}.<br>
* To retrieve the content of a specific model property, use a 'property' arg, providing the workspace,
* node ID AND the qualified name of the property.
* <p>
* This servlet only accesses content available to the guest user. If the guest user does not
* have access to the requested a 403 Forbidden response is returned to the caller.
* <p>
* 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 GuestDownloadContentServlet extends BaseDownloadContentServlet
{
private static final long serialVersionUID = -5258137503339817457L;
private static Log logger = LogFactory.getLog(GuestDownloadContentServlet.class);
private static final String DOWNLOAD_URL = "/gd/" + URL_ATTACH + "/{0}/{1}/{2}/{3}";
private static final String BROWSER_URL = "/gd/" + URL_DIRECT + "/{0}/{1}/{2}/{3}";
@Override
protected Log getLogger()
{
return logger;
}
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doGet(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) : ""));
}
DownloadContentWork dcw = new DownloadContentWork(req, res);
AuthenticationUtil.runAs(dcw, AuthenticationUtil.getGuestUserName());
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
* The content is supplied as an HTTP1.1 attachment to the response. This generally means
* a browser should prompt the user to save the content to specified location.
*
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
public final static String generateDownloadURL(NodeRef ref, String name)
{
return generateUrl(DOWNLOAD_URL, ref, name);
}
/**
* Helper to generate a URL to a content node for downloading content from the server.
* The content is supplied directly in the reponse. This generally means a browser will
* attempt to open the content directly if possible, else it will prompt to save the file.
*
* @param ref NodeRef of the content node to generate URL for (cannot be null)
* @param name File name to return in the URL (cannot be null)
*
* @return URL to download the content from the specified node
*/
public final static String generateBrowserURL(NodeRef ref, String name)
{
return generateUrl(BROWSER_URL, ref, name);
}
/**
* Class to wrap the call to processDownloadRequest.
*
* @author gavinc
*/
public class DownloadContentWork implements RunAsWork<Object>
{
private HttpServletRequest req = null;
private HttpServletResponse res = null;
public DownloadContentWork(HttpServletRequest req, HttpServletResponse res)
{
this.req = req;
this.res = res;
}
public Object doWork() throws Exception
{
processDownloadRequest(this.req, this.res, false, true);
return null;
}
}
}

View File

@@ -1,171 +1,171 @@
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;
/**
* Servlet responsible for streaming content from a template processed against a node directly
* to the response stream.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000</pre>
* or
* <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000/workspace/SpacesStore/0000-0000-0000-0000</pre>
* or
* <pre>/alfresco/template?templatePath=/Company%20Home/Data%20Dictionary/Presentation%20Templates/doc_info.ftl&contextPath=/Company%20Home/mydoc.txt</pre>
* <p>
* 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.
* <p>
* 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.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* 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".
* <p>
* 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.
* <p>
* 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
* @deprecated 5.0 not exposed in web-client web.xml
*/
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<String, Object> 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(AuthenticationUtil.getGuestUserName());
User guestUser = new User(AuthenticationUtil.getGuestUserName(), 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, this.imageResolver);
}
/**
* @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, AuthenticationUtil.getGuestUserName());
}
/**
* Helper to generate a URL to process a template against a node.
* <p>
* 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<Object>
{
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;
}
}
}
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;
/**
* Servlet responsible for streaming content from a template processed against a node directly
* to the response stream.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000</pre>
* or
* <pre>/alfresco/template/workspace/SpacesStore/0000-0000-0000-0000/workspace/SpacesStore/0000-0000-0000-0000</pre>
* or
* <pre>/alfresco/template?templatePath=/Company%20Home/Data%20Dictionary/Presentation%20Templates/doc_info.ftl&contextPath=/Company%20Home/mydoc.txt</pre>
* <p>
* 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.
* <p>
* 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.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* 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".
* <p>
* 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.
* <p>
* 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
* @deprecated 5.0 not exposed in web-client web.xml
*/
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<String, Object> 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(AuthenticationUtil.getGuestUserName());
User guestUser = new User(AuthenticationUtil.getGuestUserName(), 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, this.imageResolver);
}
/**
* @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, AuthenticationUtil.getGuestUserName());
}
/**
* Helper to generate a URL to process a template against a node.
* <p>
* 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<Object>
{
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;
}
}
}

View File

@@ -1,146 +1,146 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.workflow.jbpm.JBPMEngine;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet for handling process deployments from jBPM process designer.
*
* @author davidc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class JBPMDeployProcessServlet extends HttpServlet
{
private static final long serialVersionUID = 8002539291245090187L;
private static final String BEAN_GLOBAL_PROPERTIES = "global-properties";
private static final String PROP_ENABLED = "system.workflow.deployservlet.enabled";
@Override
public void init() throws ServletException
{
// Render this servlet permanently unavailable if its enablement property is not set
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
Properties globalProperties = (Properties) wc.getBean(BEAN_GLOBAL_PROPERTIES);
String enabled = globalProperties.getProperty(PROP_ENABLED);
if (!PropertyCheck.isValidPropertyString(enabled) || !Boolean.parseBoolean(enabled))
{
throw new UnavailableException("system.workflow.deployservlet.enabled=false");
}
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException
{
try
{
response.setContentType("text/html");
InputStream deploymentArchive = getDeploymentArchive(request);
WorkflowDefinition workflowDef = deployArchive(deploymentArchive);
response.getWriter().println("Deployed archive " + workflowDef.title + " successfully");
}
catch(IOException e)
{
// NOTE: according to original jBPM deployment servlet
response.getWriter().println("IOException");
}
catch(FileUploadException e)
{
// NOTE: according to original jBPM deployment servlet
response.getWriter().println("FileUploadException");
}
}
/**
* Retrieve the JBPM Process Designer deployment archive from the request
*
* @param request the request
* @return the input stream onto the deployment archive
* @throws WorkflowException
* @throws FileUploadException
* @throws IOException
*/
private InputStream getDeploymentArchive(HttpServletRequest request)
throws FileUploadException, IOException
{
if (!FileUpload.isMultipartContent(request))
{
throw new FileUploadException("Not a multipart request");
}
GPDUpload fileUpload = new GPDUpload();
List list = fileUpload.parseRequest(request);
Iterator iterator = list.iterator();
if (!iterator.hasNext())
{
throw new FileUploadException("No process file in the request");
}
FileItem fileItem = (FileItem) iterator.next();
if (fileItem.getContentType().indexOf("application/x-zip-compressed") == -1)
{
throw new FileUploadException("Not a process archive");
}
return fileItem.getInputStream();
}
/**
* Deploy the jBPM process archive to the Alfresco Repository
*
* @param deploymentArchive the archive to deploy
* @return the deployed workflow definition
*/
private WorkflowDefinition deployArchive(InputStream deploymentArchive)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
WorkflowService workflowService = (WorkflowService)wc.getBean(ServiceRegistry.WORKFLOW_SERVICE.getLocalName());
WorkflowDeployment deployment = workflowService.deployDefinition(JBPMEngine.ENGINE_ID, deploymentArchive, MimetypeMap.MIMETYPE_ZIP);
return deployment.definition;
}
/**
* NOTE: Workaround...
*
* The JBPM process designer (as of 3.1.2) issues a request with a multi-part line
* delimited by ",". It should be ":" according to the HTTP specification which
* the commons file-upload is adhering to.
*
* @author davidc
*/
@SuppressWarnings("deprecation")
private class GPDUpload extends DiskFileUpload
{
@Override
protected byte[] getBoundary(String contentType)
{
return super.getBoundary(contentType.replace(",", ";"));
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.workflow.jbpm.JBPMEngine;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowDeployment;
import org.alfresco.service.cmr.workflow.WorkflowException;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Servlet for handling process deployments from jBPM process designer.
*
* @author davidc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class JBPMDeployProcessServlet extends HttpServlet
{
private static final long serialVersionUID = 8002539291245090187L;
private static final String BEAN_GLOBAL_PROPERTIES = "global-properties";
private static final String PROP_ENABLED = "system.workflow.deployservlet.enabled";
@Override
public void init() throws ServletException
{
// Render this servlet permanently unavailable if its enablement property is not set
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
Properties globalProperties = (Properties) wc.getBean(BEAN_GLOBAL_PROPERTIES);
String enabled = globalProperties.getProperty(PROP_ENABLED);
if (!PropertyCheck.isValidPropertyString(enabled) || !Boolean.parseBoolean(enabled))
{
throw new UnavailableException("system.workflow.deployservlet.enabled=false");
}
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException
{
try
{
response.setContentType("text/html");
InputStream deploymentArchive = getDeploymentArchive(request);
WorkflowDefinition workflowDef = deployArchive(deploymentArchive);
response.getWriter().println("Deployed archive " + workflowDef.title + " successfully");
}
catch(IOException e)
{
// NOTE: according to original jBPM deployment servlet
response.getWriter().println("IOException");
}
catch(FileUploadException e)
{
// NOTE: according to original jBPM deployment servlet
response.getWriter().println("FileUploadException");
}
}
/**
* Retrieve the JBPM Process Designer deployment archive from the request
*
* @param request the request
* @return the input stream onto the deployment archive
* @throws WorkflowException
* @throws FileUploadException
* @throws IOException
*/
private InputStream getDeploymentArchive(HttpServletRequest request)
throws FileUploadException, IOException
{
if (!FileUpload.isMultipartContent(request))
{
throw new FileUploadException("Not a multipart request");
}
GPDUpload fileUpload = new GPDUpload();
List list = fileUpload.parseRequest(request);
Iterator iterator = list.iterator();
if (!iterator.hasNext())
{
throw new FileUploadException("No process file in the request");
}
FileItem fileItem = (FileItem) iterator.next();
if (fileItem.getContentType().indexOf("application/x-zip-compressed") == -1)
{
throw new FileUploadException("Not a process archive");
}
return fileItem.getInputStream();
}
/**
* Deploy the jBPM process archive to the Alfresco Repository
*
* @param deploymentArchive the archive to deploy
* @return the deployed workflow definition
*/
private WorkflowDefinition deployArchive(InputStream deploymentArchive)
{
WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
WorkflowService workflowService = (WorkflowService)wc.getBean(ServiceRegistry.WORKFLOW_SERVICE.getLocalName());
WorkflowDeployment deployment = workflowService.deployDefinition(JBPMEngine.ENGINE_ID, deploymentArchive, MimetypeMap.MIMETYPE_ZIP);
return deployment.definition;
}
/**
* NOTE: Workaround...
*
* The JBPM process designer (as of 3.1.2) issues a request with a multi-part line
* delimited by ",". It should be ":" according to the HTTP specification which
* the commons file-upload is adhering to.
*
* @author davidc
*/
@SuppressWarnings("deprecation")
private class GPDUpload extends DiskFileUpload
{
@Override
protected byte[] getBoundary(String contentType)
{
return super.getBoundary(contentType.replace(",", ";"));
}
}
}

View File

@@ -1,259 +1,259 @@
package org.alfresco.web.app.servlet;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
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.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Servlet responsible for streaming content directly into the repository from the PUT request.
* The appropriate mimetype is calculated based on filename extension.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/upload/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/upload/myfile.pdf</pre>
* <p>
* If the store and node id are specified in the URL then the content provided will be streamed onto the node
* using an updating writer, updating the content property value accordingly.
* <p>
* If only the file name is specified the content will be streamed into the content store and the content data
* will be returned in the reposonse. This can then be used to update the value of a content property manually.
* Any used content will be cleared up in the usual manner.
* <p>
* By default, the download assumes that the content is on the
* {@link org.alfresco.model.ContentModel#PROP_CONTENT content property}.<br>
* To set the content of a specific model property, use a 'property' arg, providing the qualified name of the property.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* Guest access is currently disabled for this servlet.
*
* @author Roy Wetherall
*/
public class UploadContentServlet extends BaseServlet
{
/** Serial version UID */
private static final long serialVersionUID = 1055960980867420355L;
/** Logger */
private static Log logger = LogFactory.getLog(UploadContentServlet.class);
/** Default mime type */
protected static final String MIMETYPE_OCTET_STREAM = "application/octet-stream";
/** Argument properties */
protected static final String ARG_PROPERTY = "property";
protected static final String ARG_MIMETYPE = "mimetype";
protected static final String ARG_ENCODING = "encoding";
protected static final String ARG_LOCALE = "locale";
/**
* @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doPut(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
if (logger.isDebugEnabled() == true)
{
String queryString = req.getQueryString();
logger.debug("Authenticating request to URL: " + req.getRequestURI()
+ ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
}
AuthenticationStatus status = servletAuthenticate(req, res, false);
if (status == AuthenticationStatus.Failure || status == AuthenticationStatus.Guest)
{
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
// Tokenise the URI
String uri = req.getRequestURI();
uri = uri.substring(req.getContextPath().length());
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
t.nextToken(); // skip servlet name
// get or calculate the noderef and filename to download as
NodeRef nodeRef = null;
String filename = null;
QName propertyQName = null;
if (tokenCount == 2)
{
// filename is the only token
filename = t.nextToken();
}
else if (tokenCount == 4 || tokenCount == 5)
{
// assume 'workspace' or other NodeRef based protocol for remaining URL
// elements
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
String id = t.nextToken();
// build noderef from the appropriate URL elements
nodeRef = new NodeRef(storeRef, id);
if (tokenCount == 5)
{
// filename is last remaining token
filename = t.nextToken();
}
// get qualified of the property to get content from - default to
// ContentModel.PROP_CONTENT
propertyQName = ContentModel.PROP_CONTENT;
String property = req.getParameter(ARG_PROPERTY);
if (property != null && property.length() != 0)
{
propertyQName = QName.createQName(property);
}
}
else
{
logger.debug("Upload URL did not contain all required args: " + uri);
res.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
return;
}
// get the services we need to retrieve the content
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
ContentService contentService = serviceRegistry.getContentService();
PermissionService permissionService = serviceRegistry.getPermissionService();
MimetypeService mimetypeService = serviceRegistry.getMimetypeService();
NodeService nodeService = serviceRegistry.getNodeService();
InputStream is = req.getInputStream();
BufferedInputStream inputStream = new BufferedInputStream(is);
// Sort out the mimetype
String mimetype = req.getParameter(ARG_MIMETYPE);
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MIMETYPE_OCTET_STREAM;
if (filename != null)
{
MimetypeService mimetypeMap = serviceRegistry.getMimetypeService();
int extIndex = filename.lastIndexOf('.');
if (extIndex != -1)
{
String ext = filename.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
}
// Get the encoding
String encoding = req.getParameter(ARG_ENCODING);
if (encoding == null || encoding.length() == 0)
{
// Get the encoding
ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder();
Charset charset = charsetFinder.getCharset(inputStream, mimetype);
encoding = charset.name();
}
// Get the locale
Locale locale = I18NUtil.parseLocale(req.getParameter(ARG_LOCALE));
if (locale == null)
{
locale = I18NUtil.getContentLocale();
if (nodeRef != null)
{
ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, propertyQName);
if (contentData != null)
{
locale = contentData.getLocale();
}
}
}
if (logger.isDebugEnabled())
{
if (nodeRef != null) {logger.debug("Found NodeRef: " + nodeRef.toString());}
logger.debug("For property: " + propertyQName);
logger.debug("File name: " + filename);
logger.debug("Mimetype: " + mimetype);
logger.debug("Encoding: " + encoding);
logger.debug("Locale: " + locale);
}
// Check that the user has the permissions to write the content
if (permissionService.hasPermission(nodeRef, PermissionService.WRITE_CONTENT) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled() == true)
{
logger.debug("User does not have permissions to wrtie content for NodeRef: " + nodeRef.toString());
}
if (logger.isDebugEnabled())
{
logger.debug("Returning 403 Forbidden error...");
}
res.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// Try and get the content writer
ContentWriter writer = contentService.getWriter(nodeRef, propertyQName, true);
if (writer == null)
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Content writer cannot be obtained for NodeRef: " + nodeRef.toString());
}
res.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
return;
}
// Set the mimetype, encoding and locale
writer.setMimetype(mimetype);
writer.setEncoding(encoding);
if (locale != null)
{
writer.setLocale(locale);
}
// Stream the content into the repository
writer.putContent(inputStream);
if (logger.isDebugEnabled() == true)
{
logger.debug("Content details: " + writer.getContentData().toString());
}
// Set return status
res.getWriter().write(writer.getContentData().toString());
res.flushBuffer();
if (logger.isDebugEnabled() == true)
{
logger.debug("UploadContentServlet done");
}
}
}
package org.alfresco.web.app.servlet;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.encoding.ContentCharsetFinder;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
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.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Servlet responsible for streaming content directly into the repository from the PUT request.
* The appropriate mimetype is calculated based on filename extension.
* <p>
* The URL to the servlet should be generated thus:
* <pre>/alfresco/upload/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf</pre>
* or
* <pre>/alfresco/upload/myfile.pdf</pre>
* <p>
* If the store and node id are specified in the URL then the content provided will be streamed onto the node
* using an updating writer, updating the content property value accordingly.
* <p>
* If only the file name is specified the content will be streamed into the content store and the content data
* will be returned in the reposonse. This can then be used to update the value of a content property manually.
* Any used content will be cleared up in the usual manner.
* <p>
* By default, the download assumes that the content is on the
* {@link org.alfresco.model.ContentModel#PROP_CONTENT content property}.<br>
* To set the content of a specific model property, use a 'property' arg, providing the qualified name of the property.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
* <p>
* Guest access is currently disabled for this servlet.
*
* @author Roy Wetherall
*/
public class UploadContentServlet extends BaseServlet
{
/** Serial version UID */
private static final long serialVersionUID = 1055960980867420355L;
/** Logger */
private static Log logger = LogFactory.getLog(UploadContentServlet.class);
/** Default mime type */
protected static final String MIMETYPE_OCTET_STREAM = "application/octet-stream";
/** Argument properties */
protected static final String ARG_PROPERTY = "property";
protected static final String ARG_MIMETYPE = "mimetype";
protected static final String ARG_ENCODING = "encoding";
protected static final String ARG_LOCALE = "locale";
/**
* @see javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doPut(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
if (logger.isDebugEnabled() == true)
{
String queryString = req.getQueryString();
logger.debug("Authenticating request to URL: " + req.getRequestURI()
+ ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
}
AuthenticationStatus status = servletAuthenticate(req, res, false);
if (status == AuthenticationStatus.Failure || status == AuthenticationStatus.Guest)
{
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
// Tokenise the URI
String uri = req.getRequestURI();
uri = uri.substring(req.getContextPath().length());
StringTokenizer t = new StringTokenizer(uri, "/");
int tokenCount = t.countTokens();
t.nextToken(); // skip servlet name
// get or calculate the noderef and filename to download as
NodeRef nodeRef = null;
String filename = null;
QName propertyQName = null;
if (tokenCount == 2)
{
// filename is the only token
filename = t.nextToken();
}
else if (tokenCount == 4 || tokenCount == 5)
{
// assume 'workspace' or other NodeRef based protocol for remaining URL
// elements
StoreRef storeRef = new StoreRef(t.nextToken(), t.nextToken());
String id = t.nextToken();
// build noderef from the appropriate URL elements
nodeRef = new NodeRef(storeRef, id);
if (tokenCount == 5)
{
// filename is last remaining token
filename = t.nextToken();
}
// get qualified of the property to get content from - default to
// ContentModel.PROP_CONTENT
propertyQName = ContentModel.PROP_CONTENT;
String property = req.getParameter(ARG_PROPERTY);
if (property != null && property.length() != 0)
{
propertyQName = QName.createQName(property);
}
}
else
{
logger.debug("Upload URL did not contain all required args: " + uri);
res.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
return;
}
// get the services we need to retrieve the content
ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext());
ContentService contentService = serviceRegistry.getContentService();
PermissionService permissionService = serviceRegistry.getPermissionService();
MimetypeService mimetypeService = serviceRegistry.getMimetypeService();
NodeService nodeService = serviceRegistry.getNodeService();
InputStream is = req.getInputStream();
BufferedInputStream inputStream = new BufferedInputStream(is);
// Sort out the mimetype
String mimetype = req.getParameter(ARG_MIMETYPE);
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MIMETYPE_OCTET_STREAM;
if (filename != null)
{
MimetypeService mimetypeMap = serviceRegistry.getMimetypeService();
int extIndex = filename.lastIndexOf('.');
if (extIndex != -1)
{
String ext = filename.substring(extIndex + 1);
mimetype = mimetypeService.getMimetype(ext);
}
}
}
// Get the encoding
String encoding = req.getParameter(ARG_ENCODING);
if (encoding == null || encoding.length() == 0)
{
// Get the encoding
ContentCharsetFinder charsetFinder = mimetypeService.getContentCharsetFinder();
Charset charset = charsetFinder.getCharset(inputStream, mimetype);
encoding = charset.name();
}
// Get the locale
Locale locale = I18NUtil.parseLocale(req.getParameter(ARG_LOCALE));
if (locale == null)
{
locale = I18NUtil.getContentLocale();
if (nodeRef != null)
{
ContentData contentData = (ContentData) nodeService.getProperty(nodeRef, propertyQName);
if (contentData != null)
{
locale = contentData.getLocale();
}
}
}
if (logger.isDebugEnabled())
{
if (nodeRef != null) {logger.debug("Found NodeRef: " + nodeRef.toString());}
logger.debug("For property: " + propertyQName);
logger.debug("File name: " + filename);
logger.debug("Mimetype: " + mimetype);
logger.debug("Encoding: " + encoding);
logger.debug("Locale: " + locale);
}
// Check that the user has the permissions to write the content
if (permissionService.hasPermission(nodeRef, PermissionService.WRITE_CONTENT) == AccessStatus.DENIED)
{
if (logger.isDebugEnabled() == true)
{
logger.debug("User does not have permissions to wrtie content for NodeRef: " + nodeRef.toString());
}
if (logger.isDebugEnabled())
{
logger.debug("Returning 403 Forbidden error...");
}
res.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// Try and get the content writer
ContentWriter writer = contentService.getWriter(nodeRef, propertyQName, true);
if (writer == null)
{
if (logger.isDebugEnabled() == true)
{
logger.debug("Content writer cannot be obtained for NodeRef: " + nodeRef.toString());
}
res.sendError(HttpServletResponse.SC_EXPECTATION_FAILED);
return;
}
// Set the mimetype, encoding and locale
writer.setMimetype(mimetype);
writer.setEncoding(encoding);
if (locale != null)
{
writer.setLocale(locale);
}
// Stream the content into the repository
writer.putContent(inputStream);
if (logger.isDebugEnabled() == true)
{
logger.debug("Content details: " + writer.getContentData().toString());
}
// Set return status
res.getWriter().write(writer.getContentData().toString());
res.flushBuffer();
if (logger.isDebugEnabled() == true)
{
logger.debug("UploadContentServlet done");
}
}
}

View File

@@ -1,107 +1,107 @@
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter;
import org.alfresco.repo.webdav.auth.BaseAuthenticationFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
import org.springframework.extensions.webscripts.Match;
import org.springframework.extensions.webscripts.RuntimeContainer;
/**
* WebScript aware Authentication Filter Class. Takes into account the authentication setting in the descriptor for the
* webscript before chaining to the downstream authentication filters. If authentication is not required then chains
* with the NO_AUTH_REQUIRED request attribute set, which should cause any downstream authentication filter to bypass
* authentication checks.
*
* @author Kevin Roast
* @author dward
*/
public class WebScriptSSOAuthenticationFilter extends BaseAuthenticationFilter implements DependencyInjectedFilter,
ActivateableBean
{
private static final Log logger = LogFactory.getLog(WebScriptSSOAuthenticationFilter.class);
private RuntimeContainer container;
private boolean isActive = true;
/**
* @param container the container to set
*/
public void setContainer(RuntimeContainer container)
{
this.container = container;
}
/**
* Activates or deactivates the bean
*
* @param active
* <code>true</code> if the bean is active and initialization should complete
*/
public final void setActive(boolean active)
{
this.isActive = active;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
*/
public final boolean isActive()
{
return isActive;
}
/* (non-Javadoc)
* @see org.alfresco.repo.webdav.auth.BaseNTLMAuthenticationFilter#doFilter(javax.servlet.ServletContext, javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletContext context, ServletRequest sreq, ServletResponse sresp, FilterChain chain)
throws IOException, ServletException
{
// Get the HTTP request/response
HttpServletRequest req = (HttpServletRequest)sreq;
// find a webscript match for the requested URI
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring((req.getContextPath() + req.getServletPath()).length());
if (getLogger().isDebugEnabled())
getLogger().debug("Processing request: " + requestURI + " SID:" +
(req.getSession(false) != null ? req.getSession().getId() : null));
Match match = container.getRegistry().findWebScript(req.getMethod(), URLDecoder.decode(pathInfo));
if (match != null && match.getWebScript() != null)
{
// check the authentication required - if none then we don't want any of
// the filters down the chain to require any authentication checks
if (RequiredAuthentication.none == match.getWebScript().getDescription().getRequiredAuthentication())
{
if (getLogger().isDebugEnabled())
getLogger().debug("Found webscript with no authentication - set NO_AUTH_REQUIRED flag.");
req.setAttribute(NO_AUTH_REQUIRED, Boolean.TRUE);
}
}
chain.doFilter(sreq, sresp);
}
/* (non-Javadoc)
* @see org.alfresco.repo.webdav.auth.BaseAuthenticationFilter#getLogger()
*/
@Override
protected Log getLogger()
{
return logger;
}
}
package org.alfresco.web.app.servlet;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.repo.management.subsystems.ActivateableBean;
import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter;
import org.alfresco.repo.webdav.auth.BaseAuthenticationFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.URLDecoder;
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
import org.springframework.extensions.webscripts.Match;
import org.springframework.extensions.webscripts.RuntimeContainer;
/**
* WebScript aware Authentication Filter Class. Takes into account the authentication setting in the descriptor for the
* webscript before chaining to the downstream authentication filters. If authentication is not required then chains
* with the NO_AUTH_REQUIRED request attribute set, which should cause any downstream authentication filter to bypass
* authentication checks.
*
* @author Kevin Roast
* @author dward
*/
public class WebScriptSSOAuthenticationFilter extends BaseAuthenticationFilter implements DependencyInjectedFilter,
ActivateableBean
{
private static final Log logger = LogFactory.getLog(WebScriptSSOAuthenticationFilter.class);
private RuntimeContainer container;
private boolean isActive = true;
/**
* @param container the container to set
*/
public void setContainer(RuntimeContainer container)
{
this.container = container;
}
/**
* Activates or deactivates the bean
*
* @param active
* <code>true</code> if the bean is active and initialization should complete
*/
public final void setActive(boolean active)
{
this.isActive = active;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
*/
public final boolean isActive()
{
return isActive;
}
/* (non-Javadoc)
* @see org.alfresco.repo.webdav.auth.BaseNTLMAuthenticationFilter#doFilter(javax.servlet.ServletContext, javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletContext context, ServletRequest sreq, ServletResponse sresp, FilterChain chain)
throws IOException, ServletException
{
// Get the HTTP request/response
HttpServletRequest req = (HttpServletRequest)sreq;
// find a webscript match for the requested URI
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring((req.getContextPath() + req.getServletPath()).length());
if (getLogger().isDebugEnabled())
getLogger().debug("Processing request: " + requestURI + " SID:" +
(req.getSession(false) != null ? req.getSession().getId() : null));
Match match = container.getRegistry().findWebScript(req.getMethod(), URLDecoder.decode(pathInfo));
if (match != null && match.getWebScript() != null)
{
// check the authentication required - if none then we don't want any of
// the filters down the chain to require any authentication checks
if (RequiredAuthentication.none == match.getWebScript().getDescription().getRequiredAuthentication())
{
if (getLogger().isDebugEnabled())
getLogger().debug("Found webscript with no authentication - set NO_AUTH_REQUIRED flag.");
req.setAttribute(NO_AUTH_REQUIRED, Boolean.TRUE);
}
}
chain.doFilter(sreq, sresp);
}
/* (non-Javadoc)
* @see org.alfresco.repo.webdav.auth.BaseAuthenticationFilter#getLogger()
*/
@Override
protected Log getLogger()
{
return logger;
}
}

View File

@@ -1,37 +1,37 @@
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Interface for all Ajax commands executed by this servlet.
*
* The method is responsible for invoking the underlying managed bean
* and dealing with the response.
*
* @author gavinc
*/
public interface AjaxCommand
{
/**
* Invokes the relevant method on the bean represented by the given
* expression. Parameters required to call the method can be retrieved
* from the request.
*
* Currently the content type of the response will always be text/xml, in the
* future sublcasses may provide a mechanism to allow the content type to be set
* dynamically.
*
* @param facesContext FacesContext
* @param expression The binding expression
* @param request The request
* @param response The response
*/
public abstract void execute(FacesContext facesContext, String expression,
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Interface for all Ajax commands executed by this servlet.
*
* The method is responsible for invoking the underlying managed bean
* and dealing with the response.
*
* @author gavinc
*/
public interface AjaxCommand
{
/**
* Invokes the relevant method on the bean represented by the given
* expression. Parameters required to call the method can be retrieved
* from the request.
*
* Currently the content type of the response will always be text/xml, in the
* future sublcasses may provide a mechanism to allow the content type to be set
* dynamically.
*
* @param facesContext FacesContext
* @param expression The binding expression
* @param request The request
* @param response The response
*/
public abstract void execute(FacesContext facesContext, String expression,
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}

View File

@@ -1,197 +1,197 @@
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import java.util.Enumeration;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.acegisecurity.context.ContextHolder;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for processing AJAX requests.
*
* The URL to the servlet should be in the form:
* <pre>/alfresco/ajax/command/Bean.binding.expression</pre>
* <p>
* See http://wiki.alfresco.com/wiki/AJAX_Support for details.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
*
* @author gavinc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class AjaxServlet extends BaseServlet
{
public static final String AJAX_LOG_KEY = "alfresco.ajax";
protected enum Command { invoke, get, set};
private static final long serialVersionUID = -7654769105419391840L;
private static Log logger = LogFactory.getLog(AJAX_LOG_KEY);
private static Log headersLogger = LogFactory.getLog(AJAX_LOG_KEY + ".headers");
private static Log perfLogger = LogFactory.getLog(AJAX_LOG_KEY + ".performance");
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void service(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
request.setCharacterEncoding("utf-8");
// set default character encoding for the response
response.setCharacterEncoding("utf-8");
response.setContentType("text/xml;charset=UTF-8");
long startTime = 0;
String uri = request.getRequestURI();
if (logger.isDebugEnabled())
{
final String queryString = request.getQueryString();
logger.debug("Processing URL: " + uri +
((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
}
// dump the request headers
if (headersLogger.isDebugEnabled())
{
final Enumeration<?> headers = request.getHeaderNames();
while (headers.hasMoreElements())
{
final String name = (String)headers.nextElement();
headersLogger.debug(name + ": " + request.getHeader(name));
}
}
try
{
// Make sure the user is authenticated, if not throw an error to return the
// 500 Internal Server Error code back to the client
AuthenticationStatus status = servletAuthenticate(request, response, false);
if (status == AuthenticationStatus.Failure)
{
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Access Denied: User not authenticated");
return;
}
setNoCacheHeaders(response);
uri = uri.substring(request.getContextPath().length() + "/".length());
final String[] tokens = uri.split("/");
if (tokens.length < 3)
{
throw new AlfrescoRuntimeException("Servlet URL did not contain all required args: " + uri);
}
// retrieve the command from the URL
final String commandName = tokens[1];
// retrieve the binding expression from the URL
final String expression = tokens[2];
// setup the faces context
final FacesContext facesContext = FacesHelper.getFacesContext(request, response, getServletContext());
// start a timer
if (perfLogger.isDebugEnabled())
startTime = System.currentTimeMillis();
// instantiate the relevant command
AjaxCommand command = null;
if (Command.invoke.toString().equals(commandName))
{
command = new InvokeCommand();
}
else if (Command.get.toString().equals(commandName))
{
command = new GetCommand();
}
else
{
throw new AlfrescoRuntimeException("Unrecognised command received: " + commandName);
}
// execute the command
command.execute(facesContext, expression, request, response);
}
catch (RuntimeException error)
{
handleError(response, error);
}
finally
{
// measure the time taken
if (perfLogger.isDebugEnabled())
{
perfLogger.debug("Time to execute command: " + (System.currentTimeMillis() - startTime) + "ms");
}
ContextHolder.setContext(null);
}
}
/**
* Handles any error that occurs during the execution of the servlet
*
* @param response The response
* @param cause The cause of the error
*/
protected void handleError(HttpServletResponse response, RuntimeException cause)
throws ServletException, IOException
{
// if we can send back the 500 error with the error from the top of the
// stack as the error status message.
// NOTE: if we use the built in support for generating error pages for
// 500 errors we can tailor the output for AJAX calls so that the
// body of the response can be used to show the error details.
if (!response.isCommitted())
{
// dump the error if debugging is enabled
if (logger.isDebugEnabled())
{
logger.error(cause);
Throwable theCause = cause.getCause();
if (theCause != null)
{
logger.error("caused by: ", theCause);
}
}
// extract a message from the exception
String msg = cause.getMessage();
if (msg == null)
{
msg = cause.toString();
}
// ALF-9036. We need to trap incomplete sessions
if (cause instanceof IllegalStateException)
{
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, cause.getMessage());
}
else
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
}
}
else
{
// the response has already been comitted, not much we can do but
// let the error through and let the container deal with it
throw cause;
}
}
}
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import java.util.Enumeration;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.acegisecurity.context.ContextHolder;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Servlet responsible for processing AJAX requests.
*
* The URL to the servlet should be in the form:
* <pre>/alfresco/ajax/command/Bean.binding.expression</pre>
* <p>
* See http://wiki.alfresco.com/wiki/AJAX_Support for details.
* <p>
* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication:
* ?ticket=1234567890
*
* @author gavinc
* @deprecated 5.0 not exposed in web-client web.xml
*/
public class AjaxServlet extends BaseServlet
{
public static final String AJAX_LOG_KEY = "alfresco.ajax";
protected enum Command { invoke, get, set};
private static final long serialVersionUID = -7654769105419391840L;
private static Log logger = LogFactory.getLog(AJAX_LOG_KEY);
private static Log headersLogger = LogFactory.getLog(AJAX_LOG_KEY + ".headers");
private static Log perfLogger = LogFactory.getLog(AJAX_LOG_KEY + ".performance");
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void service(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
request.setCharacterEncoding("utf-8");
// set default character encoding for the response
response.setCharacterEncoding("utf-8");
response.setContentType("text/xml;charset=UTF-8");
long startTime = 0;
String uri = request.getRequestURI();
if (logger.isDebugEnabled())
{
final String queryString = request.getQueryString();
logger.debug("Processing URL: " + uri +
((queryString != null && queryString.length() > 0) ? ("?" + queryString) : ""));
}
// dump the request headers
if (headersLogger.isDebugEnabled())
{
final Enumeration<?> headers = request.getHeaderNames();
while (headers.hasMoreElements())
{
final String name = (String)headers.nextElement();
headersLogger.debug(name + ": " + request.getHeader(name));
}
}
try
{
// Make sure the user is authenticated, if not throw an error to return the
// 500 Internal Server Error code back to the client
AuthenticationStatus status = servletAuthenticate(request, response, false);
if (status == AuthenticationStatus.Failure)
{
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Access Denied: User not authenticated");
return;
}
setNoCacheHeaders(response);
uri = uri.substring(request.getContextPath().length() + "/".length());
final String[] tokens = uri.split("/");
if (tokens.length < 3)
{
throw new AlfrescoRuntimeException("Servlet URL did not contain all required args: " + uri);
}
// retrieve the command from the URL
final String commandName = tokens[1];
// retrieve the binding expression from the URL
final String expression = tokens[2];
// setup the faces context
final FacesContext facesContext = FacesHelper.getFacesContext(request, response, getServletContext());
// start a timer
if (perfLogger.isDebugEnabled())
startTime = System.currentTimeMillis();
// instantiate the relevant command
AjaxCommand command = null;
if (Command.invoke.toString().equals(commandName))
{
command = new InvokeCommand();
}
else if (Command.get.toString().equals(commandName))
{
command = new GetCommand();
}
else
{
throw new AlfrescoRuntimeException("Unrecognised command received: " + commandName);
}
// execute the command
command.execute(facesContext, expression, request, response);
}
catch (RuntimeException error)
{
handleError(response, error);
}
finally
{
// measure the time taken
if (perfLogger.isDebugEnabled())
{
perfLogger.debug("Time to execute command: " + (System.currentTimeMillis() - startTime) + "ms");
}
ContextHolder.setContext(null);
}
}
/**
* Handles any error that occurs during the execution of the servlet
*
* @param response The response
* @param cause The cause of the error
*/
protected void handleError(HttpServletResponse response, RuntimeException cause)
throws ServletException, IOException
{
// if we can send back the 500 error with the error from the top of the
// stack as the error status message.
// NOTE: if we use the built in support for generating error pages for
// 500 errors we can tailor the output for AJAX calls so that the
// body of the response can be used to show the error details.
if (!response.isCommitted())
{
// dump the error if debugging is enabled
if (logger.isDebugEnabled())
{
logger.error(cause);
Throwable theCause = cause.getCause();
if (theCause != null)
{
logger.error("caused by: ", theCause);
}
}
// extract a message from the exception
String msg = cause.getMessage();
if (msg == null)
{
msg = cause.toString();
}
// ALF-9036. We need to trap incomplete sessions
if (cause instanceof IllegalStateException)
{
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, cause.getMessage());
}
else
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
}
}
else
{
// the response has already been comitted, not much we can do but
// let the error through and let the container deal with it
throw cause;
}
}
}

View File

@@ -1,19 +1,19 @@
package org.alfresco.web.app.servlet.ajax;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for all Ajax based commands
*
* @author gavinc
*/
public abstract class BaseAjaxCommand implements AjaxCommand
{
protected static Log logger = LogFactory.getLog(AjaxServlet.AJAX_LOG_KEY);
public String makeBindingExpression(String expression)
{
return "#{" + expression + "}";
}
}
package org.alfresco.web.app.servlet.ajax;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class for all Ajax based commands
*
* @author gavinc
*/
public abstract class BaseAjaxCommand implements AjaxCommand
{
protected static Log logger = LogFactory.getLog(AjaxServlet.AJAX_LOG_KEY);
public String makeBindingExpression(String expression)
{
return "#{" + expression + "}";
}
}

View File

@@ -1,69 +1,69 @@
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
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.web.bean.repository.Repository;
/**
* Command that executes the given value binding expression.
* <p>
* This command is intended to be used for calling existing managed
* bean methods. The result of the value binding is added to
* the response as is i.e. by calling toString().
* The content type of the response is always text/html.
*
* @author gavinc
*/
public class GetCommand extends BaseAjaxCommand
{
public void execute(FacesContext facesContext, String expression,
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// create the JSF binding expression
String bindingExpr = makeBindingExpression(expression);
if (logger.isDebugEnabled())
logger.debug("Retrieving value from value binding: " + bindingExpr);
UserTransaction tx = null;
try
{
// create the value binding
ValueBinding binding = facesContext.getApplication().
createValueBinding(bindingExpr);
if (binding != null)
{
// setup the transaction
tx = Repository.getUserTransaction(facesContext, true);
tx.begin();
// get the value from the value binding
Object value = binding.getValue(facesContext);
if (value != null)
{
response.getWriter().write(value.toString());
}
// commit
tx.commit();
}
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
throw new AlfrescoRuntimeException("Failed to retrieve value: " + err.getMessage(), err);
}
}
}
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
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.web.bean.repository.Repository;
/**
* Command that executes the given value binding expression.
* <p>
* This command is intended to be used for calling existing managed
* bean methods. The result of the value binding is added to
* the response as is i.e. by calling toString().
* The content type of the response is always text/html.
*
* @author gavinc
*/
public class GetCommand extends BaseAjaxCommand
{
public void execute(FacesContext facesContext, String expression,
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// create the JSF binding expression
String bindingExpr = makeBindingExpression(expression);
if (logger.isDebugEnabled())
logger.debug("Retrieving value from value binding: " + bindingExpr);
UserTransaction tx = null;
try
{
// create the value binding
ValueBinding binding = facesContext.getApplication().
createValueBinding(bindingExpr);
if (binding != null)
{
// setup the transaction
tx = Repository.getUserTransaction(facesContext, true);
tx.begin();
// get the value from the value binding
Object value = binding.getValue(facesContext);
if (value != null)
{
response.getWriter().write(value.toString());
}
// commit
tx.commit();
}
}
catch (Throwable err)
{
// rollback the transaction
try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
throw new AlfrescoRuntimeException("Failed to retrieve value: " + err.getMessage(), err);
}
}
}

View File

@@ -1,218 +1,218 @@
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
/**
* Command that invokes the method represented by the expression.
* <p>
* The managed bean method called is responsible for writing the response
* by getting hold of the JSF ResponseWriter. Parameters can also be
* retrieved via the JSF ExternalContext object.
* <p>
* In a future release (if required) annotations may be used to state
* what content type to use for the response.
*
* @author gavinc
*/
public class InvokeCommand extends BaseAjaxCommand
{
/////////////////////////////////////////////////////////////////////////////
/**
* Annotation for a bean method that handles an ajax request.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResponseMimetype
{
// NOTE: replaced Mimetype.MIMETYPE_XML with string literal due to bug
// http://bugs.sun.com/view_bug.do?bug_id=6512707 - causing build to fail
public String value() default "text/xml";
}
/////////////////////////////////////////////////////////////////////////////
public void execute(final FacesContext facesContext,
final String expression,
final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
ResponseWriter writer = null;
try
{
final int indexOfDot = expression.indexOf('.');
final String variableName = expression.substring(0, indexOfDot);
final String methodName = expression.substring(indexOfDot + 1);
if (logger.isDebugEnabled())
logger.debug("Invoking method represented by " + expression +
" on variable " + variableName +
" with method " + methodName);
Object bean = null;
if (Application.inPortalServer())
{
// retrieve the managed bean, this is really weak but if the
// request comes from a portal server the bean we need to get
// is in the session with a prefix chosen by the portal vendor,
// to cover this scenario we have to go through the names of
// all the objects in the session to find the bean we want.
String beanNameSuffix = "?" + variableName;
Enumeration<?> enumNames = request.getSession().getAttributeNames();
while (enumNames.hasMoreElements())
{
String name = (String)enumNames.nextElement();
if (name.endsWith(beanNameSuffix))
{
bean = request.getSession().getAttribute(name);
if (logger.isDebugEnabled())
logger.debug("Found bean " + bean + " in the session");
break;
}
}
}
// if we don't have the bean yet try and get it via the variable resolver
if (bean == null)
{
VariableResolver vr = facesContext.getApplication().getVariableResolver();
bean = vr.resolveVariable(facesContext, variableName);
if (logger.isDebugEnabled())
logger.debug("Created bean " + bean + " via the variable resolver");
}
final Method method = bean.getClass().getMethod(methodName);
final String responseMimetype =
(method.isAnnotationPresent(ResponseMimetype.class)
? method.getAnnotation(ResponseMimetype.class).value()
: MimetypeMap.MIMETYPE_XML);
if (logger.isDebugEnabled())
logger.debug("invoking method " + method +
" with repsonse mimetype " + responseMimetype);
writer = this.setupResponseWriter(responseMimetype,
response,
facesContext);
// setup the transaction
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
final Object beanFinal = bean;
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
// invoke the method
try
{
method.invoke(beanFinal);
return null;
}
// Let's prevent RuntimeExceptions being wrapped twice by unwrapping InvocationTargetExceptions
catch (InvocationTargetException e)
{
if (e.getCause() != null)
{
throw e.getCause();
}
throw e;
}
}
};
txnHelper.doInTransaction(callback);
}
catch (EvaluationException e)
{
Throwable err = e.getCause();
if (err == null)
{
logger.error("Failed to execute method " + expression + ": " + e.getMessage(), e);
throw e;
}
else
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
if (err instanceof RuntimeException)
{
throw (RuntimeException)err;
}
else
{
throw new AlfrescoRuntimeException("Failed to execute method " + expression + ": " + err.getMessage(), err);
}
}
}
catch (RuntimeException err)
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
throw err;
}
catch (Exception err)
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
throw new AlfrescoRuntimeException("Failed to execute method " + expression + ": " + err.getMessage(), err);
}
// force the output back to the client
writer.close();
}
/** setup the JSF response writer. */
private ResponseWriter setupResponseWriter(final String mimetype,
final HttpServletResponse response,
final FacesContext facesContext)
throws IOException
{
final OutputStream os = response.getOutputStream();
final UIViewRoot viewRoot = facesContext.getViewRoot();
final RenderKitFactory renderFactory = (RenderKitFactory)
FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
final RenderKit renderKit =
renderFactory.getRenderKit(facesContext, viewRoot.getRenderKitId());
final ResponseWriter writer =
renderKit.createResponseWriter(new OutputStreamWriter(os, "UTF-8"),
mimetype,
"UTF-8");
facesContext.setResponseWriter(writer);
// must be text/xml otherwise IE doesn't parse the response properly into responseXML
response.setContentType(mimetype);
return writer;
}
}
package org.alfresco.web.app.servlet.ajax;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import javax.faces.FactoryFinder;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
/**
* Command that invokes the method represented by the expression.
* <p>
* The managed bean method called is responsible for writing the response
* by getting hold of the JSF ResponseWriter. Parameters can also be
* retrieved via the JSF ExternalContext object.
* <p>
* In a future release (if required) annotations may be used to state
* what content type to use for the response.
*
* @author gavinc
*/
public class InvokeCommand extends BaseAjaxCommand
{
/////////////////////////////////////////////////////////////////////////////
/**
* Annotation for a bean method that handles an ajax request.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResponseMimetype
{
// NOTE: replaced Mimetype.MIMETYPE_XML with string literal due to bug
// http://bugs.sun.com/view_bug.do?bug_id=6512707 - causing build to fail
public String value() default "text/xml";
}
/////////////////////////////////////////////////////////////////////////////
public void execute(final FacesContext facesContext,
final String expression,
final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
ResponseWriter writer = null;
try
{
final int indexOfDot = expression.indexOf('.');
final String variableName = expression.substring(0, indexOfDot);
final String methodName = expression.substring(indexOfDot + 1);
if (logger.isDebugEnabled())
logger.debug("Invoking method represented by " + expression +
" on variable " + variableName +
" with method " + methodName);
Object bean = null;
if (Application.inPortalServer())
{
// retrieve the managed bean, this is really weak but if the
// request comes from a portal server the bean we need to get
// is in the session with a prefix chosen by the portal vendor,
// to cover this scenario we have to go through the names of
// all the objects in the session to find the bean we want.
String beanNameSuffix = "?" + variableName;
Enumeration<?> enumNames = request.getSession().getAttributeNames();
while (enumNames.hasMoreElements())
{
String name = (String)enumNames.nextElement();
if (name.endsWith(beanNameSuffix))
{
bean = request.getSession().getAttribute(name);
if (logger.isDebugEnabled())
logger.debug("Found bean " + bean + " in the session");
break;
}
}
}
// if we don't have the bean yet try and get it via the variable resolver
if (bean == null)
{
VariableResolver vr = facesContext.getApplication().getVariableResolver();
bean = vr.resolveVariable(facesContext, variableName);
if (logger.isDebugEnabled())
logger.debug("Created bean " + bean + " via the variable resolver");
}
final Method method = bean.getClass().getMethod(methodName);
final String responseMimetype =
(method.isAnnotationPresent(ResponseMimetype.class)
? method.getAnnotation(ResponseMimetype.class).value()
: MimetypeMap.MIMETYPE_XML);
if (logger.isDebugEnabled())
logger.debug("invoking method " + method +
" with repsonse mimetype " + responseMimetype);
writer = this.setupResponseWriter(responseMimetype,
response,
facesContext);
// setup the transaction
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
final Object beanFinal = bean;
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
// invoke the method
try
{
method.invoke(beanFinal);
return null;
}
// Let's prevent RuntimeExceptions being wrapped twice by unwrapping InvocationTargetExceptions
catch (InvocationTargetException e)
{
if (e.getCause() != null)
{
throw e.getCause();
}
throw e;
}
}
};
txnHelper.doInTransaction(callback);
}
catch (EvaluationException e)
{
Throwable err = e.getCause();
if (err == null)
{
logger.error("Failed to execute method " + expression + ": " + e.getMessage(), e);
throw e;
}
else
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
if (err instanceof RuntimeException)
{
throw (RuntimeException)err;
}
else
{
throw new AlfrescoRuntimeException("Failed to execute method " + expression + ": " + err.getMessage(), err);
}
}
}
catch (RuntimeException err)
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
throw err;
}
catch (Exception err)
{
logger.error("Failed to execute method " + expression + ": " + err.getMessage(), err);
throw new AlfrescoRuntimeException("Failed to execute method " + expression + ": " + err.getMessage(), err);
}
// force the output back to the client
writer.close();
}
/** setup the JSF response writer. */
private ResponseWriter setupResponseWriter(final String mimetype,
final HttpServletResponse response,
final FacesContext facesContext)
throws IOException
{
final OutputStream os = response.getOutputStream();
final UIViewRoot viewRoot = facesContext.getViewRoot();
final RenderKitFactory renderFactory = (RenderKitFactory)
FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
final RenderKit renderKit =
renderFactory.getRenderKit(facesContext, viewRoot.getRenderKitId());
final ResponseWriter writer =
renderKit.createResponseWriter(new OutputStreamWriter(os, "UTF-8"),
mimetype,
"UTF-8");
facesContext.setResponseWriter(writer);
// must be text/xml otherwise IE doesn't parse the response properly into responseXML
response.setContentType(mimetype);
return writer;
}
}

View File

@@ -1,45 +1,45 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.workflow.WorkflowUtil;
/**
* Approve Workflow command implementation
*
* @author Kevin Roast
*/
public final class ApproveWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ApproveCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.approve(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
return true;
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.workflow.WorkflowUtil;
/**
* Approve Workflow command implementation
*
* @author Kevin Roast
*/
public final class ApproveWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ApproveCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.approve(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
return true;
}
}

View File

@@ -1,47 +1,47 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Repository;
/**
* Initial implementation of a Command Processor that is always passed enough URL elements
* to construct a single NodeRef argument. The NodeRef is checked against READ permissions
* for the current user during the validateArguments() call.
* <p>
* This class should be enough to form the base of Command Processor objects that only require
* a single NodeRef passed on the URL.
*
* @author Kevin Roast
*/
public abstract class BaseNodeCommandProcessor implements CommandProcessor
{
protected NodeRef targetRef;
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
if (urlElements.length < 3)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
// get NodeRef to the node with the workflow attached to it
StoreRef storeRef = new StoreRef(urlElements[0], urlElements[1]);
this.targetRef = new NodeRef(storeRef, urlElements[2]);
// get the services we need to execute the workflow command
PermissionService permissionService = Repository.getServiceRegistry(sc).getPermissionService();
// check that the user has at least READ access on the node - else redirect to the login page
return (permissionService.hasPermission(this.targetRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.bean.repository.Repository;
/**
* Initial implementation of a Command Processor that is always passed enough URL elements
* to construct a single NodeRef argument. The NodeRef is checked against READ permissions
* for the current user during the validateArguments() call.
* <p>
* This class should be enough to form the base of Command Processor objects that only require
* a single NodeRef passed on the URL.
*
* @author Kevin Roast
*/
public abstract class BaseNodeCommandProcessor implements CommandProcessor
{
protected NodeRef targetRef;
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
if (urlElements.length < 3)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
// get NodeRef to the node with the workflow attached to it
StoreRef storeRef = new StoreRef(urlElements[0], urlElements[1]);
this.targetRef = new NodeRef(storeRef, urlElements[2]);
// get the services we need to execute the workflow command
PermissionService permissionService = Repository.getServiceRegistry(sc).getPermissionService();
// check that the user has at least READ access on the node - else redirect to the login page
return (permissionService.hasPermission(this.targetRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
}

View File

@@ -1,15 +1,15 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
/**
* @author Kevin Roast
*/
public abstract class BaseUIActionCommand implements Command
{
public static final String PROP_SERVLETCONTEXT = "ServletContext";
public static final String PROP_REQUEST = "Request";
public static final String PROP_RESPONSE = "Response";
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
/**
* @author Kevin Roast
*/
public abstract class BaseUIActionCommand implements Command
{
public static final String PROP_SERVLETCONTEXT = "ServletContext";
public static final String PROP_REQUEST = "Request";
public static final String PROP_RESPONSE = "Response";
}

View File

@@ -1,28 +1,28 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
/**
* Simple servlet command pattern interface.
*
* @author Kevin Roast
*/
public interface Command
{
/**
* Execute the command
*
* @param serviceRegistry The ServiceRegistry instance
* @param properties Bag of named properties for the command
*
* @return return value from the command if any
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties);
/**
* @return the names of the properties required for this command
*/
public String[] getPropertyNames();
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
/**
* Simple servlet command pattern interface.
*
* @author Kevin Roast
*/
public interface Command
{
/**
* Execute the command
*
* @param serviceRegistry The ServiceRegistry instance
* @param properties Bag of named properties for the command
*
* @return return value from the command if any
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties);
/**
* @return the names of the properties required for this command
*/
public String[] getPropertyNames();
}

View File

@@ -1,81 +1,81 @@
package org.alfresco.web.app.servlet.command;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Command Factory helper
*
* @author Kevin Roast
*/
public final class CommandFactory
{
private static Log logger = LogFactory.getLog(CommandFactory.class);
private static CommandFactory instance = new CommandFactory();
private static Map<String, Class> registry = new HashMap<String, Class>(16, 1.0f);
/**
* Private constructor - protect the singleton instance
*/
private CommandFactory()
{
}
/**
* @return the singleton CommandFactory instance
*/
public static CommandFactory getInstance()
{
return instance;
}
/**
* Register a command name against an implementation
*
* @param name Unique name of the command
* @param clazz Class implementation of the command
*/
public void registerCommand(String name, Class clazz)
{
registry.put(name, clazz);
}
/**
* Create a command instance of the specified command name
*
* @param name Name of the command to create (must be registered)
*
* @return the Command instance or null if not found
*/
public Command createCommand(String name)
{
Command result = null;
// lookup command by name in the registry
Class clazz = registry.get(name);
if (clazz != null)
{
try
{
Object obj = clazz.newInstance();
if (obj instanceof Command)
{
result = (Command)obj;
}
}
catch (Throwable err)
{
// return default if this occurs
logger.warn("Unable to create workflow command instance '" + name +
"' with classname '" + clazz.getName() + "' due to error: " + err.getMessage());
}
}
return result;
}
}
package org.alfresco.web.app.servlet.command;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Command Factory helper
*
* @author Kevin Roast
*/
public final class CommandFactory
{
private static Log logger = LogFactory.getLog(CommandFactory.class);
private static CommandFactory instance = new CommandFactory();
private static Map<String, Class> registry = new HashMap<String, Class>(16, 1.0f);
/**
* Private constructor - protect the singleton instance
*/
private CommandFactory()
{
}
/**
* @return the singleton CommandFactory instance
*/
public static CommandFactory getInstance()
{
return instance;
}
/**
* Register a command name against an implementation
*
* @param name Unique name of the command
* @param clazz Class implementation of the command
*/
public void registerCommand(String name, Class clazz)
{
registry.put(name, clazz);
}
/**
* Create a command instance of the specified command name
*
* @param name Name of the command to create (must be registered)
*
* @return the Command instance or null if not found
*/
public Command createCommand(String name)
{
Command result = null;
// lookup command by name in the registry
Class clazz = registry.get(name);
if (clazz != null)
{
try
{
Object obj = clazz.newInstance();
if (obj instanceof Command)
{
result = (Command)obj;
}
}
catch (Throwable err)
{
// return default if this occurs
logger.warn("Unable to create workflow command instance '" + name +
"' with classname '" + clazz.getName() + "' due to error: " + err.getMessage());
}
}
return result;
}
}

View File

@@ -1,63 +1,63 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.service.ServiceRegistry;
/**
* This interfaces defines the contract and lifecycle of a Servlet Command Processor.
* <p>
* A command processor is defined as a class capable of executing a set of related Command
* objects. It performs the bulk of the work for the command servlet. The processor impl
* is responsible for validating that the command can be processed (given the supplied remaining
* URL arguments from the servlet) and processing the command. It is also responsible for
* supply an output status page on successfuly execution of the command.
* <p>
* The arguments passed to a Command Processor are the remaining URL elements from the command
* servlet URL after removing the web-app name, servlet name and command processor name.
*
* @author Kevin Roast
*/
public interface CommandProcessor
{
/**
* Pass and validate URL arguments for the command processor. Validate if the command can be
* executed given the arguments supplied. Generally at this post a Command Processor will
* convert the supplied arguments to the objects it expects, and also check any permissions
* that are required by the current user to execute the command.
*
* @param sc ServletContext, can be used to retrieve ServiceRegistry instance
* from the Repository bean.
* @param command Name of the command the arguments are for
* @param args Map of URL args passed to the command servlet
* @param urlElements String[] of the remaining URL arguments to the command servlet
*
* @return true if the command can be executed by the current user given the supplied args.
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements);
/**
* Process the supplied command name. It is the responsibility of the Command Processor
* to lookup the specified command name using the CommandFactory registry. For that reason
* it also has the responsiblity to initially register commands it is responsible for so
* they can be constructed later. If the supplied command is unknown to it then an
* exception should be thrown to indicate this.
*
* @param serviceRegistry ServiceRegistry
* @param request HttpServletRequest
* @param command Name of the command to construct and execute
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command);
/**
* Output a simple status message to the supplied PrintWriter.
* It can be assumed that the process() method was successful if this method is called.
*
* @param out PrintWriter
*/
public void outputStatus(PrintWriter out);
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.service.ServiceRegistry;
/**
* This interfaces defines the contract and lifecycle of a Servlet Command Processor.
* <p>
* A command processor is defined as a class capable of executing a set of related Command
* objects. It performs the bulk of the work for the command servlet. The processor impl
* is responsible for validating that the command can be processed (given the supplied remaining
* URL arguments from the servlet) and processing the command. It is also responsible for
* supply an output status page on successfuly execution of the command.
* <p>
* The arguments passed to a Command Processor are the remaining URL elements from the command
* servlet URL after removing the web-app name, servlet name and command processor name.
*
* @author Kevin Roast
*/
public interface CommandProcessor
{
/**
* Pass and validate URL arguments for the command processor. Validate if the command can be
* executed given the arguments supplied. Generally at this post a Command Processor will
* convert the supplied arguments to the objects it expects, and also check any permissions
* that are required by the current user to execute the command.
*
* @param sc ServletContext, can be used to retrieve ServiceRegistry instance
* from the Repository bean.
* @param command Name of the command the arguments are for
* @param args Map of URL args passed to the command servlet
* @param urlElements String[] of the remaining URL arguments to the command servlet
*
* @return true if the command can be executed by the current user given the supplied args.
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements);
/**
* Process the supplied command name. It is the responsibility of the Command Processor
* to lookup the specified command name using the CommandFactory registry. For that reason
* it also has the responsiblity to initially register commands it is responsible for so
* they can be constructed later. If the supplied command is unknown to it then an
* exception should be thrown to indicate this.
*
* @param serviceRegistry ServiceRegistry
* @param request HttpServletRequest
* @param command Name of the command to construct and execute
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command);
/**
* Output a simple status message to the supplied PrintWriter.
* It can be assumed that the process() method was successful if this method is called.
*
* @param out PrintWriter
*/
public void outputStatus(PrintWriter out);
}

View File

@@ -1,72 +1,72 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.repository.Node;
/**
* Command to execute the Edit Content Properties dialog via url.
* <p>
* Arguments: noderef - of the document to show the edit props dialog for
*
* @author Kevin Roast
*/
public class EditContentPropertiesCommand extends BaseUIActionCommand
{
public static final String PROP_NODEREF = "noderef";
private static final String[] PROPERTIES = new String[] {
PROP_SERVLETCONTEXT, PROP_REQUEST, PROP_RESPONSE, PROP_NODEREF};
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
ServletContext sc = (ServletContext)properties.get(PROP_SERVLETCONTEXT);
ServletRequest req = (ServletRequest)properties.get(PROP_REQUEST);
ServletResponse res = (ServletResponse)properties.get(PROP_RESPONSE);
FacesContext fc = FacesHelper.getFacesContext(req, res, sc, "/jsp/close.jsp");
BrowseBean browseBean = (BrowseBean)FacesHelper.getManagedBean(fc, BrowseBean.BEAN_NAME);
// setup context from url args in properties map
String strNodeRef = (String)properties.get(PROP_NODEREF);
ParameterCheck.mandatoryString(PROP_NODEREF, strNodeRef);
browseBean.setDocument(new Node(new NodeRef(strNodeRef)));
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(fc, null, "dialog:editContentProperties");
String viewId = fc.getViewRoot().getViewId();
try
{
sc.getRequestDispatcher(BaseServlet.FACES_SERVLET + viewId).forward(req, res);
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Unable to forward to viewId: " + viewId, e);
}
return null;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.BrowseBean;
import org.alfresco.web.bean.repository.Node;
/**
* Command to execute the Edit Content Properties dialog via url.
* <p>
* Arguments: noderef - of the document to show the edit props dialog for
*
* @author Kevin Roast
*/
public class EditContentPropertiesCommand extends BaseUIActionCommand
{
public static final String PROP_NODEREF = "noderef";
private static final String[] PROPERTIES = new String[] {
PROP_SERVLETCONTEXT, PROP_REQUEST, PROP_RESPONSE, PROP_NODEREF};
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
ServletContext sc = (ServletContext)properties.get(PROP_SERVLETCONTEXT);
ServletRequest req = (ServletRequest)properties.get(PROP_REQUEST);
ServletResponse res = (ServletResponse)properties.get(PROP_RESPONSE);
FacesContext fc = FacesHelper.getFacesContext(req, res, sc, "/jsp/close.jsp");
BrowseBean browseBean = (BrowseBean)FacesHelper.getManagedBean(fc, BrowseBean.BEAN_NAME);
// setup context from url args in properties map
String strNodeRef = (String)properties.get(PROP_NODEREF);
ParameterCheck.mandatoryString(PROP_NODEREF, strNodeRef);
browseBean.setDocument(new Node(new NodeRef(strNodeRef)));
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(fc, null, "dialog:editContentProperties");
String viewId = fc.getViewRoot().getViewId();
try
{
sc.getRequestDispatcher(BaseServlet.FACES_SERVLET + viewId).forward(req, res);
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Unable to forward to viewId: " + viewId, e);
}
return null;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
}

View File

@@ -1,44 +1,44 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.workflow.WorkflowService;
/**
* End Task command implementation
*
* @author David Caruana
*/
public final class EndTaskCommand implements Command
{
public static final String PROP_TASK_ID = "taskId";
public static final String PROP_TRANSITION = "transition";
private static final String[] PROPERTIES = new String[] {PROP_TASK_ID, PROP_TRANSITION};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
String taskId = (String)properties.get(PROP_TASK_ID);
if (taskId == null)
{
throw new IllegalArgumentException("Unable to execute EndTaskCommand - mandatory parameter not supplied: " + PROP_TASK_ID);
}
String transition = (String)properties.get(PROP_TRANSITION);
// end task
WorkflowService workflowService = serviceRegistry.getWorkflowService();
return workflowService.endTask(taskId, transition);
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.workflow.WorkflowService;
/**
* End Task command implementation
*
* @author David Caruana
*/
public final class EndTaskCommand implements Command
{
public static final String PROP_TASK_ID = "taskId";
public static final String PROP_TRANSITION = "transition";
private static final String[] PROPERTIES = new String[] {PROP_TASK_ID, PROP_TRANSITION};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
String taskId = (String)properties.get(PROP_TASK_ID);
if (taskId == null)
{
throw new IllegalArgumentException("Unable to execute EndTaskCommand - mandatory parameter not supplied: " + PROP_TASK_ID);
}
String transition = (String)properties.get(PROP_TRANSITION);
// end task
WorkflowService workflowService = serviceRegistry.getWorkflowService();
return workflowService.endTask(taskId, transition);
}
}

View File

@@ -1,81 +1,81 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
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.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
/**
* Execute Script command implementation.
* <p>
* Executes the supplied script against the default data-model.
*
* @author Kevin Roast
*/
public final class ExecuteScriptCommand implements Command
{
public static final String PROP_SCRIPT = "script";
public static final String PROP_DOCUMENT = "document";
public static final String PROP_USERPERSON = "person";
public static final String PROP_ARGS = "args";
private static final String[] PROPERTIES = new String[] {PROP_SCRIPT, PROP_DOCUMENT, PROP_USERPERSON, PROP_ARGS};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Script node for the command
NodeRef scriptRef = (NodeRef)properties.get(PROP_SCRIPT);
if (scriptRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_SCRIPT);
}
NodeRef personRef = (NodeRef)properties.get(PROP_USERPERSON);
if (personRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_USERPERSON);
}
// get the optional document and space context ref
NodeService nodeService = serviceRegistry.getNodeService();
NodeRef docRef = (NodeRef)properties.get(PROP_DOCUMENT);
NodeRef spaceRef = null;
if (docRef != null)
{
spaceRef = nodeService.getPrimaryParent(docRef).getParentRef();
}
// build the model needed to execute the script
Map<String, Object> model = serviceRegistry.getScriptService().buildDefaultModel(
personRef,
new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId()),
(NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER),
scriptRef,
docRef,
spaceRef);
// add the url arguments map
model.put("args", properties.get(PROP_ARGS));
// execute the script and return the result
return serviceRegistry.getScriptService().executeScript(scriptRef, null, model);
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
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.web.app.Application;
import org.alfresco.web.bean.repository.Repository;
/**
* Execute Script command implementation.
* <p>
* Executes the supplied script against the default data-model.
*
* @author Kevin Roast
*/
public final class ExecuteScriptCommand implements Command
{
public static final String PROP_SCRIPT = "script";
public static final String PROP_DOCUMENT = "document";
public static final String PROP_USERPERSON = "person";
public static final String PROP_ARGS = "args";
private static final String[] PROPERTIES = new String[] {PROP_SCRIPT, PROP_DOCUMENT, PROP_USERPERSON, PROP_ARGS};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Script node for the command
NodeRef scriptRef = (NodeRef)properties.get(PROP_SCRIPT);
if (scriptRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_SCRIPT);
}
NodeRef personRef = (NodeRef)properties.get(PROP_USERPERSON);
if (personRef == null)
{
throw new IllegalArgumentException(
"Unable to execute ExecuteScriptCommand - mandatory parameter not supplied: " + PROP_USERPERSON);
}
// get the optional document and space context ref
NodeService nodeService = serviceRegistry.getNodeService();
NodeRef docRef = (NodeRef)properties.get(PROP_DOCUMENT);
NodeRef spaceRef = null;
if (docRef != null)
{
spaceRef = nodeService.getPrimaryParent(docRef).getParentRef();
}
// build the model needed to execute the script
Map<String, Object> model = serviceRegistry.getScriptService().buildDefaultModel(
personRef,
new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId()),
(NodeRef)nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER),
scriptRef,
docRef,
spaceRef);
// add the url arguments map
model.put("args", properties.get(PROP_ARGS));
// execute the script and return the result
return serviceRegistry.getScriptService().executeScript(scriptRef, null, model);
}
}

View File

@@ -1,35 +1,35 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
/**
* This interfaces defines the contract and lifecycle of a Servlet Command Processor.
* <p>
* The ExtCommandProcessor adds an overloaded process() method to allow the
* HttpServletResponse to be passed.
*
* @author Kevin Roast
*/
public interface ExtCommandProcessor extends CommandProcessor
{
/**
* Process the supplied command name. It is the responsibility of the Command Processor
* to lookup the specified command name using the CommandFactory registry. For that reason
* it also has the responsiblity to initially register commands it is responsible for so
* they can be constructed later. If the supplied command is unknown to it then an
* exception should be thrown to indicate this.
*
* @param serviceRegistry ServiceRegistry
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param command Name of the command to construct and execute
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, HttpServletResponse response, String command);
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
/**
* This interfaces defines the contract and lifecycle of a Servlet Command Processor.
* <p>
* The ExtCommandProcessor adds an overloaded process() method to allow the
* HttpServletResponse to be passed.
*
* @author Kevin Roast
*/
public interface ExtCommandProcessor extends CommandProcessor
{
/**
* Process the supplied command name. It is the responsibility of the Command Processor
* to lookup the specified command name using the CommandFactory registry. For that reason
* it also has the responsiblity to initially register commands it is responsible for so
* they can be constructed later. If the supplied command is unknown to it then an
* exception should be thrown to indicate this.
*
* @param serviceRegistry ServiceRegistry
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param command Name of the command to construct and execute
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, HttpServletResponse response, String command);
}

View File

@@ -1,75 +1,75 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.workflow.WorkflowBean;
import org.springframework.extensions.surf.util.ParameterCheck;
/**
* Command to execute the Manage Task dialog via url.
* <p>
* Arguments: id = the id of the task
* type = the qname type of the task
*
* @author Kevin Roast
*/
public class ManageTaskDialogCommand extends BaseUIActionCommand
{
public static final String PROP_TASKID = "id";
public static final String PROP_TASKTYPE = "type";
private static final String[] PROPERTIES = new String[] {
PROP_SERVLETCONTEXT, PROP_REQUEST, PROP_RESPONSE, PROP_TASKID, PROP_TASKTYPE};
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
ServletContext sc = (ServletContext)properties.get(PROP_SERVLETCONTEXT);
ServletRequest req = (ServletRequest)properties.get(PROP_REQUEST);
ServletResponse res = (ServletResponse)properties.get(PROP_RESPONSE);
FacesContext fc = FacesHelper.getFacesContext(req, res, sc, "/jsp/close.jsp");
WorkflowBean wfBean = (WorkflowBean)FacesHelper.getManagedBean(fc, WorkflowBean.BEAN_NAME);
// setup dialog context from url args in properties map
String taskId = (String)properties.get(PROP_TASKID);
ParameterCheck.mandatoryString(PROP_TASKID, taskId);
String taskType = (String)properties.get(PROP_TASKTYPE);
ParameterCheck.mandatoryString(PROP_TASKTYPE, taskType);
wfBean.setupTaskDialog(taskId, taskType);
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(fc, null, "dialog:manageTask");
String viewId = fc.getViewRoot().getViewId();
try
{
sc.getRequestDispatcher(BaseServlet.FACES_SERVLET + viewId).forward(req, res);
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Unable to forward to viewId: " + viewId, e);
}
return null;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.workflow.WorkflowBean;
import org.springframework.extensions.surf.util.ParameterCheck;
/**
* Command to execute the Manage Task dialog via url.
* <p>
* Arguments: id = the id of the task
* type = the qname type of the task
*
* @author Kevin Roast
*/
public class ManageTaskDialogCommand extends BaseUIActionCommand
{
public static final String PROP_TASKID = "id";
public static final String PROP_TASKTYPE = "type";
private static final String[] PROPERTIES = new String[] {
PROP_SERVLETCONTEXT, PROP_REQUEST, PROP_RESPONSE, PROP_TASKID, PROP_TASKTYPE};
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
ServletContext sc = (ServletContext)properties.get(PROP_SERVLETCONTEXT);
ServletRequest req = (ServletRequest)properties.get(PROP_REQUEST);
ServletResponse res = (ServletResponse)properties.get(PROP_RESPONSE);
FacesContext fc = FacesHelper.getFacesContext(req, res, sc, "/jsp/close.jsp");
WorkflowBean wfBean = (WorkflowBean)FacesHelper.getManagedBean(fc, WorkflowBean.BEAN_NAME);
// setup dialog context from url args in properties map
String taskId = (String)properties.get(PROP_TASKID);
ParameterCheck.mandatoryString(PROP_TASKID, taskId);
String taskType = (String)properties.get(PROP_TASKTYPE);
ParameterCheck.mandatoryString(PROP_TASKTYPE, taskType);
wfBean.setupTaskDialog(taskId, taskType);
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
navigationHandler.handleNavigation(fc, null, "dialog:manageTask");
String viewId = fc.getViewRoot().getViewId();
try
{
sc.getRequestDispatcher(BaseServlet.FACES_SERVLET + viewId).forward(req, res);
}
catch (Exception e)
{
throw new AlfrescoRuntimeException("Unable to forward to viewId: " + viewId, e);
}
return null;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
}

View File

@@ -1,45 +1,45 @@
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.workflow.WorkflowUtil;
/**
* Reject Workflow command implementation
*
* @author Kevin Roast
*/
public final class RejectWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute RejectCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.reject(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
return true;
}
}
package org.alfresco.web.app.servlet.command;
import java.util.Map;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.web.bean.workflow.WorkflowUtil;
/**
* Reject Workflow command implementation
*
* @author Kevin Roast
*/
public final class RejectWorkflowCommand implements Command
{
public static final String PROP_TARGET = "target";
private static final String[] PROPERTIES = new String[] {PROP_TARGET};
/**
* @see org.alfresco.web.app.servlet.command.Command#getPropertyNames()
*/
public String[] getPropertyNames()
{
return PROPERTIES;
}
/**
* @see org.alfresco.web.app.servlet.command.Command#execute(org.alfresco.service.ServiceRegistry, java.util.Map)
*/
public Object execute(ServiceRegistry serviceRegistry, Map<String, Object> properties)
{
// get the target Node for the command
NodeRef nodeRef = (NodeRef)properties.get(PROP_TARGET);
if (nodeRef == null)
{
throw new IllegalArgumentException(
"Unable to execute RejectCommand - mandatory parameter not supplied: " + PROP_TARGET);
}
WorkflowUtil.reject(nodeRef, serviceRegistry.getNodeService(), serviceRegistry.getCopyService());
return true;
}
}

View File

@@ -1,143 +1,143 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.ClientConfigElement;
import org.springframework.extensions.config.ConfigService;
/**
* Script command processor implementation.
* <p>
* Responsible for executing 'execute' script commands on a Node.
*
* @author Kevin Roast
*/
public final class ScriptCommandProcessor implements CommandProcessor
{
private static final String ARG_SCRIPT_PATH = "scriptPath";
private static final String ARG_CONTEXT_PATH = "contextPath";
private NodeRef scriptRef;
private NodeRef docRef;
private Object result;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("execute", ExecuteScriptCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
boolean allowed = false;
String scriptPath = args.get(ARG_SCRIPT_PATH);
if (scriptPath != null)
{
// resolve path to a node
this.scriptRef = BaseServlet.resolveNamePath(sc, scriptPath).NodeRef;
// same for the document context path if specified
String docPath = args.get(ARG_CONTEXT_PATH);
if (docPath != null)
{
this.docRef = BaseServlet.resolveNamePath(sc, docPath).NodeRef;
}
}
else
{
if (urlElements.length < 3)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
// get NodeRef to the node script to execute
StoreRef storeRef = new StoreRef(urlElements[0], urlElements[1]);
this.scriptRef = new NodeRef(storeRef, urlElements[2]);
if (urlElements.length >= 6)
{
storeRef = new StoreRef(urlElements[3], urlElements[4]);
this.docRef = new NodeRef(storeRef, urlElements[5]);
}
}
// check we can READ access the nodes specified
PermissionService ps = Repository.getServiceRegistry(sc).getPermissionService();
allowed = (ps.hasPermission(this.scriptRef, PermissionService.READ) == AccessStatus.ALLOWED);
if (this.docRef != null)
{
allowed &= (ps.hasPermission(this.docRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
// check to see if user is allowed to execute arbituary javascript
// by default only an admin authority can perform this action
ConfigService configService = Application.getConfigService(sc);
ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client");
boolean allowScriptExecute = configElement.getAllowUserScriptExecute();
AuthorityService authService = Repository.getServiceRegistry(sc).getAuthorityService();
allowed &= (allowScriptExecute || authService.isAdminAuthority(AuthenticationUtil.getFullyAuthenticatedUser()));
return allowed;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(4, 1.0f);
properties.put(ExecuteScriptCommand.PROP_SCRIPT, this.scriptRef);
properties.put(ExecuteScriptCommand.PROP_DOCUMENT, this.docRef);
User user = Application.getCurrentUser(request.getSession());
properties.put(ExecuteScriptCommand.PROP_USERPERSON, user.getPerson());
// add URL arguments as a special Scriptable Map property called 'args'
Map<String, String> args = new ScriptableHashMap<String, String>();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
args.put(name, request.getParameter(name));
}
properties.put(ExecuteScriptCommand.PROP_ARGS, args);
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered script command specified: " + command);
}
this.result = cmd.execute(serviceRegistry, properties);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.write(this.result != null ? this.result.toString() : "Successfully executed script.");
}
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.config.ClientConfigElement;
import org.springframework.extensions.config.ConfigService;
/**
* Script command processor implementation.
* <p>
* Responsible for executing 'execute' script commands on a Node.
*
* @author Kevin Roast
*/
public final class ScriptCommandProcessor implements CommandProcessor
{
private static final String ARG_SCRIPT_PATH = "scriptPath";
private static final String ARG_CONTEXT_PATH = "contextPath";
private NodeRef scriptRef;
private NodeRef docRef;
private Object result;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("execute", ExecuteScriptCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
boolean allowed = false;
String scriptPath = args.get(ARG_SCRIPT_PATH);
if (scriptPath != null)
{
// resolve path to a node
this.scriptRef = BaseServlet.resolveNamePath(sc, scriptPath).NodeRef;
// same for the document context path if specified
String docPath = args.get(ARG_CONTEXT_PATH);
if (docPath != null)
{
this.docRef = BaseServlet.resolveNamePath(sc, docPath).NodeRef;
}
}
else
{
if (urlElements.length < 3)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
// get NodeRef to the node script to execute
StoreRef storeRef = new StoreRef(urlElements[0], urlElements[1]);
this.scriptRef = new NodeRef(storeRef, urlElements[2]);
if (urlElements.length >= 6)
{
storeRef = new StoreRef(urlElements[3], urlElements[4]);
this.docRef = new NodeRef(storeRef, urlElements[5]);
}
}
// check we can READ access the nodes specified
PermissionService ps = Repository.getServiceRegistry(sc).getPermissionService();
allowed = (ps.hasPermission(this.scriptRef, PermissionService.READ) == AccessStatus.ALLOWED);
if (this.docRef != null)
{
allowed &= (ps.hasPermission(this.docRef, PermissionService.READ) == AccessStatus.ALLOWED);
}
// check to see if user is allowed to execute arbituary javascript
// by default only an admin authority can perform this action
ConfigService configService = Application.getConfigService(sc);
ClientConfigElement configElement = (ClientConfigElement)configService.getGlobalConfig().getConfigElement("client");
boolean allowScriptExecute = configElement.getAllowUserScriptExecute();
AuthorityService authService = Repository.getServiceRegistry(sc).getAuthorityService();
allowed &= (allowScriptExecute || authService.isAdminAuthority(AuthenticationUtil.getFullyAuthenticatedUser()));
return allowed;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(4, 1.0f);
properties.put(ExecuteScriptCommand.PROP_SCRIPT, this.scriptRef);
properties.put(ExecuteScriptCommand.PROP_DOCUMENT, this.docRef);
User user = Application.getCurrentUser(request.getSession());
properties.put(ExecuteScriptCommand.PROP_USERPERSON, user.getPerson());
// add URL arguments as a special Scriptable Map property called 'args'
Map<String, String> args = new ScriptableHashMap<String, String>();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements())
{
String name = (String)names.nextElement();
args.put(name, request.getParameter(name));
}
properties.put(ExecuteScriptCommand.PROP_ARGS, args);
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered script command specified: " + command);
}
this.result = cmd.execute(serviceRegistry, properties);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.write(this.result != null ? this.result.toString() : "Successfully executed script.");
}
}

View File

@@ -1,84 +1,84 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.bean.workflow.WorkflowUtil;
import org.alfresco.web.ui.common.Utils;
/**
* Task specific command processor implementation.
* <p>
* Responsible for executing workflow task operations.
*
* @author David Caruana
*/
public final class TaskCommandProcessor implements CommandProcessor
{
private String taskId;
private String transition = null;
private String command;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("end", EndTaskCommand.class);
}
/* (non-Javadoc)
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String cmd, Map<String, String> args, String[] urlElements)
{
if (urlElements.length == 0)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
taskId = urlElements[0];
if (urlElements.length == 2)
{
transition = urlElements[1];
}
return WorkflowUtil.isTaskEditable(taskId, sc);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String commandName)
{
Map<String, Object> properties = new HashMap<String, Object>(1, 1.0f);
// all workflow commands use a "target" Node property as an argument
properties.put(EndTaskCommand.PROP_TASK_ID, taskId);
if (transition != null)
{
properties.put(EndTaskCommand.PROP_TRANSITION, transition);
}
Command cmd = CommandFactory.getInstance().createCommand(commandName);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered workflow command specified: " + commandName);
}
cmd.execute(serviceRegistry, properties);
this.command = commandName;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("Task command: '");
out.print(Utils.encode(command));
out.print("' executed against task: ");
out.println(Utils.encode(taskId));
}
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.bean.workflow.WorkflowUtil;
import org.alfresco.web.ui.common.Utils;
/**
* Task specific command processor implementation.
* <p>
* Responsible for executing workflow task operations.
*
* @author David Caruana
*/
public final class TaskCommandProcessor implements CommandProcessor
{
private String taskId;
private String transition = null;
private String command;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("end", EndTaskCommand.class);
}
/* (non-Javadoc)
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String cmd, Map<String, String> args, String[] urlElements)
{
if (urlElements.length == 0)
{
throw new IllegalArgumentException("Not enough URL arguments passed to command servlet.");
}
taskId = urlElements[0];
if (urlElements.length == 2)
{
transition = urlElements[1];
}
return WorkflowUtil.isTaskEditable(taskId, sc);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String commandName)
{
Map<String, Object> properties = new HashMap<String, Object>(1, 1.0f);
// all workflow commands use a "target" Node property as an argument
properties.put(EndTaskCommand.PROP_TASK_ID, taskId);
if (transition != null)
{
properties.put(EndTaskCommand.PROP_TRANSITION, transition);
}
Command cmd = CommandFactory.getInstance().createCommand(commandName);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered workflow command specified: " + commandName);
}
cmd.execute(serviceRegistry, properties);
this.command = commandName;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("Task command: '");
out.print(Utils.encode(command));
out.print("' executed against task: ");
out.println(Utils.encode(taskId));
}
}

View File

@@ -1,112 +1,112 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.bean.workflow.WorkflowUtil;
import org.alfresco.web.ui.common.Utils;
/**
* UI action command processor implementation.
* <p>
* Responsible for executing specific UI actions via a REST style URL interface.
* <p>
* The URL postfix for each specific command depends on the context that is required
* for that command. For example, a command to launch the Create Web Content dialog may
* require the current sandbox and the current web project as its context e.g.
* <br>
* http://server/alfresco/command/ui/createwebcontent?sandbox=website1&webproject=1234567890
*
* @author Kevin Roast
*/
public class UIActionCommandProcessor implements ExtCommandProcessor
{
private static final String MANAGE_TASK = "managetask";
public static final String PARAM_CONTAINER = "container";
private ServletContext sc = null;
private String command = null;
private Map<String, String> args = null;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand(MANAGE_TASK, ManageTaskDialogCommand.class);
CommandFactory.getInstance().registerCommand("editcontentprops", EditContentPropertiesCommand.class);
CommandFactory.getInstance().registerCommand("userprofile", UserProfileDialogCommand.class);
CommandFactory.getInstance().registerCommand("editspace", EditSpaceCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
this.sc = sc;
if (args.size() != 0)
{
this.args = new HashMap<String, String>(args);
}
if (MANAGE_TASK.equals(command))
{
String taskId = args.get(ManageTaskDialogCommand.PROP_TASKID);
return WorkflowUtil.isTaskEditable(taskId, sc);
}
return true;
}
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
// not implemented in ExtCommandProcessor!
}
/**
* @see org.alfresco.web.app.servlet.command.ExtCommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, HttpServletResponse response, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(this.args);
properties.put(BaseUIActionCommand.PROP_SERVLETCONTEXT, this.sc);
properties.put(BaseUIActionCommand.PROP_REQUEST, request);
properties.put(BaseUIActionCommand.PROP_RESPONSE, response);
// if the container parameter is present and equal to "plain" add the
// external container object to the session
String container = request.getParameter(PARAM_CONTAINER);
if (container != null && container.equalsIgnoreCase("plain"))
{
request.getSession().setAttribute(
AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION, Boolean.TRUE);
}
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered UI Action command specified: " + command);
}
cmd.execute(serviceRegistry, properties);
this.command = command;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("UI Action command: '");
out.print(Utils.encode(this.command));
out.print("' executed with args: ");
out.println(this.args != null ? (Utils.encode(this.args.toString())) : "");
}
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.bean.workflow.WorkflowUtil;
import org.alfresco.web.ui.common.Utils;
/**
* UI action command processor implementation.
* <p>
* Responsible for executing specific UI actions via a REST style URL interface.
* <p>
* The URL postfix for each specific command depends on the context that is required
* for that command. For example, a command to launch the Create Web Content dialog may
* require the current sandbox and the current web project as its context e.g.
* <br>
* http://server/alfresco/command/ui/createwebcontent?sandbox=website1&webproject=1234567890
*
* @author Kevin Roast
*/
public class UIActionCommandProcessor implements ExtCommandProcessor
{
private static final String MANAGE_TASK = "managetask";
public static final String PARAM_CONTAINER = "container";
private ServletContext sc = null;
private String command = null;
private Map<String, String> args = null;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand(MANAGE_TASK, ManageTaskDialogCommand.class);
CommandFactory.getInstance().registerCommand("editcontentprops", EditContentPropertiesCommand.class);
CommandFactory.getInstance().registerCommand("userprofile", UserProfileDialogCommand.class);
CommandFactory.getInstance().registerCommand("editspace", EditSpaceCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#validateArguments(javax.servlet.ServletContext, java.lang.String, java.util.Map, java.lang.String[])
*/
public boolean validateArguments(ServletContext sc, String command, Map<String, String> args, String[] urlElements)
{
this.sc = sc;
if (args.size() != 0)
{
this.args = new HashMap<String, String>(args);
}
if (MANAGE_TASK.equals(command))
{
String taskId = args.get(ManageTaskDialogCommand.PROP_TASKID);
return WorkflowUtil.isTaskEditable(taskId, sc);
}
return true;
}
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
// not implemented in ExtCommandProcessor!
}
/**
* @see org.alfresco.web.app.servlet.command.ExtCommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, HttpServletResponse response, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(this.args);
properties.put(BaseUIActionCommand.PROP_SERVLETCONTEXT, this.sc);
properties.put(BaseUIActionCommand.PROP_REQUEST, request);
properties.put(BaseUIActionCommand.PROP_RESPONSE, response);
// if the container parameter is present and equal to "plain" add the
// external container object to the session
String container = request.getParameter(PARAM_CONTAINER);
if (container != null && container.equalsIgnoreCase("plain"))
{
request.getSession().setAttribute(
AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION, Boolean.TRUE);
}
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered UI Action command specified: " + command);
}
cmd.execute(serviceRegistry, properties);
this.command = command;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("UI Action command: '");
out.print(Utils.encode(this.command));
out.print("' executed with args: ");
out.println(this.args != null ? (Utils.encode(this.args.toString())) : "");
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.ui.common.Utils;
/**
* Workflow specific command processor implementation.
* <p>
* Responsible for executing 'approve' and 'reject' workflow commands on a Node.
*
* @author Kevin Roast
*/
public final class WorkflowCommandProcessor extends BaseNodeCommandProcessor
{
private String command;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("approve", ApproveWorkflowCommand.class);
CommandFactory.getInstance().registerCommand("reject", RejectWorkflowCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(1, 1.0f);
// all workflow commands use a "target" Node property as an argument
properties.put(ApproveWorkflowCommand.PROP_TARGET, this.targetRef);
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered workflow command specified: " + command);
}
cmd.execute(serviceRegistry, properties);
this.command = command;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("Workflow command: '");
out.print(Utils.encode(this.command));
out.print("' executed against node: ");
out.println(Utils.encode(this.targetRef.toString()));
}
}
package org.alfresco.web.app.servlet.command;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.ui.common.Utils;
/**
* Workflow specific command processor implementation.
* <p>
* Responsible for executing 'approve' and 'reject' workflow commands on a Node.
*
* @author Kevin Roast
*/
public final class WorkflowCommandProcessor extends BaseNodeCommandProcessor
{
private String command;
static
{
// add our commands to the command registry
CommandFactory.getInstance().registerCommand("approve", ApproveWorkflowCommand.class);
CommandFactory.getInstance().registerCommand("reject", RejectWorkflowCommand.class);
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#process(org.alfresco.service.ServiceRegistry, javax.servlet.http.HttpServletRequest, java.lang.String)
*/
public void process(ServiceRegistry serviceRegistry, HttpServletRequest request, String command)
{
Map<String, Object> properties = new HashMap<String, Object>(1, 1.0f);
// all workflow commands use a "target" Node property as an argument
properties.put(ApproveWorkflowCommand.PROP_TARGET, this.targetRef);
Command cmd = CommandFactory.getInstance().createCommand(command);
if (cmd == null)
{
throw new AlfrescoRuntimeException("Unregistered workflow command specified: " + command);
}
cmd.execute(serviceRegistry, properties);
this.command = command;
}
/**
* @see org.alfresco.web.app.servlet.command.CommandProcessor#outputStatus(java.io.PrintWriter)
*/
public void outputStatus(PrintWriter out)
{
out.print("Workflow command: '");
out.print(Utils.encode(this.command));
out.print("' executed against node: ");
out.println(Utils.encode(this.targetRef.toString()));
}
}

View File

@@ -1,88 +1,88 @@
package org.alfresco.web.bean;
import javax.faces.context.FacesContext;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
/**
* Simple backing bean used by the about page to display the version.
*
* @author gavinc
*/
public class AboutBean extends BaseDialogBean
{
private static final long serialVersionUID = -3777479360531145878L;
private final static String MSG_VERSION = "version";
private final static String MSG_CLOSE = "close";
transient private DescriptorService descriptorService;
/**
* Retrieves the version of the repository.
*
* @return The version string
*/
public String getVersion()
{
return this.getDescriptorService().getServerDescriptor().getVersion();
}
/**
* Retrieves the edition of the repository.
*
* @return The edition
*/
public String getEdition()
{
return this.getDescriptorService().getServerDescriptor().getEdition();
}
/**
* Sets the DescriptorService.
*
* @param descriptorService The DescriptorService
*/
public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return null;
}
@Override
public String getContainerDescription()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_VERSION) + " :" + getEdition() + " - v" + getVersion();
}
DescriptorService getDescriptorService()
{
//check for null in cluster environment
if (descriptorService == null)
{
descriptorService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getDescriptorService();
}
return descriptorService;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CLOSE);
}
@Override
protected String getDefaultCancelOutcome()
{
return "dialog:close:browse";
}
}
package org.alfresco.web.bean;
import javax.faces.context.FacesContext;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
/**
* Simple backing bean used by the about page to display the version.
*
* @author gavinc
*/
public class AboutBean extends BaseDialogBean
{
private static final long serialVersionUID = -3777479360531145878L;
private final static String MSG_VERSION = "version";
private final static String MSG_CLOSE = "close";
transient private DescriptorService descriptorService;
/**
* Retrieves the version of the repository.
*
* @return The version string
*/
public String getVersion()
{
return this.getDescriptorService().getServerDescriptor().getVersion();
}
/**
* Retrieves the edition of the repository.
*
* @return The edition
*/
public String getEdition()
{
return this.getDescriptorService().getServerDescriptor().getEdition();
}
/**
* Sets the DescriptorService.
*
* @param descriptorService The DescriptorService
*/
public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return null;
}
@Override
public String getContainerDescription()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_VERSION) + " :" + getEdition() + " - v" + getVersion();
}
DescriptorService getDescriptorService()
{
//check for null in cluster environment
if (descriptorService == null)
{
descriptorService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getDescriptorService();
}
return descriptorService;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CLOSE);
}
@Override
protected String getDefaultCancelOutcome()
{
return "dialog:close:browse";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,144 +1,144 @@
package org.alfresco.web.bean;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
public class CategoriesProperties
{
protected CategoryService categoryService;
/** Component references */
protected UIRichList categoriesRichList;
/** Currently visible category Node */
private Node category = null;
/** Current category ref */
private NodeRef categoryRef = null;
/** Action category node */
private Node actionCategory = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Dialog properties */
private String name = null;
private String description = null;
/** RichList view mode */
private String viewMode = "icons";
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
public CategoryService getCategoryService()
{
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public Node getActionCategory()
{
return actionCategory;
}
public void setActionCategory(Node actionCategory)
{
this.actionCategory = actionCategory;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getViewMode()
{
return viewMode;
}
public void setViewMode(String viewMode)
{
this.viewMode = viewMode;
}
public List<IBreadcrumbHandler> getLocation()
{
return location;
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
}
package org.alfresco.web.bean;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
public class CategoriesProperties
{
protected CategoryService categoryService;
/** Component references */
protected UIRichList categoriesRichList;
/** Currently visible category Node */
private Node category = null;
/** Current category ref */
private NodeRef categoryRef = null;
/** Action category node */
private Node actionCategory = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Dialog properties */
private String name = null;
private String description = null;
/** RichList view mode */
private String viewMode = "icons";
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
public CategoryService getCategoryService()
{
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public Node getActionCategory()
{
return actionCategory;
}
public void setActionCategory(Node actionCategory)
{
this.actionCategory = actionCategory;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getViewMode()
{
return viewMode;
}
public void setViewMode(String viewMode)
{
this.viewMode = viewMode;
}
public List<IBreadcrumbHandler> getLocation()
{
return location;
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
}

View File

@@ -1,59 +1,59 @@
package org.alfresco.web.bean;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.web.bean.search.SearchContext;
public class CategoryBrowserBean
{
public static String BEAN_NAME = "CategoryBrowserBean";
private NodeService nodeService;
private NodeRef currentCategory = null;
private boolean includeSubcategories = false;
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setCurrentCategory(NodeRef currentCategory)
{
this.currentCategory = currentCategory;
}
public String getCurrentCategoryName()
{
String currentCategoryName = null;
if (currentCategory != null)
currentCategoryName = (String) this.nodeService.getProperty(currentCategory, ContentModel.PROP_NAME);
return currentCategoryName;
}
public boolean isIncludeSubcategories()
{
return includeSubcategories;
}
public void setIncludeSubcategories(boolean includeSubcategories)
{
this.includeSubcategories = includeSubcategories;
}
public SearchContext generateCategorySearchContext()
{
SearchContext categorySearch = new SearchContext();
String[] categories = new String[1];
categories[0] = SearchContext.getPathFromSpaceRef(currentCategory, includeSubcategories);
categorySearch.setText("");
categorySearch.setCategories(categories);
return categorySearch;
}
}
package org.alfresco.web.bean;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.web.bean.search.SearchContext;
public class CategoryBrowserBean
{
public static String BEAN_NAME = "CategoryBrowserBean";
private NodeService nodeService;
private NodeRef currentCategory = null;
private boolean includeSubcategories = false;
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setCurrentCategory(NodeRef currentCategory)
{
this.currentCategory = currentCategory;
}
public String getCurrentCategoryName()
{
String currentCategoryName = null;
if (currentCategory != null)
currentCategoryName = (String) this.nodeService.getProperty(currentCategory, ContentModel.PROP_NAME);
return currentCategoryName;
}
public boolean isIncludeSubcategories()
{
return includeSubcategories;
}
public void setIncludeSubcategories(boolean includeSubcategories)
{
this.includeSubcategories = includeSubcategories;
}
public SearchContext generateCategorySearchContext()
{
SearchContext categorySearch = new SearchContext();
String[] categories = new String[1];
categories[0] = SearchContext.getPathFromSpaceRef(currentCategory, includeSubcategories);
categorySearch.setText("");
categorySearch.setCategories(categories);
return categorySearch;
}
}

View File

@@ -1,229 +1,229 @@
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.Utils.URLMode;
/**
* Backing bean for the edit link properties dialog
*
* @author kevinr
* @author YanO
*/
public class LinkPropertiesDialog extends BaseDialogBean
{
private static final long serialVersionUID = -167326851073011187L;
private Node editableNode = null;
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// reset node instance for next dialog invocation
this.editableNode = null;
}
public Map<String, Object> getProperties()
{
return getEditableNode().getProperties();
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
/**
* Returns the node being edited
*
* @return The node being edited
*/
public Node getEditableNode()
{
if (this.editableNode == null)
{
if (this.parameters.containsKey("nodeRef"))
{
this.editableNode = new Node(new NodeRef(this.parameters.get("nodeRef")));
}
else
{
throw new IllegalArgumentException("Dialog has not been initialised with noderef or setup action event called.");
}
}
return this.editableNode;
}
/**
* Event handler called to setup the link object for property editing
*
* @param event The event
*/
public void setupFileLinkForAction(ActionEvent event)
{
this.editableNode = new Node(this.browseBean.getDocument().getNodeRef());
}
/**
* Event handler called to setup the link object for property editing
*
* @param event The event
*/
public void setupFolderLinkForAction(ActionEvent event)
{
this.editableNode = new Node(this.browseBean.getActionSpace().getNodeRef());
}
/**
* @return Human readable version of the Path to the destination object
*/
public String getDestinationPath()
{
NodeRef destRef = (NodeRef)getEditableNode().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Repository.getNamePath(
this.getNodeService(), this.getNodeService().getPath(destRef), null, "/", null);
}
/**
* Returns the URL to access the details page for the current document link object
*
* @return The bookmark URL
*/
public String getFileLinkBookmarkUrl()
{
NodeRef destRef = (NodeRef)this.browseBean.getDocument().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.SHOW_DETAILS);
}
/**
* Returns the URL to access the details page for the current document link object
*
* @return The bookmark URL
*/
public String getSpaceLinkDestinationUrl()
{
NodeRef destRef = (NodeRef)this.browseBean.getActionSpace().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.SHOW_DETAILS);
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
try
{
NodeRef nodeRef = getEditableNode().getNodeRef();
Map<String, Object> props = getEditableNode().getProperties();
//get the name and move the node as necessary
String name = (String) props.get(ContentModel.PROP_NAME);
if (name != null)
{
getFileFolderService().rename(nodeRef, name);
}
Map<QName, Serializable> properties = this.getNodeService().getProperties(nodeRef);
// we need to put all the properties from the editable bag back into
// the format expected by the repository
// deal with adding the "titled" aspect if required
String title = (String)props.get(ContentModel.PROP_TITLE);
String description = (String)props.get(ContentModel.PROP_DESCRIPTION);
if (title != null || description != null)
{
// add the aspect to be sure it's present
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
// other props will get added later in setProperties()
}
// add the remaining properties
Iterator<String> iterProps = props.keySet().iterator();
while (iterProps.hasNext())
{
String propName = iterProps.next();
QName qname = QName.createQName(propName);
// make sure the property is represented correctly
Serializable propValue = (Serializable)props.get(propName);
// check for empty strings when using number types, set to null in this case
if ((propValue != null) && (propValue instanceof String) &&
(propValue.toString().length() == 0))
{
PropertyDefinition propDef = this.getDictionaryService().getProperty(qname);
if (propDef != null)
{
if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) ||
propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.INT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.LONG))
{
propValue = null;
}
}
}
properties.put(qname, propValue);
}
// send the properties back to the repository
this.getNodeService().setProperties(nodeRef, properties);
}
catch (InvalidNodeRefException err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_NODEREF), new Object[] {this.browseBean.getDocument().getId()}));
// this failure means the node no longer exists - we cannot show the doc properties screen
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
catch (Throwable e)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_GENERIC), e.getMessage()), e);
outcome = null;
ReportedException.throwIfNecessary(e);
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
if (this.browseBean.getDocument() != null)
{
this.browseBean.getDocument().reset();
}
else if (this.browseBean.getActionSpace() != null)
{
this.browseBean.getActionSpace().reset();
}
return outcome;
}
}
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.Utils.URLMode;
/**
* Backing bean for the edit link properties dialog
*
* @author kevinr
* @author YanO
*/
public class LinkPropertiesDialog extends BaseDialogBean
{
private static final long serialVersionUID = -167326851073011187L;
private Node editableNode = null;
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// reset node instance for next dialog invocation
this.editableNode = null;
}
public Map<String, Object> getProperties()
{
return getEditableNode().getProperties();
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
/**
* Returns the node being edited
*
* @return The node being edited
*/
public Node getEditableNode()
{
if (this.editableNode == null)
{
if (this.parameters.containsKey("nodeRef"))
{
this.editableNode = new Node(new NodeRef(this.parameters.get("nodeRef")));
}
else
{
throw new IllegalArgumentException("Dialog has not been initialised with noderef or setup action event called.");
}
}
return this.editableNode;
}
/**
* Event handler called to setup the link object for property editing
*
* @param event The event
*/
public void setupFileLinkForAction(ActionEvent event)
{
this.editableNode = new Node(this.browseBean.getDocument().getNodeRef());
}
/**
* Event handler called to setup the link object for property editing
*
* @param event The event
*/
public void setupFolderLinkForAction(ActionEvent event)
{
this.editableNode = new Node(this.browseBean.getActionSpace().getNodeRef());
}
/**
* @return Human readable version of the Path to the destination object
*/
public String getDestinationPath()
{
NodeRef destRef = (NodeRef)getEditableNode().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Repository.getNamePath(
this.getNodeService(), this.getNodeService().getPath(destRef), null, "/", null);
}
/**
* Returns the URL to access the details page for the current document link object
*
* @return The bookmark URL
*/
public String getFileLinkBookmarkUrl()
{
NodeRef destRef = (NodeRef)this.browseBean.getDocument().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.SHOW_DETAILS);
}
/**
* Returns the URL to access the details page for the current document link object
*
* @return The bookmark URL
*/
public String getSpaceLinkDestinationUrl()
{
NodeRef destRef = (NodeRef)this.browseBean.getActionSpace().getProperties().get(ContentModel.PROP_LINK_DESTINATION);
return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.SHOW_DETAILS);
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
try
{
NodeRef nodeRef = getEditableNode().getNodeRef();
Map<String, Object> props = getEditableNode().getProperties();
//get the name and move the node as necessary
String name = (String) props.get(ContentModel.PROP_NAME);
if (name != null)
{
getFileFolderService().rename(nodeRef, name);
}
Map<QName, Serializable> properties = this.getNodeService().getProperties(nodeRef);
// we need to put all the properties from the editable bag back into
// the format expected by the repository
// deal with adding the "titled" aspect if required
String title = (String)props.get(ContentModel.PROP_TITLE);
String description = (String)props.get(ContentModel.PROP_DESCRIPTION);
if (title != null || description != null)
{
// add the aspect to be sure it's present
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
// other props will get added later in setProperties()
}
// add the remaining properties
Iterator<String> iterProps = props.keySet().iterator();
while (iterProps.hasNext())
{
String propName = iterProps.next();
QName qname = QName.createQName(propName);
// make sure the property is represented correctly
Serializable propValue = (Serializable)props.get(propName);
// check for empty strings when using number types, set to null in this case
if ((propValue != null) && (propValue instanceof String) &&
(propValue.toString().length() == 0))
{
PropertyDefinition propDef = this.getDictionaryService().getProperty(qname);
if (propDef != null)
{
if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) ||
propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.INT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.LONG))
{
propValue = null;
}
}
}
properties.put(qname, propValue);
}
// send the properties back to the repository
this.getNodeService().setProperties(nodeRef, properties);
}
catch (InvalidNodeRefException err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_NODEREF), new Object[] {this.browseBean.getDocument().getId()}));
// this failure means the node no longer exists - we cannot show the doc properties screen
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
catch (Throwable e)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_GENERIC), e.getMessage()), e);
outcome = null;
ReportedException.throwIfNecessary(e);
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
if (this.browseBean.getDocument() != null)
{
this.browseBean.getDocument().reset();
}
else if (this.browseBean.getActionSpace() != null)
{
this.browseBean.getActionSpace().reset();
}
return outcome;
}
}

View File

@@ -1,26 +1,26 @@
package org.alfresco.web.bean;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Helper bean used to temporarily store the last item added in a multi
* value editor component.
*
* A Map is used so that multiple components on the same page can use the
* same backing bean.
*
* @author gavinc
*/
public class MultiValueEditorBean implements Serializable
{
private static final long serialVersionUID = -5180578793877515158L;
private Map<String, Object> lastItemsAdded = new HashMap<String, Object>(10);
public Map<String, Object> getLastItemsAdded()
{
return lastItemsAdded;
}
}
package org.alfresco.web.bean;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Helper bean used to temporarily store the last item added in a multi
* value editor component.
*
* A Map is used so that multiple components on the same page can use the
* same backing bean.
*
* @author gavinc
*/
public class MultiValueEditorBean implements Serializable
{
private static final long serialVersionUID = -5180578793877515158L;
private Map<String, Object> lastItemsAdded = new HashMap<String, Object>(10);
public Map<String, Object> getLastItemsAdded()
{
return lastItemsAdded;
}
}

View File

@@ -1,21 +1,21 @@
package org.alfresco.web.bean;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
/**
* @author Kevin Roast
*/
public interface NodeEventListener extends Serializable
{
/**
* Callback executed when a Node wrapped object is created. This is generally used
* to add additional property resolvers to the Node for a specific model type.
*
* @param node The Node wrapper that has been created
* @param type Type of the Node that has been created
*/
public void created(Node node, QName type);
}
package org.alfresco.web.bean;
import java.io.Serializable;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Node;
/**
* @author Kevin Roast
*/
public interface NodeEventListener extends Serializable
{
/**
* Callback executed when a Node wrapped object is created. This is generally used
* to add additional property resolvers to the Node for a specific model type.
*
* @param node The Node wrapper that has been created
* @param type Type of the Node that has been created
*/
public void created(Node node, QName type);
}

View File

@@ -1,292 +1,292 @@
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.UrlUtil;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Repository;
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;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
/**
* @author Kevin Roast
*/
public class TemplateMailHelperBean implements Serializable
{
private static final long serialVersionUID = 9117248002321651339L;
private static Log logger = LogFactory.getLog(TemplateMailHelperBean.class);
/** JavaMailSender bean reference */
transient private JavaMailSender mailSender;
/** NodeService bean reference */
transient private NodeService nodeService;
/** dialog state */
private String subject = null;
private String body = null;
private String automaticText = null;
private String template = null;
private String usingTemplate = null;
private String finalBody;
/**
* @param mailSender The JavaMailSender to set.
*/
public void setMailSender(JavaMailSender mailSender)
{
this.mailSender = mailSender;
}
protected JavaMailSender getMailSender()
{
if (mailSender == null)
{
mailSender = (JavaMailSender) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "mailService");
}
return mailSender;
}
/**
* @param nodeService The nodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
protected NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
/**
* Initialises the bean
*/
public TemplateMailHelperBean()
{
subject = "";
body = "";
automaticText = "";
template = null;
usingTemplate = null;
}
/**
* Send an email notification to the specified User authority
*
* @param person Person node representing the user
* @param node Node they are invited too
* @param from From text message
* @param roleText The role display label for the user invite notification
*/
public void notifyUser(NodeRef person, NodeRef node, final String from, String roleText)
{
final String to = (String)this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL);
if (to != null && to.length() != 0)
{
String body = this.body;
if (this.usingTemplate != null)
{
FacesContext fc = FacesContext.getCurrentInstance();
// use template service to format the email
NodeRef templateRef = new NodeRef(Repository.getStoreRef(), this.usingTemplate);
ServiceRegistry services = Repository.getServiceRegistry(fc);
Map<String, Object> model = DefaultModelHelper.buildDefaultModel(
services, Application.getCurrentUser(fc), templateRef);
model.put("role", roleText);
model.put("space", node);
// object to allow client urls to be generated in emails
model.put("url", new BaseTemplateContentServlet.URLHelper(fc));
model.put("msg", new I18NMessageMethod());
model.put("document", node);
if (nodeService.getType(node).equals(ContentModel.TYPE_CONTENT))
{
NodeRef parentNodeRef = nodeService.getParentAssocs(node).get(0).getParentRef();
if (parentNodeRef == null)
{
throw new IllegalArgumentException("Parent folder doesn't exists for node: " + node);
}
model.put("space", parentNodeRef);
}
model.put("shareUrl", UrlUtil.getShareUrl(services.getSysAdminParams()));
body = services.getTemplateService().processTemplate("freemarker", templateRef.toString(), model);
}
this.finalBody = body;
MimeMessagePreparator mailPreparer = new MimeMessagePreparator()
{
public void prepare(MimeMessage mimeMessage) throws MessagingException
{
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(to);
message.setSubject(subject);
message.setText(finalBody, MailActionExecuter.isHTML(finalBody));
message.setFrom(from);
}
};
if (logger.isDebugEnabled())
logger.debug("Sending notification email to: " + to + "\n...with subject:\n" + subject + "\n...with body:\n" + body);
try
{
// Send the message
this.getMailSender().send(mailPreparer);
}
catch (Throwable e)
{
// don't stop the action but let admins know email is not getting sent
logger.error("Failed to send email to " + to, e);
}
}
}
/**
* Action handler called to insert a template as the email body
*/
public void insertTemplate(ActionEvent event)
{
if (this.template != null && this.template.equals(TemplateSupportBean.NO_SELECTION) == false)
{
// get the content of the template so the user can get a basic preview of it
try
{
NodeRef templateRef = new NodeRef(Repository.getStoreRef(), this.template);
ContentService cs = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
ContentReader reader = cs.getReader(templateRef, ContentModel.PROP_CONTENT);
if (reader != null && reader.exists())
{
this.body = reader.getContentString();
this.usingTemplate = this.template;
}
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
}
}
}
/**
* Action handler called to discard the template from the email body
*/
public void discardTemplate(ActionEvent event)
{
this.body = this.automaticText;
usingTemplate = null;
}
/**
* @return Returns the email body text.
*/
public String getBody()
{
return this.body;
}
/**
* @param body The email body text to set.
*/
public void setBody(String body)
{
this.body = body;
}
/**
* @return Returns the email subject text.
*/
public String getSubject()
{
return this.subject;
}
/**
* @param subject The email subject text to set.
*/
public void setSubject(String subject)
{
this.subject = subject;
}
/**
* @return Returns the automatic text.
*/
public String getAutomaticText()
{
return this.automaticText;
}
/**
* @param automaticText The automatic text to set.
*/
public void setAutomaticText(String automaticText)
{
this.automaticText = automaticText;
}
/**
* @return Returns the email template Id
*/
public String getTemplate()
{
return this.template;
}
/**
* @param template The email template to set.
*/
public void setTemplate(String template)
{
this.template = template;
}
/**
* @return Returns if a template has been inserted by a user for email body.
*/
public String getUsingTemplate()
{
return this.usingTemplate;
}
/**
* @param usingTemplate Template that has been inserted by a user for the email body.
*/
public void setUsingTemplate(String usingTemplate)
{
this.usingTemplate = usingTemplate;
}
}
package org.alfresco.web.bean;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.UrlUtil;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.repository.Repository;
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;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
/**
* @author Kevin Roast
*/
public class TemplateMailHelperBean implements Serializable
{
private static final long serialVersionUID = 9117248002321651339L;
private static Log logger = LogFactory.getLog(TemplateMailHelperBean.class);
/** JavaMailSender bean reference */
transient private JavaMailSender mailSender;
/** NodeService bean reference */
transient private NodeService nodeService;
/** dialog state */
private String subject = null;
private String body = null;
private String automaticText = null;
private String template = null;
private String usingTemplate = null;
private String finalBody;
/**
* @param mailSender The JavaMailSender to set.
*/
public void setMailSender(JavaMailSender mailSender)
{
this.mailSender = mailSender;
}
protected JavaMailSender getMailSender()
{
if (mailSender == null)
{
mailSender = (JavaMailSender) FacesHelper.getManagedBean(FacesContext.getCurrentInstance(), "mailService");
}
return mailSender;
}
/**
* @param nodeService The nodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
protected NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
/**
* Initialises the bean
*/
public TemplateMailHelperBean()
{
subject = "";
body = "";
automaticText = "";
template = null;
usingTemplate = null;
}
/**
* Send an email notification to the specified User authority
*
* @param person Person node representing the user
* @param node Node they are invited too
* @param from From text message
* @param roleText The role display label for the user invite notification
*/
public void notifyUser(NodeRef person, NodeRef node, final String from, String roleText)
{
final String to = (String)this.getNodeService().getProperty(person, ContentModel.PROP_EMAIL);
if (to != null && to.length() != 0)
{
String body = this.body;
if (this.usingTemplate != null)
{
FacesContext fc = FacesContext.getCurrentInstance();
// use template service to format the email
NodeRef templateRef = new NodeRef(Repository.getStoreRef(), this.usingTemplate);
ServiceRegistry services = Repository.getServiceRegistry(fc);
Map<String, Object> model = DefaultModelHelper.buildDefaultModel(
services, Application.getCurrentUser(fc), templateRef);
model.put("role", roleText);
model.put("space", node);
// object to allow client urls to be generated in emails
model.put("url", new BaseTemplateContentServlet.URLHelper(fc));
model.put("msg", new I18NMessageMethod());
model.put("document", node);
if (nodeService.getType(node).equals(ContentModel.TYPE_CONTENT))
{
NodeRef parentNodeRef = nodeService.getParentAssocs(node).get(0).getParentRef();
if (parentNodeRef == null)
{
throw new IllegalArgumentException("Parent folder doesn't exists for node: " + node);
}
model.put("space", parentNodeRef);
}
model.put("shareUrl", UrlUtil.getShareUrl(services.getSysAdminParams()));
body = services.getTemplateService().processTemplate("freemarker", templateRef.toString(), model);
}
this.finalBody = body;
MimeMessagePreparator mailPreparer = new MimeMessagePreparator()
{
public void prepare(MimeMessage mimeMessage) throws MessagingException
{
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(to);
message.setSubject(subject);
message.setText(finalBody, MailActionExecuter.isHTML(finalBody));
message.setFrom(from);
}
};
if (logger.isDebugEnabled())
logger.debug("Sending notification email to: " + to + "\n...with subject:\n" + subject + "\n...with body:\n" + body);
try
{
// Send the message
this.getMailSender().send(mailPreparer);
}
catch (Throwable e)
{
// don't stop the action but let admins know email is not getting sent
logger.error("Failed to send email to " + to, e);
}
}
}
/**
* Action handler called to insert a template as the email body
*/
public void insertTemplate(ActionEvent event)
{
if (this.template != null && this.template.equals(TemplateSupportBean.NO_SELECTION) == false)
{
// get the content of the template so the user can get a basic preview of it
try
{
NodeRef templateRef = new NodeRef(Repository.getStoreRef(), this.template);
ContentService cs = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
ContentReader reader = cs.getReader(templateRef, ContentModel.PROP_CONTENT);
if (reader != null && reader.exists())
{
this.body = reader.getContentString();
this.usingTemplate = this.template;
}
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
}
}
}
/**
* Action handler called to discard the template from the email body
*/
public void discardTemplate(ActionEvent event)
{
this.body = this.automaticText;
usingTemplate = null;
}
/**
* @return Returns the email body text.
*/
public String getBody()
{
return this.body;
}
/**
* @param body The email body text to set.
*/
public void setBody(String body)
{
this.body = body;
}
/**
* @return Returns the email subject text.
*/
public String getSubject()
{
return this.subject;
}
/**
* @param subject The email subject text to set.
*/
public void setSubject(String subject)
{
this.subject = subject;
}
/**
* @return Returns the automatic text.
*/
public String getAutomaticText()
{
return this.automaticText;
}
/**
* @param automaticText The automatic text to set.
*/
public void setAutomaticText(String automaticText)
{
this.automaticText = automaticText;
}
/**
* @return Returns the email template Id
*/
public String getTemplate()
{
return this.template;
}
/**
* @param template The email template to set.
*/
public void setTemplate(String template)
{
this.template = template;
}
/**
* @return Returns if a template has been inserted by a user for email body.
*/
public String getUsingTemplate()
{
return this.usingTemplate;
}
/**
* @param usingTemplate Template that has been inserted by a user for the email body.
*/
public void setUsingTemplate(String usingTemplate)
{
this.usingTemplate = usingTemplate;
}
}

View File

@@ -1,272 +1,272 @@
package org.alfresco.web.bean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.ExpiringValueCache;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
/**
* Provide access to commonly used lists of templates and script files.
* <p>
* The lists are cached for a small period of time to help performance in the client,
* as generally the contents of the template folders are not changed frequently.
*
* @author Kevin Roast
*/
public class TemplateSupportBean implements Serializable
{
private static final long serialVersionUID = 6698338879903536081L;
private static final String MSG_SELECT_TEMPLATE = "select_a_template";
private static final String MSG_SELECT_SCRIPT = "select_a_script";
/** "no selection" marker for SelectItem lists */
public static final String NO_SELECTION = "none";
/** NodeService instance */
transient private NodeService nodeService;
/** The SearchService instance */
transient private SearchService searchService;
/** cache of content templates that lasts 30 seconds - enough for a couple of page refreshes */
private ExpiringValueCache<List<SelectItem>> contentTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of email templates that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> emailTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of RSS templates that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> rssTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of JavaScript files that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> scriptFiles = new ExpiringValueCache<List<SelectItem>>(1000*30);
/**
* @param nodeService The NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
/**
* @param searchService The SearchService to set.
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
private SearchService getSearchService()
{
if (searchService == null)
{
searchService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getSearchService();
}
return searchService;
}
/**
* @return the list of available Content Templates that can be applied to the current document.
*/
public List<SelectItem> getContentTemplates()
{
List<SelectItem> templates = contentTemplates.get();
if (templates == null)
{
// get the template from the special Content Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getContentTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
contentTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available Email Templates.
*/
public List<SelectItem> getEmailTemplates()
{
List<SelectItem> templates = emailTemplates.get();
if (templates == null)
{
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
emailTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available Notify Email Templates.
*/
public List<SelectItem> getNotifyEmailTemplates()
{
List<SelectItem> templates = null;
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "/" +
Application.getNotifyEmailTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
return templates;
}
/**
* @return the list of available RSS Templates.
*/
public List<SelectItem> getRSSTemplates()
{
List<SelectItem> templates = rssTemplates.get();
if (templates == null)
{
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getRSSTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
rssTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available JavaScript files that can be applied to the current document.
*/
public List<SelectItem> getScriptFiles()
{
List<SelectItem> scripts = this.scriptFiles.get();
if (scripts == null)
{
// get the scripts from the special Scripts folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getScriptsFolderName(fc) + "//*";
scripts = selectDictionaryNodes(fc, xpath, MSG_SELECT_SCRIPT, MimetypeMap.MIMETYPE_JAVASCRIPT);
scriptFiles.put(scripts);
}
return scripts;
}
/**
* @param fc FacesContext
* @param xpath XPath to the nodes to select
* @param noSelectionLabel Label to add to the list if no items are found in the search
*
* @return List of SelectItem wrapper objects for the nodes found at the XPath
*/
private List<SelectItem> selectDictionaryNodes(FacesContext fc, String xpath, String noSelectionLabel)
{
return selectDictionaryNodes(fc, xpath, noSelectionLabel, null);
}
/**
* @param fc FacesContext
* @param xpath XPath to the nodes to select
* @param noSelectionLabel Label to add to the list if no items are found in the search
* @param mimetype Optional mimetype of items to add, will not add to list if mimetype does not match
*
* @return List of SelectItem wrapper objects for the nodes found at the XPath
*/
private List<SelectItem> selectDictionaryNodes(FacesContext fc, String xpath, String noSelectionLabel, String mimetype)
{
List<SelectItem> wrappers = null;
try
{
NodeRef rootNodeRef = this.getNodeService().getRootNode(Repository.getStoreRef());
NamespaceService resolver = Repository.getServiceRegistry(fc).getNamespaceService();
List<NodeRef> results = this.getSearchService().selectNodes(rootNodeRef, xpath, null, resolver, false);
wrappers = new ArrayList<SelectItem>(results.size() + 1);
if (results.size() != 0)
{
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
for (NodeRef ref : results)
{
if (this.getNodeService().exists(ref) == true)
{
Node childNode = new Node(ref);
ContentData content = (ContentData)childNode.getProperties().get(ContentModel.PROP_CONTENT);
if (dd.isSubClass(childNode.getType(), ContentModel.TYPE_CONTENT) &&
(mimetype == null || mimetype.equals(content.getMimetype())))
{
wrappers.add(new SelectItem(childNode.getId(), childNode.getName()));
}
}
}
// make sure the list is sorted by the label
QuickSort sorter = new QuickSort(wrappers, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
}
catch (AccessDeniedException accessErr)
{
// ignore the result if we cannot access the root
}
// add an entry (at the start) to instruct the user to select an item
if (wrappers == null)
{
wrappers = new ArrayList<SelectItem>(1);
}
wrappers.add(0, new SelectItem(NO_SELECTION, Application.getMessage(FacesContext.getCurrentInstance(), noSelectionLabel)));
return wrappers;
}
}
package org.alfresco.web.bean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.ExpiringValueCache;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
/**
* Provide access to commonly used lists of templates and script files.
* <p>
* The lists are cached for a small period of time to help performance in the client,
* as generally the contents of the template folders are not changed frequently.
*
* @author Kevin Roast
*/
public class TemplateSupportBean implements Serializable
{
private static final long serialVersionUID = 6698338879903536081L;
private static final String MSG_SELECT_TEMPLATE = "select_a_template";
private static final String MSG_SELECT_SCRIPT = "select_a_script";
/** "no selection" marker for SelectItem lists */
public static final String NO_SELECTION = "none";
/** NodeService instance */
transient private NodeService nodeService;
/** The SearchService instance */
transient private SearchService searchService;
/** cache of content templates that lasts 30 seconds - enough for a couple of page refreshes */
private ExpiringValueCache<List<SelectItem>> contentTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of email templates that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> emailTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of RSS templates that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> rssTemplates = new ExpiringValueCache<List<SelectItem>>(1000*30);
/** cache of JavaScript files that lasts 30 seconds - enough for a few page refreshes */
private ExpiringValueCache<List<SelectItem>> scriptFiles = new ExpiringValueCache<List<SelectItem>>(1000*30);
/**
* @param nodeService The NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
/**
* @param searchService The SearchService to set.
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
private SearchService getSearchService()
{
if (searchService == null)
{
searchService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getSearchService();
}
return searchService;
}
/**
* @return the list of available Content Templates that can be applied to the current document.
*/
public List<SelectItem> getContentTemplates()
{
List<SelectItem> templates = contentTemplates.get();
if (templates == null)
{
// get the template from the special Content Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getContentTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
contentTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available Email Templates.
*/
public List<SelectItem> getEmailTemplates()
{
List<SelectItem> templates = emailTemplates.get();
if (templates == null)
{
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
emailTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available Notify Email Templates.
*/
public List<SelectItem> getNotifyEmailTemplates()
{
List<SelectItem> templates = null;
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "/" +
Application.getNotifyEmailTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
return templates;
}
/**
* @return the list of available RSS Templates.
*/
public List<SelectItem> getRSSTemplates()
{
List<SelectItem> templates = rssTemplates.get();
if (templates == null)
{
// get the template from the special Email Templates folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getRSSTemplatesFolderName(fc) + "//*";
templates = selectDictionaryNodes(fc, xpath, MSG_SELECT_TEMPLATE, MimetypeMap.MIMETYPE_TEXT_PLAIN);
rssTemplates.put(templates);
}
return templates;
}
/**
* @return the list of available JavaScript files that can be applied to the current document.
*/
public List<SelectItem> getScriptFiles()
{
List<SelectItem> scripts = this.scriptFiles.get();
if (scripts == null)
{
// get the scripts from the special Scripts folder
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getScriptsFolderName(fc) + "//*";
scripts = selectDictionaryNodes(fc, xpath, MSG_SELECT_SCRIPT, MimetypeMap.MIMETYPE_JAVASCRIPT);
scriptFiles.put(scripts);
}
return scripts;
}
/**
* @param fc FacesContext
* @param xpath XPath to the nodes to select
* @param noSelectionLabel Label to add to the list if no items are found in the search
*
* @return List of SelectItem wrapper objects for the nodes found at the XPath
*/
private List<SelectItem> selectDictionaryNodes(FacesContext fc, String xpath, String noSelectionLabel)
{
return selectDictionaryNodes(fc, xpath, noSelectionLabel, null);
}
/**
* @param fc FacesContext
* @param xpath XPath to the nodes to select
* @param noSelectionLabel Label to add to the list if no items are found in the search
* @param mimetype Optional mimetype of items to add, will not add to list if mimetype does not match
*
* @return List of SelectItem wrapper objects for the nodes found at the XPath
*/
private List<SelectItem> selectDictionaryNodes(FacesContext fc, String xpath, String noSelectionLabel, String mimetype)
{
List<SelectItem> wrappers = null;
try
{
NodeRef rootNodeRef = this.getNodeService().getRootNode(Repository.getStoreRef());
NamespaceService resolver = Repository.getServiceRegistry(fc).getNamespaceService();
List<NodeRef> results = this.getSearchService().selectNodes(rootNodeRef, xpath, null, resolver, false);
wrappers = new ArrayList<SelectItem>(results.size() + 1);
if (results.size() != 0)
{
DictionaryService dd = Repository.getServiceRegistry(fc).getDictionaryService();
for (NodeRef ref : results)
{
if (this.getNodeService().exists(ref) == true)
{
Node childNode = new Node(ref);
ContentData content = (ContentData)childNode.getProperties().get(ContentModel.PROP_CONTENT);
if (dd.isSubClass(childNode.getType(), ContentModel.TYPE_CONTENT) &&
(mimetype == null || mimetype.equals(content.getMimetype())))
{
wrappers.add(new SelectItem(childNode.getId(), childNode.getName()));
}
}
}
// make sure the list is sorted by the label
QuickSort sorter = new QuickSort(wrappers, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
}
catch (AccessDeniedException accessErr)
{
// ignore the result if we cannot access the root
}
// add an entry (at the start) to instruct the user to select an item
if (wrappers == null)
{
wrappers = new ArrayList<SelectItem>(1);
}
wrappers.add(0, new SelectItem(NO_SELECTION, Application.getMessage(FacesContext.getCurrentInstance(), noSelectionLabel)));
return wrappers;
}
}

View File

@@ -1,25 +1,25 @@
package org.alfresco.web.bean.admin;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
public class AdminConsoleDialog extends BaseDialogBean
{
private static final long serialVersionUID = -2520599525975495006L;
private static final String BUTTON_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return outcome;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), BUTTON_CLOSE);
}
}
package org.alfresco.web.bean.admin;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
public class AdminConsoleDialog extends BaseDialogBean
{
private static final long serialVersionUID = -2520599525975495006L;
private static final String BUTTON_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return outcome;
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), BUTTON_CLOSE);
}
}

View File

@@ -1,61 +1,61 @@
package org.alfresco.web.bean.admin;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.AboutBean;
import org.alfresco.web.bean.dialog.BaseDialogBean;
/**
* Implementation for the SystemInfo dialog.
*
* @author gavinc
*/
public class ShowSystemInfoDialog extends BaseDialogBean
{
private static final long serialVersionUID = 1328587489092603676L;
private static final String MSG_CURRENT_USER = "current_user";
private static final String MSG_CLOSE = "close";
private static final String MSG_VERSION = "version";
protected AboutBean aboutBean;
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return null;
}
public void setAboutBean(AboutBean aboutBean)
{
this.aboutBean = aboutBean;
}
@Override
public String getContainerSubTitle()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CURRENT_USER) + ": " +
this.navigator.getCurrentUser().getUserName();
}
@Override
public String getContainerDescription()
{
StringBuilder builder = new StringBuilder(Application.getMessage(
FacesContext.getCurrentInstance(), MSG_VERSION));
builder.append(": ");
builder.append(this.aboutBean.getEdition());
builder.append(" - v");
builder.append(this.aboutBean.getVersion());
return builder.toString();
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CLOSE);
}
}
package org.alfresco.web.bean.admin;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.AboutBean;
import org.alfresco.web.bean.dialog.BaseDialogBean;
/**
* Implementation for the SystemInfo dialog.
*
* @author gavinc
*/
public class ShowSystemInfoDialog extends BaseDialogBean
{
private static final long serialVersionUID = 1328587489092603676L;
private static final String MSG_CURRENT_USER = "current_user";
private static final String MSG_CLOSE = "close";
private static final String MSG_VERSION = "version";
protected AboutBean aboutBean;
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return null;
}
public void setAboutBean(AboutBean aboutBean)
{
this.aboutBean = aboutBean;
}
@Override
public String getContainerSubTitle()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CURRENT_USER) + ": " +
this.navigator.getCurrentUser().getUserName();
}
@Override
public String getContainerDescription()
{
StringBuilder builder = new StringBuilder(Application.getMessage(
FacesContext.getCurrentInstance(), MSG_VERSION));
builder.append(": ");
builder.append(this.aboutBean.getEdition());
builder.append(" - v");
builder.append(this.aboutBean.getVersion());
return builder.toString();
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_CLOSE);
}
}

View File

@@ -1,329 +1,329 @@
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.transaction.UserTransaction;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.repo.component.UITree.TreeNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CategoryBrowserPluginBean implements Serializable
{
private static final long serialVersionUID = -1493808456969763500L;
public static final String BEAN_NAME = "CategoryBrowserPluginBean";
private static final Log logger = LogFactory.getLog(CategoryBrowserPluginBean.class);
transient private CategoryService categoryService;
transient private NodeService nodeService;
private List<TreeNode> categoryRootNodes;
private Map<String, TreeNode> categoryNodes;
protected NodeRef previouslySelectedNode;
/**
* @param categoryService
* the categoryService to set
*/
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
/**
* @param nodeService
* the nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @return the nodeService
*/
private NodeService getNodeService()
{
//check for null in cluster environment
if(nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
public List<TreeNode> getCategoryRootNodes()
{
if (this.categoryRootNodes == null)
{
this.categoryRootNodes = new ArrayList<TreeNode>();
this.categoryNodes = new HashMap<String, TreeNode>();
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
tx.begin();
Collection<ChildAssociationRef> childRefs = this.getCategoryService().getRootCategories(
Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE);
for (ChildAssociationRef ref : childRefs)
{
NodeRef child = ref.getChildRef();
TreeNode node = createTreeNode(child);
this.categoryRootNodes.add(node);
this.categoryNodes.put(node.getNodeRef(), node);
}
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage("NavigatorPluginBean exception in getCompanyHomeRootNodes()", err);
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception tex)
{
}
}
}
return this.categoryRootNodes;
}
protected Map<String, TreeNode> getNodesMap()
{
return this.categoryNodes;
}
/**
* Retrieves the child folders for the noderef given in the 'noderef' parameter and caches the nodes against the area
* in the 'area' parameter.
*/
public void retrieveChildren() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context, true);
tx.begin();
Map params = context.getExternalContext().getRequestParameterMap();
String nodeRefStr = (String) params.get("nodeRef");
// work out which list to cache the nodes in
Map<String, TreeNode> currentNodes = getNodesMap();
if (nodeRefStr != null && currentNodes != null)
{
// get the given node's details
NodeRef parentNodeRef = new NodeRef(nodeRefStr);
TreeNode parentNode = currentNodes.get(parentNodeRef.toString());
parentNode.setExpanded(true);
if (logger.isDebugEnabled())
logger.debug("retrieving children for noderef: " + parentNodeRef);
// remove any existing children as the latest ones will be added
// below
parentNode.removeChildren();
// get all the child folder objects for the parent
List<ChildAssociationRef> childRefs = this.getNodeService().getChildAssocs(parentNodeRef,
ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL);
List<TreeNode> sortedNodes = new ArrayList<TreeNode>();
for (ChildAssociationRef ref : childRefs)
{
NodeRef nodeRef = ref.getChildRef();
logger.debug("retrieving child : " + nodeRef);
// build the XML representation of the child node
TreeNode childNode = createTreeNode(nodeRef);
parentNode.addChild(childNode);
currentNodes.put(childNode.getNodeRef(), childNode);
sortedNodes.add(childNode);
}
// order the tree nodes by the tree label
if (sortedNodes.size() > 1)
{
QuickSort sorter = new QuickSort(sortedNodes, "name", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
// generate the XML representation
StringBuilder xml = new StringBuilder(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><nodes>");
for (TreeNode childNode : sortedNodes)
{
xml.append(childNode.toXML());
}
xml.append("</nodes>");
// send the generated XML back to the tree
out.write(xml.toString());
if (logger.isDebugEnabled())
logger.debug("returning XML: " + xml.toString());
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception tex)
{
}
}
}
/**
* Sets the state of the node given in the 'nodeRef' parameter to collapsed
*/
public void nodeCollapsed() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
Map params = context.getExternalContext().getRequestParameterMap();
String nodeRefStr = (String) params.get("nodeRef");
// work out which list to cache the nodes in
Map<String, TreeNode> currentNodes = getNodesMap();
if (nodeRefStr != null && currentNodes != null)
{
TreeNode treeNode = currentNodes.get(nodeRefStr);
if (treeNode != null)
{
treeNode.setExpanded(false);
// we need to return something for the client to be happy!
out.write("<ok/>");
if (logger.isDebugEnabled())
logger.debug("Set node " + treeNode + " to collapsed state");
}
}
}
public void selectNode(NodeRef selectedNode, String area)
{
// if there is a currently selected node, get hold of
// it (from any of the areas) and reset to unselected
if (this.previouslySelectedNode != null)
{
TreeNode node = this.categoryNodes.get(this.previouslySelectedNode.toString());
if (node != null)
{
node.setSelected(false);
}
}
// find the node just selected and set its state to selected
if (selectedNode != null)
{
TreeNode node = this.categoryNodes.get(selectedNode.toString());
if (node != null)
{
node.setSelected(true);
}
}
this.previouslySelectedNode = selectedNode;
if (logger.isDebugEnabled())
logger.debug("Selected node: " + selectedNode);
}
/**
* Resets the selected node
*/
public void resetSelectedNode()
{
if (this.previouslySelectedNode != null)
{
TreeNode node = this.categoryNodes.get(this.previouslySelectedNode.toString());
if (node != null)
{
node.setSelected(false);
}
}
if (logger.isDebugEnabled())
logger.debug("Reset selected node: " + this.previouslySelectedNode);
}
/**
* Resets all the caches held by the bean.
*/
public void reset()
{
this.categoryNodes = null;
this.categoryRootNodes = null;
resetSelectedNode();
}
/**
* Creates a TreeNode object from the given NodeRef
*
* @param nodeRef
* The NodeRef to create the TreeNode from
*/
protected TreeNode createTreeNode(NodeRef nodeRef)
{
TreeNode node = new TreeNode(nodeRef.toString(), Repository.getNameForNode(this.getNodeService(), nodeRef),
(String) this.getNodeService().getProperty(nodeRef, ApplicationModel.PROP_ICON));
return node;
}
}
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.transaction.UserTransaction;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.repo.component.UITree.TreeNode;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CategoryBrowserPluginBean implements Serializable
{
private static final long serialVersionUID = -1493808456969763500L;
public static final String BEAN_NAME = "CategoryBrowserPluginBean";
private static final Log logger = LogFactory.getLog(CategoryBrowserPluginBean.class);
transient private CategoryService categoryService;
transient private NodeService nodeService;
private List<TreeNode> categoryRootNodes;
private Map<String, TreeNode> categoryNodes;
protected NodeRef previouslySelectedNode;
/**
* @param categoryService
* the categoryService to set
*/
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
/**
* @param nodeService
* the nodeService to set
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @return the nodeService
*/
private NodeService getNodeService()
{
//check for null in cluster environment
if(nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
public List<TreeNode> getCategoryRootNodes()
{
if (this.categoryRootNodes == null)
{
this.categoryRootNodes = new ArrayList<TreeNode>();
this.categoryNodes = new HashMap<String, TreeNode>();
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
tx.begin();
Collection<ChildAssociationRef> childRefs = this.getCategoryService().getRootCategories(
Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE);
for (ChildAssociationRef ref : childRefs)
{
NodeRef child = ref.getChildRef();
TreeNode node = createTreeNode(child);
this.categoryRootNodes.add(node);
this.categoryNodes.put(node.getNodeRef(), node);
}
tx.commit();
}
catch (Throwable err)
{
Utils.addErrorMessage("NavigatorPluginBean exception in getCompanyHomeRootNodes()", err);
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception tex)
{
}
}
}
return this.categoryRootNodes;
}
protected Map<String, TreeNode> getNodesMap()
{
return this.categoryNodes;
}
/**
* Retrieves the child folders for the noderef given in the 'noderef' parameter and caches the nodes against the area
* in the 'area' parameter.
*/
public void retrieveChildren() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context, true);
tx.begin();
Map params = context.getExternalContext().getRequestParameterMap();
String nodeRefStr = (String) params.get("nodeRef");
// work out which list to cache the nodes in
Map<String, TreeNode> currentNodes = getNodesMap();
if (nodeRefStr != null && currentNodes != null)
{
// get the given node's details
NodeRef parentNodeRef = new NodeRef(nodeRefStr);
TreeNode parentNode = currentNodes.get(parentNodeRef.toString());
parentNode.setExpanded(true);
if (logger.isDebugEnabled())
logger.debug("retrieving children for noderef: " + parentNodeRef);
// remove any existing children as the latest ones will be added
// below
parentNode.removeChildren();
// get all the child folder objects for the parent
List<ChildAssociationRef> childRefs = this.getNodeService().getChildAssocs(parentNodeRef,
ContentModel.ASSOC_SUBCATEGORIES, RegexQNamePattern.MATCH_ALL);
List<TreeNode> sortedNodes = new ArrayList<TreeNode>();
for (ChildAssociationRef ref : childRefs)
{
NodeRef nodeRef = ref.getChildRef();
logger.debug("retrieving child : " + nodeRef);
// build the XML representation of the child node
TreeNode childNode = createTreeNode(nodeRef);
parentNode.addChild(childNode);
currentNodes.put(childNode.getNodeRef(), childNode);
sortedNodes.add(childNode);
}
// order the tree nodes by the tree label
if (sortedNodes.size() > 1)
{
QuickSort sorter = new QuickSort(sortedNodes, "name", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
// generate the XML representation
StringBuilder xml = new StringBuilder(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><nodes>");
for (TreeNode childNode : sortedNodes)
{
xml.append(childNode.toXML());
}
xml.append("</nodes>");
// send the generated XML back to the tree
out.write(xml.toString());
if (logger.isDebugEnabled())
logger.debug("returning XML: " + xml.toString());
}
// commit the transaction
tx.commit();
}
catch (Throwable err)
{
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception tex)
{
}
}
}
/**
* Sets the state of the node given in the 'nodeRef' parameter to collapsed
*/
public void nodeCollapsed() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
Map params = context.getExternalContext().getRequestParameterMap();
String nodeRefStr = (String) params.get("nodeRef");
// work out which list to cache the nodes in
Map<String, TreeNode> currentNodes = getNodesMap();
if (nodeRefStr != null && currentNodes != null)
{
TreeNode treeNode = currentNodes.get(nodeRefStr);
if (treeNode != null)
{
treeNode.setExpanded(false);
// we need to return something for the client to be happy!
out.write("<ok/>");
if (logger.isDebugEnabled())
logger.debug("Set node " + treeNode + " to collapsed state");
}
}
}
public void selectNode(NodeRef selectedNode, String area)
{
// if there is a currently selected node, get hold of
// it (from any of the areas) and reset to unselected
if (this.previouslySelectedNode != null)
{
TreeNode node = this.categoryNodes.get(this.previouslySelectedNode.toString());
if (node != null)
{
node.setSelected(false);
}
}
// find the node just selected and set its state to selected
if (selectedNode != null)
{
TreeNode node = this.categoryNodes.get(selectedNode.toString());
if (node != null)
{
node.setSelected(true);
}
}
this.previouslySelectedNode = selectedNode;
if (logger.isDebugEnabled())
logger.debug("Selected node: " + selectedNode);
}
/**
* Resets the selected node
*/
public void resetSelectedNode()
{
if (this.previouslySelectedNode != null)
{
TreeNode node = this.categoryNodes.get(this.previouslySelectedNode.toString());
if (node != null)
{
node.setSelected(false);
}
}
if (logger.isDebugEnabled())
logger.debug("Reset selected node: " + this.previouslySelectedNode);
}
/**
* Resets all the caches held by the bean.
*/
public void reset()
{
this.categoryNodes = null;
this.categoryRootNodes = null;
resetSelectedNode();
}
/**
* Creates a TreeNode object from the given NodeRef
*
* @param nodeRef
* The NodeRef to create the TreeNode from
*/
protected TreeNode createTreeNode(NodeRef nodeRef)
{
TreeNode node = new TreeNode(nodeRef.toString(), Repository.getNameForNode(this.getNodeService(), nodeRef),
(String) this.getNodeService().getProperty(nodeRef, ApplicationModel.PROP_ICON));
return node;
}
}

View File

@@ -1,126 +1,126 @@
package org.alfresco.web.bean.ajax;
import java.io.File;
import java.io.Serializable;
import java.util.List;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.TempFileProvider;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.util.XMLUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Bean managing the ajax servlet upload of a multi-part form containing file content
* to replace the content of a node within the repository.
*
* @author Mike Hatfield
*/
public class ContentUpdateBean implements Serializable
{
private static final long serialVersionUID = -7209326198823950952L;
private static Log logger = LogFactory.getLog(ContentUpdateBean.class);
/**
* Ajax method to update file content. A multi-part form is required as the input.
*
* "return-page" = javascript to execute on return from the upload request
* "nodeRef" = the nodeRef of the item to update the content of
*
* @throws Exception
*/
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void updateFile() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext externalContext = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setHeaderEncoding("UTF-8");
List<FileItem> fileItems = upload.parseRequest(request);
String strNodeRef = null;
String strFilename = null;
String strReturnPage = null;
File file = null;
for (FileItem item : fileItems)
{
if (item.isFormField() && item.getFieldName().equals("return-page"))
{
strReturnPage = item.getString();
}
else if (item.isFormField() && item.getFieldName().equals("nodeRef"))
{
strNodeRef = item.getString();
}
else
{
strFilename = FilenameUtils.getName(item.getName());
file = TempFileProvider.createTempFile("alfresco", ".upload");
item.write(file);
}
}
if (logger.isDebugEnabled())
logger.debug("Ajax content update request: " + strFilename + " to nodeRef: " + strNodeRef + " return page: " + strReturnPage);
try
{
if (file != null && strNodeRef != null && strNodeRef.length() != 0)
{
NodeRef nodeRef = new NodeRef(strNodeRef);
if (nodeRef != null)
{
ServiceRegistry services = Repository.getServiceRegistry(fc);
// get a writer for the content and put the file
ContentWriter writer = services.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
writer.putContent(file);
}
}
}
catch (Exception e)
{
strReturnPage = strReturnPage.replace("${UPLOAD_ERROR}", e.getMessage());
}
Document result = XMLUtil.newDocument();
Element htmlEl = result.createElement("html");
result.appendChild(htmlEl);
Element bodyEl = result.createElement("body");
htmlEl.appendChild(bodyEl);
Element scriptEl = result.createElement("script");
bodyEl.appendChild(scriptEl);
scriptEl.setAttribute("type", "text/javascript");
Node scriptText = result.createTextNode(strReturnPage);
scriptEl.appendChild(scriptText);
if (logger.isDebugEnabled())
logger.debug("Content update request complete.");
ResponseWriter out = fc.getResponseWriter();
XMLUtil.print(result, out);
}
}
package org.alfresco.web.bean.ajax;
import java.io.File;
import java.io.Serializable;
import java.util.List;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.TempFileProvider;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.util.XMLUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Bean managing the ajax servlet upload of a multi-part form containing file content
* to replace the content of a node within the repository.
*
* @author Mike Hatfield
*/
public class ContentUpdateBean implements Serializable
{
private static final long serialVersionUID = -7209326198823950952L;
private static Log logger = LogFactory.getLog(ContentUpdateBean.class);
/**
* Ajax method to update file content. A multi-part form is required as the input.
*
* "return-page" = javascript to execute on return from the upload request
* "nodeRef" = the nodeRef of the item to update the content of
*
* @throws Exception
*/
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void updateFile() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext externalContext = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setHeaderEncoding("UTF-8");
List<FileItem> fileItems = upload.parseRequest(request);
String strNodeRef = null;
String strFilename = null;
String strReturnPage = null;
File file = null;
for (FileItem item : fileItems)
{
if (item.isFormField() && item.getFieldName().equals("return-page"))
{
strReturnPage = item.getString();
}
else if (item.isFormField() && item.getFieldName().equals("nodeRef"))
{
strNodeRef = item.getString();
}
else
{
strFilename = FilenameUtils.getName(item.getName());
file = TempFileProvider.createTempFile("alfresco", ".upload");
item.write(file);
}
}
if (logger.isDebugEnabled())
logger.debug("Ajax content update request: " + strFilename + " to nodeRef: " + strNodeRef + " return page: " + strReturnPage);
try
{
if (file != null && strNodeRef != null && strNodeRef.length() != 0)
{
NodeRef nodeRef = new NodeRef(strNodeRef);
if (nodeRef != null)
{
ServiceRegistry services = Repository.getServiceRegistry(fc);
// get a writer for the content and put the file
ContentWriter writer = services.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
writer.putContent(file);
}
}
}
catch (Exception e)
{
strReturnPage = strReturnPage.replace("${UPLOAD_ERROR}", e.getMessage());
}
Document result = XMLUtil.newDocument();
Element htmlEl = result.createElement("html");
result.appendChild(htmlEl);
Element bodyEl = result.createElement("body");
htmlEl.appendChild(bodyEl);
Element scriptEl = result.createElement("script");
bodyEl.appendChild(scriptEl);
scriptEl.setAttribute("type", "text/javascript");
Node scriptText = result.createTextNode(strReturnPage);
scriptEl.appendChild(scriptText);
if (logger.isDebugEnabled())
logger.debug("Content update request complete.");
ResponseWriter out = fc.getResponseWriter();
XMLUtil.print(result, out);
}
}

View File

@@ -1,229 +1,229 @@
package org.alfresco.web.bean.ajax;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.TempFileProvider;
import org.springframework.extensions.surf.util.URLDecoder;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.util.XMLUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Bean managing the ajax servlet upload of a multi-part form containing file content
* to be added at a specific path in the server.
*
* @author Kevin Roast
*/
public class FileUploadBean implements Serializable
{
private static final long serialVersionUID = 4555828718375916674L;
private static Log logger = LogFactory.getLog(FileUploadBean.class);
/**
* Ajax method to upload file content. A multi-part form is required as the input.
*
* "return-page" = javascript to execute on return from the upload request
* "currentPath" = the cm:name based server path to upload the content into
* and the file item content.
*
* @throws Exception
*/
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void uploadFile() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext externalContext = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setHeaderEncoding("UTF-8");
List<FileItem> fileItems = upload.parseRequest(request);
FileUploadBean bean = new FileUploadBean();
String currentPath = null;
String filename = null;
String returnPage = null;
File file = null;
for (FileItem item : fileItems)
{
if (item.isFormField() && item.getFieldName().equals("return-page"))
{
returnPage = item.getString();
}
else if (item.isFormField() && item.getFieldName().equals("currentPath"))
{
currentPath = URLDecoder.decode(item.getString());
}
else
{
filename = FilenameUtils.getName(item.getName());
file = TempFileProvider.createTempFile("alfresco", ".upload");
item.write(file);
}
}
if (logger.isDebugEnabled())
logger.debug("Ajax file upload request: " + filename + " to path: " + currentPath + " return page: " + returnPage);
try
{
if (file != null && currentPath != null && currentPath.length() != 0)
{
NodeRef containerRef = pathToNodeRef(fc, currentPath);
if (containerRef != null)
{
// Guess the mimetype
String mimetype = Repository.getMimeTypeForFileName(fc, filename);
// Now guess the encoding
String encoding = "UTF-8";
InputStream is = null;
try
{
is = new BufferedInputStream(new FileInputStream(file));
encoding = Repository.guessEncoding(fc, is, mimetype);
}
catch (Throwable e)
{
// Bad as it is, it's not terminal
logger.error("Failed to guess character encoding of file: " + file, e);
}
finally
{
if (is != null)
{
try { is.close(); } catch (Throwable e) {}
}
}
// Try and extract metadata from the file
ContentReader cr = new FileContentReader(file);
cr.setMimetype(mimetype);
// create properties for content type
String author = null;
String title = null;
String description = null;
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(5, 1.0f);
if (Repository.extractMetadata(fc, cr, contentProps))
{
author = (String)(contentProps.get(ContentModel.PROP_AUTHOR));
title = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_TITLE));
description = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_DESCRIPTION));
}
// default the title to the file name if not set
if (title == null)
{
title = filename;
}
ServiceRegistry services = Repository.getServiceRegistry(fc);
FileInfo fileInfo = services.getFileFolderService().create(
containerRef, filename, ContentModel.TYPE_CONTENT);
NodeRef fileNodeRef = fileInfo.getNodeRef();
// set the author aspect
if (author != null)
{
Map<QName, Serializable> authorProps = new HashMap<QName, Serializable>(1, 1.0f);
authorProps.put(ContentModel.PROP_AUTHOR, author);
services.getNodeService().addAspect(fileNodeRef, ContentModel.ASPECT_AUTHOR, authorProps);
}
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(2, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, title);
titledProps.put(ContentModel.PROP_DESCRIPTION, description);
services.getNodeService().addAspect(fileNodeRef, ContentModel.ASPECT_TITLED, titledProps);
// get a writer for the content and put the file
ContentWriter writer = services.getContentService().getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(mimetype);
writer.setEncoding(encoding);
writer.putContent(file);
}
}
}
catch (Exception e)
{
returnPage = returnPage.replace("${UPLOAD_ERROR}", e.getMessage());
}
finally
{
if(file != null)
{
logger.debug("delete temporary file:" + file.getPath());
// Delete the temporary file
file.delete();
}
}
Document result = XMLUtil.newDocument();
Element htmlEl = result.createElement("html");
result.appendChild(htmlEl);
Element bodyEl = result.createElement("body");
htmlEl.appendChild(bodyEl);
Element scriptEl = result.createElement("script");
bodyEl.appendChild(scriptEl);
scriptEl.setAttribute("type", "text/javascript");
Node scriptText = result.createTextNode(returnPage);
scriptEl.appendChild(scriptText);
if (logger.isDebugEnabled())
{
logger.debug("File upload request complete.");
}
ResponseWriter out = fc.getResponseWriter();
XMLUtil.print(result, out);
}
static NodeRef pathToNodeRef(FacesContext fc, String path)
{
// convert cm:name based path to a NodeRef
StringTokenizer t = new StringTokenizer(path, "/");
int tokenCount = t.countTokens();
String[] elements = new String[tokenCount];
for (int i=0; i<tokenCount; i++)
{
elements[i] = t.nextToken();
}
return BaseServlet.resolveWebDAVPath(fc, elements, false);
}
}
package org.alfresco.web.bean.ajax;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.TempFileProvider;
import org.springframework.extensions.surf.util.URLDecoder;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.util.XMLUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Bean managing the ajax servlet upload of a multi-part form containing file content
* to be added at a specific path in the server.
*
* @author Kevin Roast
*/
public class FileUploadBean implements Serializable
{
private static final long serialVersionUID = 4555828718375916674L;
private static Log logger = LogFactory.getLog(FileUploadBean.class);
/**
* Ajax method to upload file content. A multi-part form is required as the input.
*
* "return-page" = javascript to execute on return from the upload request
* "currentPath" = the cm:name based server path to upload the content into
* and the file item content.
*
* @throws Exception
*/
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void uploadFile() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext externalContext = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest)externalContext.getRequest();
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
upload.setHeaderEncoding("UTF-8");
List<FileItem> fileItems = upload.parseRequest(request);
FileUploadBean bean = new FileUploadBean();
String currentPath = null;
String filename = null;
String returnPage = null;
File file = null;
for (FileItem item : fileItems)
{
if (item.isFormField() && item.getFieldName().equals("return-page"))
{
returnPage = item.getString();
}
else if (item.isFormField() && item.getFieldName().equals("currentPath"))
{
currentPath = URLDecoder.decode(item.getString());
}
else
{
filename = FilenameUtils.getName(item.getName());
file = TempFileProvider.createTempFile("alfresco", ".upload");
item.write(file);
}
}
if (logger.isDebugEnabled())
logger.debug("Ajax file upload request: " + filename + " to path: " + currentPath + " return page: " + returnPage);
try
{
if (file != null && currentPath != null && currentPath.length() != 0)
{
NodeRef containerRef = pathToNodeRef(fc, currentPath);
if (containerRef != null)
{
// Guess the mimetype
String mimetype = Repository.getMimeTypeForFileName(fc, filename);
// Now guess the encoding
String encoding = "UTF-8";
InputStream is = null;
try
{
is = new BufferedInputStream(new FileInputStream(file));
encoding = Repository.guessEncoding(fc, is, mimetype);
}
catch (Throwable e)
{
// Bad as it is, it's not terminal
logger.error("Failed to guess character encoding of file: " + file, e);
}
finally
{
if (is != null)
{
try { is.close(); } catch (Throwable e) {}
}
}
// Try and extract metadata from the file
ContentReader cr = new FileContentReader(file);
cr.setMimetype(mimetype);
// create properties for content type
String author = null;
String title = null;
String description = null;
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(5, 1.0f);
if (Repository.extractMetadata(fc, cr, contentProps))
{
author = (String)(contentProps.get(ContentModel.PROP_AUTHOR));
title = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_TITLE));
description = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_DESCRIPTION));
}
// default the title to the file name if not set
if (title == null)
{
title = filename;
}
ServiceRegistry services = Repository.getServiceRegistry(fc);
FileInfo fileInfo = services.getFileFolderService().create(
containerRef, filename, ContentModel.TYPE_CONTENT);
NodeRef fileNodeRef = fileInfo.getNodeRef();
// set the author aspect
if (author != null)
{
Map<QName, Serializable> authorProps = new HashMap<QName, Serializable>(1, 1.0f);
authorProps.put(ContentModel.PROP_AUTHOR, author);
services.getNodeService().addAspect(fileNodeRef, ContentModel.ASPECT_AUTHOR, authorProps);
}
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(2, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, title);
titledProps.put(ContentModel.PROP_DESCRIPTION, description);
services.getNodeService().addAspect(fileNodeRef, ContentModel.ASPECT_TITLED, titledProps);
// get a writer for the content and put the file
ContentWriter writer = services.getContentService().getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
writer.setMimetype(mimetype);
writer.setEncoding(encoding);
writer.putContent(file);
}
}
}
catch (Exception e)
{
returnPage = returnPage.replace("${UPLOAD_ERROR}", e.getMessage());
}
finally
{
if(file != null)
{
logger.debug("delete temporary file:" + file.getPath());
// Delete the temporary file
file.delete();
}
}
Document result = XMLUtil.newDocument();
Element htmlEl = result.createElement("html");
result.appendChild(htmlEl);
Element bodyEl = result.createElement("body");
htmlEl.appendChild(bodyEl);
Element scriptEl = result.createElement("script");
bodyEl.appendChild(scriptEl);
scriptEl.setAttribute("type", "text/javascript");
Node scriptText = result.createTextNode(returnPage);
scriptEl.appendChild(scriptText);
if (logger.isDebugEnabled())
{
logger.debug("File upload request complete.");
}
ResponseWriter out = fc.getResponseWriter();
XMLUtil.print(result, out);
}
static NodeRef pathToNodeRef(FacesContext fc, String path)
{
// convert cm:name based path to a NodeRef
StringTokenizer t = new StringTokenizer(path, "/");
int tokenCount = t.countTokens();
String[] elements = new String[tokenCount];
for (int i=0; i<tokenCount; i++)
{
elements[i] = t.nextToken();
}
return BaseServlet.resolveWebDAVPath(fc, elements, false);
}
}

View File

@@ -1,85 +1,85 @@
package org.alfresco.web.bean.ajax;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.spaces.CreateSpaceWizard;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean backing the ajax requests from the MySpaces portlet webscript.
*
* @author Kevin Roast
*/
public class MySpacesBean implements Serializable
{
private static final long serialVersionUID = -5684182834188359483L;
private static Log logger = LogFactory.getLog(MySpacesBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void createSpace() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String path = (String)requestMap.get("path");
String name = (String)requestMap.get("name");
String title = (String)requestMap.get("title");
String description = (String)requestMap.get("description");
if (logger.isDebugEnabled())
logger.debug("MySpacesBean.createSpace() path=" + path + " name=" + name +
" title=" + title + " description=" + description);
try
{
if (path != null && name != null)
{
NodeRef containerRef = FileUploadBean.pathToNodeRef(fc, path);
if (containerRef != null)
{
NodeService nodeService = Repository.getServiceRegistry(fc).getNodeService();
FileFolderService ffService = Repository.getServiceRegistry(fc).getFileFolderService();
FileInfo folderInfo = ffService.create(containerRef, name, ContentModel.TYPE_FOLDER);
if (logger.isDebugEnabled())
logger.debug("Created new folder: " + folderInfo.getNodeRef().toString());
// apply the uifacets aspect - icon, title and description properties
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4, 1.0f);
uiFacetsProps.put(ApplicationModel.PROP_ICON, CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME);
uiFacetsProps.put(ContentModel.PROP_TITLE, title);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, description);
nodeService.addAspect(folderInfo.getNodeRef(), ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
out.write("OK: " + folderInfo.getNodeRef().toString());
}
}
}
catch (FileExistsException ferr)
{
out.write("ERROR: A file with that name already exists.");
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
package org.alfresco.web.bean.ajax;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.spaces.CreateSpaceWizard;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean backing the ajax requests from the MySpaces portlet webscript.
*
* @author Kevin Roast
*/
public class MySpacesBean implements Serializable
{
private static final long serialVersionUID = -5684182834188359483L;
private static Log logger = LogFactory.getLog(MySpacesBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void createSpace() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String path = (String)requestMap.get("path");
String name = (String)requestMap.get("name");
String title = (String)requestMap.get("title");
String description = (String)requestMap.get("description");
if (logger.isDebugEnabled())
logger.debug("MySpacesBean.createSpace() path=" + path + " name=" + name +
" title=" + title + " description=" + description);
try
{
if (path != null && name != null)
{
NodeRef containerRef = FileUploadBean.pathToNodeRef(fc, path);
if (containerRef != null)
{
NodeService nodeService = Repository.getServiceRegistry(fc).getNodeService();
FileFolderService ffService = Repository.getServiceRegistry(fc).getFileFolderService();
FileInfo folderInfo = ffService.create(containerRef, name, ContentModel.TYPE_FOLDER);
if (logger.isDebugEnabled())
logger.debug("Created new folder: " + folderInfo.getNodeRef().toString());
// apply the uifacets aspect - icon, title and description properties
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4, 1.0f);
uiFacetsProps.put(ApplicationModel.PROP_ICON, CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME);
uiFacetsProps.put(ContentModel.PROP_TITLE, title);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, description);
nodeService.addAspect(folderInfo.getNodeRef(), ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
out.write("OK: " + folderInfo.getNodeRef().toString());
}
}
}
catch (FileExistsException ferr)
{
out.write("ERROR: A file with that name already exists.");
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}

View File

@@ -1,160 +1,160 @@
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.repo.content.transform.TransformerInfoException;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateException;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean used by an AJAX control to send information back on the
* requested node.
*
* @author gavinc
*/
public class NodeInfoBean implements Serializable
{
private static final long serialVersionUID = 137294178658919187L;
transient private NodeService nodeService;
private static final Log logger = LogFactory.getLog(NodeInfoBean.class);
/**
* Returns information on the node identified by the 'noderef'
* parameter found in the ExternalContext. If no noderef is supplied, then the template
* is executed without context.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendNodeInfo() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
String strTemplate = (String)requestMap.get("template");
if (strTemplate == null || strTemplate.length() == 0)
{
strTemplate = "node_summary_panel.ftl";
}
NodeRef nodeRef = null;
if (strNodeRef != null && strNodeRef.length() != 0)
{
nodeRef = new NodeRef(strNodeRef);
if (this.getNodeService().exists(nodeRef) == false)
{
out.write("<span class='errorMessage'>Node could not be found in the repository!</span>");
return;
}
}
try
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/" + strTemplate, getModel(nodeRef, requestMap), out);
}
catch (TemplateException ex)
{
// Try to catch TransformerInfoException to display it in NodeInfo pane.
// Fix bug reported in https://issues.alfresco.com/jira/browse/ETWOTWO-440
Throwable cause = ex.getCause();
while (cause != null)
{
cause = cause.getCause();
if (cause instanceof TransformerInfoException)
{
out.write("<tr><td colspan=\"2\"><span class='errorMessage'>" + cause.getMessage() + "</span></td></tr>");
return;
}
}
throw ex;
}
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @param nodeService The NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
// ------------------------------------------------------------------------------
// Helper methods
private Map<String, Object> getModel(NodeRef nodeRef, Map<String, String> requestMap) throws ContentIOException
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
I18NUtil.registerResourceBundle("alfresco.messages.webclient");
// create api methods
model.put("date", new Date());
model.put("msg", new I18NMessageMethod());
model.put("url", new BaseTemplateContentServlet.URLHelper(context));
model.put("locale", I18NUtil.getLocale());
if (nodeRef != null)
{
model.put("node", new TemplateNode(
nodeRef,
Repository.getServiceRegistry(context),
this.imageResolver));
}
// add URL arguments as a map called 'args' to the root of the model
Map<String, String> args = new HashMap<String, String>(4, 1.0f);
for (String name : requestMap.keySet())
{
args.put(name, requestMap.get(name));
}
model.put("args", args);
return model;
}
/** Template Image resolver helper */
private TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size);
}
};
}
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.repo.content.transform.TransformerInfoException;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateException;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean used by an AJAX control to send information back on the
* requested node.
*
* @author gavinc
*/
public class NodeInfoBean implements Serializable
{
private static final long serialVersionUID = 137294178658919187L;
transient private NodeService nodeService;
private static final Log logger = LogFactory.getLog(NodeInfoBean.class);
/**
* Returns information on the node identified by the 'noderef'
* parameter found in the ExternalContext. If no noderef is supplied, then the template
* is executed without context.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendNodeInfo() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
String strTemplate = (String)requestMap.get("template");
if (strTemplate == null || strTemplate.length() == 0)
{
strTemplate = "node_summary_panel.ftl";
}
NodeRef nodeRef = null;
if (strNodeRef != null && strNodeRef.length() != 0)
{
nodeRef = new NodeRef(strNodeRef);
if (this.getNodeService().exists(nodeRef) == false)
{
out.write("<span class='errorMessage'>Node could not be found in the repository!</span>");
return;
}
}
try
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/" + strTemplate, getModel(nodeRef, requestMap), out);
}
catch (TemplateException ex)
{
// Try to catch TransformerInfoException to display it in NodeInfo pane.
// Fix bug reported in https://issues.alfresco.com/jira/browse/ETWOTWO-440
Throwable cause = ex.getCause();
while (cause != null)
{
cause = cause.getCause();
if (cause instanceof TransformerInfoException)
{
out.write("<tr><td colspan=\"2\"><span class='errorMessage'>" + cause.getMessage() + "</span></td></tr>");
return;
}
}
throw ex;
}
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @param nodeService The NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
// ------------------------------------------------------------------------------
// Helper methods
private Map<String, Object> getModel(NodeRef nodeRef, Map<String, String> requestMap) throws ContentIOException
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
I18NUtil.registerResourceBundle("alfresco.messages.webclient");
// create api methods
model.put("date", new Date());
model.put("msg", new I18NMessageMethod());
model.put("url", new BaseTemplateContentServlet.URLHelper(context));
model.put("locale", I18NUtil.getLocale());
if (nodeRef != null)
{
model.put("node", new TemplateNode(
nodeRef,
Repository.getServiceRegistry(context),
this.imageResolver));
}
// add URL arguments as a map called 'args' to the root of the model
Map<String, String> args = new HashMap<String, String>(4, 1.0f);
for (String name : requestMap.keySet())
{
args.put(name, requestMap.get(name));
}
model.put("args", args);
return model;
}
/** Template Image resolver helper */
private TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size);
}
};
}

View File

@@ -1,99 +1,99 @@
package org.alfresco.web.bean.ajax;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean backing the ajax requests from various Portlet webscripts.
*
* @author Mike Hatfield
*/
public class PortletActionsBean implements Serializable
{
private static final long serialVersionUID = -8230154592621310289L;
private static Log logger = LogFactory.getLog(PortletActionsBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void deleteItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Repository.getServiceRegistry(fc).getFileFolderService().delete(new NodeRef(strNodeRef));
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void checkoutItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Repository.getServiceRegistry(fc).getCheckOutCheckInService().checkout(new NodeRef(strNodeRef));
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void checkinItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Map<String, Serializable> props = new HashMap<String, Serializable>(2, 1.0f);
props.put(Version.PROP_DESCRIPTION, "");
props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
Repository.getServiceRegistry(fc).getCheckOutCheckInService().checkin(new NodeRef(strNodeRef), props);
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
package org.alfresco.web.bean.ajax;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean backing the ajax requests from various Portlet webscripts.
*
* @author Mike Hatfield
*/
public class PortletActionsBean implements Serializable
{
private static final long serialVersionUID = -8230154592621310289L;
private static Log logger = LogFactory.getLog(PortletActionsBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void deleteItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Repository.getServiceRegistry(fc).getFileFolderService().delete(new NodeRef(strNodeRef));
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void checkoutItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Repository.getServiceRegistry(fc).getCheckOutCheckInService().checkout(new NodeRef(strNodeRef));
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void checkinItem() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String strNodeRef = (String)requestMap.get("noderef");
if (strNodeRef != null && strNodeRef.length() != 0)
{
try
{
Map<String, Serializable> props = new HashMap<String, Serializable>(2, 1.0f);
props.put(Version.PROP_DESCRIPTION, "");
props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
Repository.getServiceRegistry(fc).getCheckOutCheckInService().checkin(new NodeRef(strNodeRef), props);
out.write("OK: " + strNodeRef);
}
catch (Throwable err)
{
out.write("ERROR: " + err.getMessage());
}
}
}
}

View File

@@ -1,90 +1,90 @@
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean which proxies requests to online presence servers.
*
* @author Mike Hatfield
*/
public class PresenceProxyBean implements Serializable
{
private static final long serialVersionUID = -3041576848188629589L;
private static Log logger = LogFactory.getLog(PresenceProxyBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void proxyRequest() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String url = (String)requestMap.get("url");
if (logger.isDebugEnabled())
logger.debug("PresenceProxyBean.proxyRequest() url=" + url);
if (url != null)
{
String response = getUrlResponse(url);
out.write(response);
}
}
/**
* Perform request
*/
public String getUrlResponse(String requestUrl)
{
String response = "";
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(requestUrl);
method.setRequestHeader("Accept", "*/*");
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
try
{
int statusCode = client.executeMethod(method);
if (statusCode == HttpStatus.SC_OK)
{
response = method.getResponseBodyAsString();
}
else
{
response = method.getStatusText();
}
}
catch (HttpException e)
{
response = e.getMessage();
}
catch (IOException e)
{
response = e.getMessage();
}
finally
{
// Release the connection.
method.releaseConnection();
}
return response;
}
}
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean which proxies requests to online presence servers.
*
* @author Mike Hatfield
*/
public class PresenceProxyBean implements Serializable
{
private static final long serialVersionUID = -3041576848188629589L;
private static Log logger = LogFactory.getLog(PresenceProxyBean.class);
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
public void proxyRequest() throws Exception
{
FacesContext fc = FacesContext.getCurrentInstance();
ResponseWriter out = fc.getResponseWriter();
Map<String, String> requestMap = fc.getExternalContext().getRequestParameterMap();
String url = (String)requestMap.get("url");
if (logger.isDebugEnabled())
logger.debug("PresenceProxyBean.proxyRequest() url=" + url);
if (url != null)
{
String response = getUrlResponse(url);
out.write(response);
}
}
/**
* Perform request
*/
public String getUrlResponse(String requestUrl)
{
String response = "";
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(requestUrl);
method.setRequestHeader("Accept", "*/*");
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
try
{
int statusCode = client.executeMethod(method);
if (statusCode == HttpStatus.SC_OK)
{
response = method.getResponseBodyAsString();
}
else
{
response = method.getStatusText();
}
}
catch (HttpException e)
{
response = e.getMessage();
}
catch (IOException e)
{
response = e.getMessage();
}
finally
{
// Release the connection.
method.releaseConnection();
}
return response;
}
}

View File

@@ -1,144 +1,144 @@
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.repo.template.Workflow;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Bean used by an AJAX control to send information back on the requested workflow task.
*
* @author Kevin Roast
*/
public class TaskInfoBean implements Serializable
{
private static final long serialVersionUID = -6627537519541525897L;
transient private WorkflowService workflowService;
/**
* Returns information for the workflow task identified by the 'taskId'
* parameter found in the ExternalContext.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendTaskInfo() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
String taskId = (String)context.getExternalContext().getRequestParameterMap().get("taskId");
if (taskId == null || taskId.length() == 0)
{
throw new IllegalArgumentException("'taskId' parameter is missing");
}
WorkflowTask task = this.getWorkflowService().getTaskById(taskId);
if (task != null)
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/task_summary_panel.ftl", getModel(task), out);
}
else
{
out.write("<span class='errorMessage'>Task could not be found.</span>");
}
}
/**
* Returns the resource list for the workflow task identified by the 'taskId'
* parameter found in the ExternalContext.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendTaskResources() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
String taskId = (String)context.getExternalContext().getRequestParameterMap().get("taskId");
if (taskId == null || taskId.length() == 0)
{
throw new IllegalArgumentException("'taskId' parameter is missing");
}
WorkflowTask task = this.getWorkflowService().getTaskById(taskId);
if (task != null)
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/task_resource_panel.ftl", getModel(task), out);
}
else
{
out.write("<span class='errorMessage'>Task could not be found.</span>");
}
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @param workflowService The WorkflowService to set.
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
private WorkflowService getWorkflowService()
{
if (workflowService == null)
{
workflowService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getWorkflowService();
}
return workflowService;
}
// ------------------------------------------------------------------------------
// Helper methods
private Map<String, Object> getModel(WorkflowTask task)
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
I18NUtil.registerResourceBundle("alfresco.messages.webclient");
// create template api methods and objects
model.put("date", new Date());
model.put("msg", new I18NMessageMethod());
model.put("url", new BaseTemplateContentServlet.URLHelper(context));
model.put("locale", I18NUtil.getLocale());
model.put("task", new Workflow.WorkflowTaskItem(
Repository.getServiceRegistry(context),
this.imageResolver,
task));
return model;
}
/** Template Image resolver helper */
private TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size);
}
};
}
package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.I18NMessageMethod;
import org.alfresco.repo.template.Workflow;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* Bean used by an AJAX control to send information back on the requested workflow task.
*
* @author Kevin Roast
*/
public class TaskInfoBean implements Serializable
{
private static final long serialVersionUID = -6627537519541525897L;
transient private WorkflowService workflowService;
/**
* Returns information for the workflow task identified by the 'taskId'
* parameter found in the ExternalContext.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendTaskInfo() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
String taskId = (String)context.getExternalContext().getRequestParameterMap().get("taskId");
if (taskId == null || taskId.length() == 0)
{
throw new IllegalArgumentException("'taskId' parameter is missing");
}
WorkflowTask task = this.getWorkflowService().getTaskById(taskId);
if (task != null)
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/task_summary_panel.ftl", getModel(task), out);
}
else
{
out.write("<span class='errorMessage'>Task could not be found.</span>");
}
}
/**
* Returns the resource list for the workflow task identified by the 'taskId'
* parameter found in the ExternalContext.
* <p>
* The result is the formatted HTML to show on the client.
*/
public void sendTaskResources() throws IOException
{
FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter();
String taskId = (String)context.getExternalContext().getRequestParameterMap().get("taskId");
if (taskId == null || taskId.length() == 0)
{
throw new IllegalArgumentException("'taskId' parameter is missing");
}
WorkflowTask task = this.getWorkflowService().getTaskById(taskId);
if (task != null)
{
Repository.getServiceRegistry(context).getTemplateService().processTemplate(
"/alfresco/templates/client/task_resource_panel.ftl", getModel(task), out);
}
else
{
out.write("<span class='errorMessage'>Task could not be found.</span>");
}
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @param workflowService The WorkflowService to set.
*/
public void setWorkflowService(WorkflowService workflowService)
{
this.workflowService = workflowService;
}
private WorkflowService getWorkflowService()
{
if (workflowService == null)
{
workflowService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getWorkflowService();
}
return workflowService;
}
// ------------------------------------------------------------------------------
// Helper methods
private Map<String, Object> getModel(WorkflowTask task)
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
I18NUtil.registerResourceBundle("alfresco.messages.webclient");
// create template api methods and objects
model.put("date", new Date());
model.put("msg", new I18NMessageMethod());
model.put("url", new BaseTemplateContentServlet.URLHelper(context));
model.put("locale", I18NUtil.getLocale());
model.put("task", new Workflow.WorkflowTaskItem(
Repository.getServiceRegistry(context),
this.imageResolver,
task));
return model;
}
/** Template Image resolver helper */
private TemplateImageResolver imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return FileTypeImageUtils.getFileTypeImage(FacesContext.getCurrentInstance(), filename, size);
}
};
}

View File

@@ -1,166 +1,166 @@
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
public class CreateCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = 1905920932992642119L;
private static final String DEFAULT_OUTCOME = "finish";
transient protected CategoryService categoryService;
/** Current category ref */
private NodeRef categoryRef = null;
/** Dialog properties */
private String name = null;
private String description = null;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
// retrieve parameters
String ref = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
this.name = null;
this.description = null;
if (ref != null)
{
categoryRef = new NodeRef(ref);
}
else
{
categoryRef = null;
}
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishCreate();
return outcome;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "new_category");
}
public String finishCreate()
{
String outcome = DEFAULT_OUTCOME;
try
{
FacesContext context = FacesContext.getCurrentInstance();
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(context);
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
// create category using categoryservice
NodeRef ref;
if (getCategoryRef() == null || getCategoryRef().getId().equals("null"))
{
ref = getCategoryService().createRootCategory(Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, getName());
}
else
{
ref = getCategoryService().createCategory(getCategoryRef(), getName());
}
// apply the titled aspect - for description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
titledProps.put(ContentModel.PROP_DESCRIPTION, getDescription());
getNodeService().addAspect(ref, ContentModel.ASPECT_TITLED, titledProps);
return null;
}
};
txnHelper.doInTransaction(callback);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
return outcome;
}
}
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
public class CreateCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = 1905920932992642119L;
private static final String DEFAULT_OUTCOME = "finish";
transient protected CategoryService categoryService;
/** Current category ref */
private NodeRef categoryRef = null;
/** Dialog properties */
private String name = null;
private String description = null;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
// retrieve parameters
String ref = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
this.name = null;
this.description = null;
if (ref != null)
{
categoryRef = new NodeRef(ref);
}
else
{
categoryRef = null;
}
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishCreate();
return outcome;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "new_category");
}
public String finishCreate()
{
String outcome = DEFAULT_OUTCOME;
try
{
FacesContext context = FacesContext.getCurrentInstance();
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(context);
RetryingTransactionCallback<Object> callback = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
// create category using categoryservice
NodeRef ref;
if (getCategoryRef() == null || getCategoryRef().getId().equals("null"))
{
ref = getCategoryService().createRootCategory(Repository.getStoreRef(), ContentModel.ASPECT_GEN_CLASSIFIABLE, getName());
}
else
{
ref = getCategoryService().createCategory(getCategoryRef(), getName());
}
// apply the titled aspect - for description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
titledProps.put(ContentModel.PROP_DESCRIPTION, getDescription());
getNodeService().addAspect(ref, ContentModel.ASPECT_TITLED, titledProps);
return null;
}
};
txnHelper.doInTransaction(callback);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
return outcome;
}
}

View File

@@ -1,395 +1,395 @@
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.CategoryService.Depth;
import org.alfresco.service.cmr.search.CategoryService.Mode;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.categories.CategoriesDialog.CategoryBreadcrumbHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.ParameterCheck;
public class DeleteCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = -8929785826091612856L;
private static Log logger = LogFactory.getLog(DeleteCategoryDialog.class);
private static final String DEFAULT_OUTCOME = "finish";
private final static String MSG_DELETE_CATEGORY = "delete_category";
private final static String MSG_DELETE = "delete";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static final String MSG_CATEGORIES = "categories";
transient protected CategoryService categoryService;
/** Dialog properties */
private String name = null;
private String description = null;
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Current category ref */
private NodeRef categoryRef = null;
/** Action category node */
private Node actionCategory = null;
/** Component references */
protected UIRichList categoriesRichList;
/** Currently visible category Node */
private Node category = null;
private Boolean categoryFlag = false;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
this.categoryFlag = false;
// retrieve parameters
String categoryRef = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
// make sure nodeRef was supplied
ParameterCheck.mandatoryString(CategoriesDialog.PARAM_CATEGORY_REF, categoryRef);
// create the node
this.category = new Node(new NodeRef(categoryRef));
setActionCategory(category);
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// add the category to the request object so it gets picked up by
// category dialog, this will allow it to be removed from the breadcrumb
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY, this.category.getName());
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY_FLAG, this.categoryFlag.toString());
return outcome;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
public int getMembersSize()
{
return getMembers().size();
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public Boolean getCategoryFlag()
{
return categoryFlag;
}
public void setCategoryFlag(Boolean categoryFlag)
{
this.categoryFlag = categoryFlag;
}
/**
* @param node Set the Node to be used for the current category screen action.
*/
@SuppressWarnings("unchecked")
public void setActionCategory(Node node)
{
this.actionCategory = node;
if (node != null)
{
// setup form properties
setName(node.getName());
setDescription((String)node.getProperties().get(ContentModel.PROP_DESCRIPTION));
setMembers(getCategoryService().getChildren(node.getNodeRef(), Mode.MEMBERS, Depth.ANY));
}
else
{
setName(null);
setDescription(null);
Object emptyCollection = Collections.emptyList();
setMembers((Collection<ChildAssociationRef>) emptyCollection);
}
}
public Node getActionCategory()
{
return actionCategory;
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
/**
* @return Breadcrumb location list
*/
public List<IBreadcrumbHandler> getLocation()
{
return this.location;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishDelete();
return outcome;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_DELETE_CATEGORY) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ getActionCategory().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_DELETE);
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
/**
* @see org.alfresco.web.app.context.IContextListener#contextUpdated()
*/
public void contextUpdated()
{
if (logger.isDebugEnabled())
logger.debug("Invalidating Category Management Components...");
// force a requery of the current category ref properties
setCategory(null);
// force a requery of the richlist dataset
if (this.categoriesRichList != null)
{
this.categoriesRichList.setValue(null);
}
}
/**
* @return The ID of the currently displayed category or null if at the root.
*/
public String getCurrentCategoryId()
{
if (getCategoryRef() != null)
{
return getCategoryRef().getId();
}
else
{
return null;
}
}
/**
* Set the current category node.
* <p>
* Setting this value causes the UI to update and display the specified node as current.
*
* @param ref The current category node.
*/
public void setCurrentCategory(NodeRef ref)
{
if (logger.isDebugEnabled())
logger.debug("Setting current category: " + ref);
// set the current NodeRef for our UI context operations
setCategoryRef(ref);
// clear current node context
setCategory(null);
// inform that the UI needs updating after this change
contextUpdated();
}
public String finishDelete()
{
String outcome = DEFAULT_OUTCOME;
if (getActionCategory() != null)
{
try
{
FacesContext context = FacesContext.getCurrentInstance();
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(context);
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
{
@SuppressWarnings("unchecked")
public NodeRef execute() throws Throwable
{
// delete the category node using the nodeservice
NodeRef categoryNodeRef = getActionCategory().getNodeRef();
getCategoryService().deleteCategory(categoryNodeRef);
// if there are other items in the repository using this category
// all the associations to the category should be removed too
if (getMembers() != null && getMembers().size() > 0)
{
for (ChildAssociationRef childRef : getMembers())
{
List<NodeRef> list = new ArrayList<NodeRef>(getMembers().size());
NodeRef member = childRef.getChildRef();
Collection<NodeRef> categories = (Collection<NodeRef>)getNodeService().getProperty(member, ContentModel.PROP_CATEGORIES);
for (NodeRef category : categories)
{
if (category.equals(categoryNodeRef) == false)
{
list.add(category);
}
}
// persist the list back to the repository
getNodeService().setProperty(member, ContentModel.PROP_CATEGORIES, (Serializable) list);
}
}
return categoryNodeRef;
}
};
NodeRef categoryNodeRef = txnHelper.doInTransaction(callback);
// Figure out if the deletion is made by an icon or by a list of actions
CategoriesDialog categoriesDialog = (CategoriesDialog) UIContextService.getInstance(FacesContext.getCurrentInstance())
.getRegisteredBean(CategoriesDialog.CATEGORIES_DIALOG_CLASS_NAME);
setLocation(categoriesDialog.getLocation());
List<IBreadcrumbHandler> location = getLocation();
CategoryBreadcrumbHandler handler = (CategoryBreadcrumbHandler) location.get(location.size() - 1);
setCategoryFlag(!handler.toString().equals(getCategory().getName()));
// clear action context
setActionCategory(null);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
}
return outcome;
}
}
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.CategoryService.Depth;
import org.alfresco.service.cmr.search.CategoryService.Mode;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.categories.CategoriesDialog.CategoryBreadcrumbHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.ParameterCheck;
public class DeleteCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = -8929785826091612856L;
private static Log logger = LogFactory.getLog(DeleteCategoryDialog.class);
private static final String DEFAULT_OUTCOME = "finish";
private final static String MSG_DELETE_CATEGORY = "delete_category";
private final static String MSG_DELETE = "delete";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static final String MSG_CATEGORIES = "categories";
transient protected CategoryService categoryService;
/** Dialog properties */
private String name = null;
private String description = null;
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Current category ref */
private NodeRef categoryRef = null;
/** Action category node */
private Node actionCategory = null;
/** Component references */
protected UIRichList categoriesRichList;
/** Currently visible category Node */
private Node category = null;
private Boolean categoryFlag = false;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
this.categoryFlag = false;
// retrieve parameters
String categoryRef = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
// make sure nodeRef was supplied
ParameterCheck.mandatoryString(CategoriesDialog.PARAM_CATEGORY_REF, categoryRef);
// create the node
this.category = new Node(new NodeRef(categoryRef));
setActionCategory(category);
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// add the category to the request object so it gets picked up by
// category dialog, this will allow it to be removed from the breadcrumb
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY, this.category.getName());
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY_FLAG, this.categoryFlag.toString());
return outcome;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
public int getMembersSize()
{
return getMembers().size();
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public NodeRef getCategoryRef()
{
return categoryRef;
}
public void setCategoryRef(NodeRef categoryRef)
{
this.categoryRef = categoryRef;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public Boolean getCategoryFlag()
{
return categoryFlag;
}
public void setCategoryFlag(Boolean categoryFlag)
{
this.categoryFlag = categoryFlag;
}
/**
* @param node Set the Node to be used for the current category screen action.
*/
@SuppressWarnings("unchecked")
public void setActionCategory(Node node)
{
this.actionCategory = node;
if (node != null)
{
// setup form properties
setName(node.getName());
setDescription((String)node.getProperties().get(ContentModel.PROP_DESCRIPTION));
setMembers(getCategoryService().getChildren(node.getNodeRef(), Mode.MEMBERS, Depth.ANY));
}
else
{
setName(null);
setDescription(null);
Object emptyCollection = Collections.emptyList();
setMembers((Collection<ChildAssociationRef>) emptyCollection);
}
}
public Node getActionCategory()
{
return actionCategory;
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
/**
* @return Breadcrumb location list
*/
public List<IBreadcrumbHandler> getLocation()
{
return this.location;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishDelete();
return outcome;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_DELETE_CATEGORY) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ getActionCategory().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_DELETE);
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
/**
* @see org.alfresco.web.app.context.IContextListener#contextUpdated()
*/
public void contextUpdated()
{
if (logger.isDebugEnabled())
logger.debug("Invalidating Category Management Components...");
// force a requery of the current category ref properties
setCategory(null);
// force a requery of the richlist dataset
if (this.categoriesRichList != null)
{
this.categoriesRichList.setValue(null);
}
}
/**
* @return The ID of the currently displayed category or null if at the root.
*/
public String getCurrentCategoryId()
{
if (getCategoryRef() != null)
{
return getCategoryRef().getId();
}
else
{
return null;
}
}
/**
* Set the current category node.
* <p>
* Setting this value causes the UI to update and display the specified node as current.
*
* @param ref The current category node.
*/
public void setCurrentCategory(NodeRef ref)
{
if (logger.isDebugEnabled())
logger.debug("Setting current category: " + ref);
// set the current NodeRef for our UI context operations
setCategoryRef(ref);
// clear current node context
setCategory(null);
// inform that the UI needs updating after this change
contextUpdated();
}
public String finishDelete()
{
String outcome = DEFAULT_OUTCOME;
if (getActionCategory() != null)
{
try
{
FacesContext context = FacesContext.getCurrentInstance();
RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(context);
RetryingTransactionCallback<NodeRef> callback = new RetryingTransactionCallback<NodeRef>()
{
@SuppressWarnings("unchecked")
public NodeRef execute() throws Throwable
{
// delete the category node using the nodeservice
NodeRef categoryNodeRef = getActionCategory().getNodeRef();
getCategoryService().deleteCategory(categoryNodeRef);
// if there are other items in the repository using this category
// all the associations to the category should be removed too
if (getMembers() != null && getMembers().size() > 0)
{
for (ChildAssociationRef childRef : getMembers())
{
List<NodeRef> list = new ArrayList<NodeRef>(getMembers().size());
NodeRef member = childRef.getChildRef();
Collection<NodeRef> categories = (Collection<NodeRef>)getNodeService().getProperty(member, ContentModel.PROP_CATEGORIES);
for (NodeRef category : categories)
{
if (category.equals(categoryNodeRef) == false)
{
list.add(category);
}
}
// persist the list back to the repository
getNodeService().setProperty(member, ContentModel.PROP_CATEGORIES, (Serializable) list);
}
}
return categoryNodeRef;
}
};
NodeRef categoryNodeRef = txnHelper.doInTransaction(callback);
// Figure out if the deletion is made by an icon or by a list of actions
CategoriesDialog categoriesDialog = (CategoriesDialog) UIContextService.getInstance(FacesContext.getCurrentInstance())
.getRegisteredBean(CategoriesDialog.CATEGORIES_DIALOG_CLASS_NAME);
setLocation(categoriesDialog.getLocation());
List<IBreadcrumbHandler> location = getLocation();
CategoryBreadcrumbHandler handler = (CategoryBreadcrumbHandler) location.get(location.size() - 1);
setCategoryFlag(!handler.toString().equals(getCategory().getName()));
// clear action context
setActionCategory(null);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
}
return outcome;
}
}

View File

@@ -1,307 +1,307 @@
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.CategoryService.Depth;
import org.alfresco.service.cmr.search.CategoryService.Mode;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.categories.CategoriesDialog.CategoryBreadcrumbHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.alfresco.web.ui.repo.component.IRepoBreadcrumbHandler;
public class EditCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = 3316665625854694278L;
private static final String DEFAULT_OUTCOME = "finish";
private final static String MSG_EDIT_CATEGORY = "edit_category";
private final static String MSG_FINISH = "finish_button";
private static final String MSG_CATEGORIES = "categories";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
transient protected CategoryService categoryService;
/** Action category node */
private Node actionCategory = null;
/** Currently visible category Node */
private Node category = null;
private Boolean categoryFlag = false;
String categoryRef = null;
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Component references */
protected UIRichList categoriesRichList;
/** Dialog properties */
private String name = null;
private String description = null;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
this.categoryFlag = false;
// retrieve parameters
categoryRef = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
// make sure nodeRef was supplied
ParameterCheck.mandatoryString(CategoriesDialog.PARAM_CATEGORY_REF, categoryRef);
// create the node
this.category = new Node(new NodeRef(categoryRef));
setActionCategory(category);
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// add the category to the request object so it gets picked up by
// category dialog, this will allow it to be edited in the breadcrumb
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY, this.category.getName());
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY_FLAG, this.categoryFlag.toString());
return outcome;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public Boolean getCategoryFlag()
{
return categoryFlag;
}
public void setCategoryFlag(Boolean categoryFlag)
{
this.categoryFlag = categoryFlag;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
@SuppressWarnings("unchecked")
public void setActionCategory(Node node)
{
this.actionCategory = node;
if (node != null)
{
// setup form properties
setName(node.getName());
setDescription((String) node.getProperties().get(ContentModel.PROP_DESCRIPTION));
setMembers(getCategoryService().getChildren(node.getNodeRef(), Mode.MEMBERS, Depth.ANY));
}
else
{
setName(null);
setDescription(null);
Object emptyCollection = Collections.emptyList();
setMembers((Collection<ChildAssociationRef>) emptyCollection);
}
}
public Node getActionCategory()
{
return actionCategory;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishEdit();
return outcome;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_EDIT_CATEGORY) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ getActionCategory().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_FINISH);
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
/**
* @return Breadcrumb location list
*/
public List<IBreadcrumbHandler> getLocation()
{
return this.location;
}
public String finishEdit()
{
String outcome = DEFAULT_OUTCOME;
try
{
// update the category node
NodeRef nodeRef = getActionCategory().getNodeRef();
getNodeService().setProperty(nodeRef, ContentModel.PROP_NAME, getName());
// ALF-1788 Need to rename the association
ChildAssociationRef assocRef = getNodeService().getPrimaryParent(nodeRef);
QName qname = QName.createQName(
assocRef.getQName().getNamespaceURI(),
QName.createValidLocalName(name));
getNodeService().moveNode(
assocRef.getChildRef(),
assocRef.getParentRef(),
assocRef.getTypeQName(),
qname);
// apply the titled aspect - for description
if (getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false)
{
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
titledProps.put(ContentModel.PROP_DESCRIPTION, getDescription());
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, titledProps);
}
else
{
getNodeService().setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, getDescription());
}
//Figure out if the editing is made by an icon or by a list of actions
CategoriesDialog categoriesDialog = (CategoriesDialog) UIContextService.getInstance(FacesContext.getCurrentInstance())
.getRegisteredBean(CategoriesDialog.CATEGORIES_DIALOG_CLASS_NAME);
setLocation(categoriesDialog.getLocation());
List<IBreadcrumbHandler> location = getLocation();
CategoryBreadcrumbHandler handler = (CategoryBreadcrumbHandler) location.get(location.size() - 1);
if (!handler.toString().equals(getCategory().getName()))
{
setCategoryFlag(true);
}
else
{
setCategoryFlag(false);
}
Node categoryNode = new Node(nodeRef);
setCategory(categoryNode);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
return outcome;
}
}
package org.alfresco.web.bean.categories;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.CategoryService.Depth;
import org.alfresco.service.cmr.search.CategoryService.Mode;
import org.alfresco.service.namespace.QName;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.categories.CategoriesDialog.CategoryBreadcrumbHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
import org.alfresco.web.ui.common.component.data.UIRichList;
import org.alfresco.web.ui.repo.component.IRepoBreadcrumbHandler;
public class EditCategoryDialog extends BaseDialogBean
{
private static final long serialVersionUID = 3316665625854694278L;
private static final String DEFAULT_OUTCOME = "finish";
private final static String MSG_EDIT_CATEGORY = "edit_category";
private final static String MSG_FINISH = "finish_button";
private static final String MSG_CATEGORIES = "categories";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
transient protected CategoryService categoryService;
/** Action category node */
private Node actionCategory = null;
/** Currently visible category Node */
private Node category = null;
private Boolean categoryFlag = false;
String categoryRef = null;
/** Category path breadcrumb location */
private List<IBreadcrumbHandler> location = null;
/** Members of the linked items of a category */
private Collection<ChildAssociationRef> members = null;
/** Component references */
protected UIRichList categoriesRichList;
/** Dialog properties */
private String name = null;
private String description = null;
@Override
public void init(Map<String, String> parameters)
{
this.isFinished = false;
this.categoryFlag = false;
// retrieve parameters
categoryRef = parameters.get(CategoriesDialog.PARAM_CATEGORY_REF);
// make sure nodeRef was supplied
ParameterCheck.mandatoryString(CategoriesDialog.PARAM_CATEGORY_REF, categoryRef);
// create the node
this.category = new Node(new NodeRef(categoryRef));
setActionCategory(category);
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// add the category to the request object so it gets picked up by
// category dialog, this will allow it to be edited in the breadcrumb
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY, this.category.getName());
context.getExternalContext().getRequestMap().put(
CategoriesDialog.KEY_CATEGORY_FLAG, this.categoryFlag.toString());
return outcome;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public UIRichList getCategoriesRichList()
{
return categoriesRichList;
}
public void setCategoriesRichList(UIRichList categoriesRichList)
{
this.categoriesRichList = categoriesRichList;
}
/**
* @return the categoryService
*/
private CategoryService getCategoryService()
{
//check for null in cluster environment
if(categoryService == null)
{
categoryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCategoryService();
}
return categoryService;
}
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
public Node getCategory()
{
return category;
}
public void setCategory(Node category)
{
this.category = category;
}
public Boolean getCategoryFlag()
{
return categoryFlag;
}
public void setCategoryFlag(Boolean categoryFlag)
{
this.categoryFlag = categoryFlag;
}
public Collection<ChildAssociationRef> getMembers()
{
return members;
}
public void setMembers(Collection<ChildAssociationRef> members)
{
this.members = members;
}
@SuppressWarnings("unchecked")
public void setActionCategory(Node node)
{
this.actionCategory = node;
if (node != null)
{
// setup form properties
setName(node.getName());
setDescription((String) node.getProperties().get(ContentModel.PROP_DESCRIPTION));
setMembers(getCategoryService().getChildren(node.getNodeRef(), Mode.MEMBERS, Depth.ANY));
}
else
{
setName(null);
setDescription(null);
Object emptyCollection = Collections.emptyList();
setMembers((Collection<ChildAssociationRef>) emptyCollection);
}
}
public Node getActionCategory()
{
return actionCategory;
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
finishEdit();
return outcome;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_EDIT_CATEGORY) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ getActionCategory().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_FINISH);
}
public void setLocation(List<IBreadcrumbHandler> location)
{
this.location = location;
}
/**
* @return Breadcrumb location list
*/
public List<IBreadcrumbHandler> getLocation()
{
return this.location;
}
public String finishEdit()
{
String outcome = DEFAULT_OUTCOME;
try
{
// update the category node
NodeRef nodeRef = getActionCategory().getNodeRef();
getNodeService().setProperty(nodeRef, ContentModel.PROP_NAME, getName());
// ALF-1788 Need to rename the association
ChildAssociationRef assocRef = getNodeService().getPrimaryParent(nodeRef);
QName qname = QName.createQName(
assocRef.getQName().getNamespaceURI(),
QName.createValidLocalName(name));
getNodeService().moveNode(
assocRef.getChildRef(),
assocRef.getParentRef(),
assocRef.getTypeQName(),
qname);
// apply the titled aspect - for description
if (getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false)
{
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(1, 1.0f);
titledProps.put(ContentModel.PROP_DESCRIPTION, getDescription());
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, titledProps);
}
else
{
getNodeService().setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, getDescription());
}
//Figure out if the editing is made by an icon or by a list of actions
CategoriesDialog categoriesDialog = (CategoriesDialog) UIContextService.getInstance(FacesContext.getCurrentInstance())
.getRegisteredBean(CategoriesDialog.CATEGORIES_DIALOG_CLASS_NAME);
setLocation(categoriesDialog.getLocation());
List<IBreadcrumbHandler> location = getLocation();
CategoryBreadcrumbHandler handler = (CategoryBreadcrumbHandler) location.get(location.size() - 1);
if (!handler.toString().equals(getCategory().getName()))
{
setCategoryFlag(true);
}
else
{
setCategoryFlag(false);
}
Node categoryNode = new Node(nodeRef);
setCategory(categoryNode);
}
catch (Throwable err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
outcome = null;
ReportedException.throwIfNecessary(err);
}
return outcome;
}
}

View File

@@ -1,193 +1,193 @@
package org.alfresco.web.bean.clipboard;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class representing a single item added to the clipboard.
*
* @author Kevin Roast
*/
abstract class AbstractClipboardItem implements ClipboardItem
{
protected static Log logger = LogFactory.getLog(ClipboardBean.class);
protected static final String MSG_COPY_OF = "copy_of";
/** Shallow search for nodes with a name pattern */
private static final String XPATH_QUERY_NODE_MATCH = "./*[like(@cm:name, $cm:name, false)]";
transient private ServiceRegistry services = null;
protected NodeRef ref;
protected NodeRef parent;
protected ClipboardStatus mode;
// cached values
private String name;
private QName type;
private String icon;
private List<String> customPasteViewIds;
/**
* Constructor
*
* @param ref The ref of the item on the clipboard
* @param mode The ClipboardStatus enum value
*/
public AbstractClipboardItem(NodeRef ref, ClipboardStatus mode, List<String> customPasteViewIds)
{
this.ref = ref;
this.mode = mode;
this.customPasteViewIds = customPasteViewIds;
}
/**
* Constructor
*
* @param ref The ref of the item on the clipboard
* @param parent The parent of the item on the clipboard
* @param mode The ClipboardStatus enum value
*/
public AbstractClipboardItem(NodeRef ref, NodeRef parent, ClipboardStatus mode, List<String> customPasteViewIds)
{
this.ref = ref;
this.mode = mode;
this.parent = parent;
this.customPasteViewIds = customPasteViewIds;
}
public ClipboardStatus getMode()
{
return this.mode;
}
public String getName()
{
if (this.name == null)
{
this.name = (String)getServiceRegistry().getNodeService().getProperty(
this.ref, ContentModel.PROP_NAME);
}
return this.name;
}
public QName getType()
{
if (this.type == null)
{
this.type = getServiceRegistry().getNodeService().getType(this.ref);
}
return this.type;
}
public String getIcon()
{
if (this.icon == null)
{
this.icon = (String)getServiceRegistry().getNodeService().getProperty(
this.ref, ApplicationModel.PROP_ICON);
}
return this.icon;
}
public NodeRef getNodeRef()
{
return this.ref;
}
public NodeRef getParent()
{
return this.parent;
}
/**
* Override equals() to compare NodeRefs
*/
public boolean equals(Object obj)
{
if (obj == this)
{
return true;
}
if (obj instanceof ClipboardItem)
{
return ((ClipboardItem)obj).getNodeRef().equals(this.ref);
}
else
{
return false;
}
}
/**
* Override hashCode() to use the internal NodeRef hashcode instead
*/
public int hashCode()
{
return ref.hashCode();
}
protected ServiceRegistry getServiceRegistry()
{
if (services == null)
{
services = Repository.getServiceRegistry(FacesContext.getCurrentInstance());
}
return services;
}
public boolean canCopyToViewId(String viewId)
{
if (this.customPasteViewIds != null)
{
return this.customPasteViewIds.contains(viewId);
}
return false;
}
public boolean canMoveToViewId(String viewId)
{
if (this.customPasteViewIds != null)
{
return this.customPasteViewIds.contains(viewId);
}
return false;
}
protected boolean checkExists(String name, NodeRef parent)
{
QueryParameterDefinition[] params = new QueryParameterDefinition[1];
params[0] = new QueryParameterDefImpl(
ContentModel.PROP_NAME,
getServiceRegistry().getDictionaryService().getDataType(
DataTypeDefinition.TEXT),
true,
name);
// execute the query
List<NodeRef> nodeRefs = getServiceRegistry().getSearchService().selectNodes(
parent,
XPATH_QUERY_NODE_MATCH,
params,
getServiceRegistry().getNamespaceService(),
false);
return (nodeRefs.size() != 0);
}
}
package org.alfresco.web.bean.clipboard;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.QueryParameterDefImpl;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.search.QueryParameterDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base class representing a single item added to the clipboard.
*
* @author Kevin Roast
*/
abstract class AbstractClipboardItem implements ClipboardItem
{
protected static Log logger = LogFactory.getLog(ClipboardBean.class);
protected static final String MSG_COPY_OF = "copy_of";
/** Shallow search for nodes with a name pattern */
private static final String XPATH_QUERY_NODE_MATCH = "./*[like(@cm:name, $cm:name, false)]";
transient private ServiceRegistry services = null;
protected NodeRef ref;
protected NodeRef parent;
protected ClipboardStatus mode;
// cached values
private String name;
private QName type;
private String icon;
private List<String> customPasteViewIds;
/**
* Constructor
*
* @param ref The ref of the item on the clipboard
* @param mode The ClipboardStatus enum value
*/
public AbstractClipboardItem(NodeRef ref, ClipboardStatus mode, List<String> customPasteViewIds)
{
this.ref = ref;
this.mode = mode;
this.customPasteViewIds = customPasteViewIds;
}
/**
* Constructor
*
* @param ref The ref of the item on the clipboard
* @param parent The parent of the item on the clipboard
* @param mode The ClipboardStatus enum value
*/
public AbstractClipboardItem(NodeRef ref, NodeRef parent, ClipboardStatus mode, List<String> customPasteViewIds)
{
this.ref = ref;
this.mode = mode;
this.parent = parent;
this.customPasteViewIds = customPasteViewIds;
}
public ClipboardStatus getMode()
{
return this.mode;
}
public String getName()
{
if (this.name == null)
{
this.name = (String)getServiceRegistry().getNodeService().getProperty(
this.ref, ContentModel.PROP_NAME);
}
return this.name;
}
public QName getType()
{
if (this.type == null)
{
this.type = getServiceRegistry().getNodeService().getType(this.ref);
}
return this.type;
}
public String getIcon()
{
if (this.icon == null)
{
this.icon = (String)getServiceRegistry().getNodeService().getProperty(
this.ref, ApplicationModel.PROP_ICON);
}
return this.icon;
}
public NodeRef getNodeRef()
{
return this.ref;
}
public NodeRef getParent()
{
return this.parent;
}
/**
* Override equals() to compare NodeRefs
*/
public boolean equals(Object obj)
{
if (obj == this)
{
return true;
}
if (obj instanceof ClipboardItem)
{
return ((ClipboardItem)obj).getNodeRef().equals(this.ref);
}
else
{
return false;
}
}
/**
* Override hashCode() to use the internal NodeRef hashcode instead
*/
public int hashCode()
{
return ref.hashCode();
}
protected ServiceRegistry getServiceRegistry()
{
if (services == null)
{
services = Repository.getServiceRegistry(FacesContext.getCurrentInstance());
}
return services;
}
public boolean canCopyToViewId(String viewId)
{
if (this.customPasteViewIds != null)
{
return this.customPasteViewIds.contains(viewId);
}
return false;
}
public boolean canMoveToViewId(String viewId)
{
if (this.customPasteViewIds != null)
{
return this.customPasteViewIds.contains(viewId);
}
return false;
}
protected boolean checkExists(String name, NodeRef parent)
{
QueryParameterDefinition[] params = new QueryParameterDefinition[1];
params[0] = new QueryParameterDefImpl(
ContentModel.PROP_NAME,
getServiceRegistry().getDictionaryService().getDataType(
DataTypeDefinition.TEXT),
true,
name);
// execute the query
List<NodeRef> nodeRefs = getServiceRegistry().getSearchService().selectNodes(
parent,
XPATH_QUERY_NODE_MATCH,
params,
getServiceRegistry().getNamespaceService(),
false);
return (nodeRefs.size() != 0);
}
}

View File

@@ -1,319 +1,319 @@
package org.alfresco.web.bean.clipboard;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem;
/**
* Class representing a 'workspace' store protocol clipboard item
*
* @author Kevin Roast
*/
public class WorkspaceClipboardItem extends AbstractClipboardItem
{
private static final long serialVersionUID = -1686557602737846009L;
private static final String WORKSPACE_PASTE_VIEW_ID = "/jsp/browse/browse.jsp";
private static final String FORUMS_PASTE_VIEW_ID = "/jsp/forums/forums.jsp";
private static final String FORUM_PASTE_VIEW_ID = "/jsp/forums/forum.jsp";
private static final String MSG_LINK_TO = "link_to";
// File extension to use for link nodes
private static final String LINK_NODE_EXTENSION = ".url";
/**
* @param ref
* @param mode
*/
public WorkspaceClipboardItem(NodeRef ref, ClipboardStatus mode, List<String> customPasteViewIds)
{
super(ref, mode, customPasteViewIds);
}
/**
* @param ref
* @param mode
*/
public WorkspaceClipboardItem(NodeRef ref, NodeRef parent, ClipboardStatus mode, List<String> customPasteViewIds)
{
super(ref, parent, mode, customPasteViewIds);
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#supportsLink()
*/
public boolean supportsLink()
{
return true;
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#canCopyToViewId(java.lang.String)
*/
public boolean canCopyToViewId(String viewId)
{
return super.canCopyToViewId(viewId) || (WORKSPACE_PASTE_VIEW_ID.equals(viewId) ||
FORUMS_PASTE_VIEW_ID.equals(viewId) || FORUM_PASTE_VIEW_ID.equals(viewId));
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#canMoveToViewId(java.lang.String)
*/
public boolean canMoveToViewId(String viewId)
{
return super.canMoveToViewId(viewId) || (WORKSPACE_PASTE_VIEW_ID.equals(viewId) || FORUMS_PASTE_VIEW_ID.equals(viewId) ||
FORUM_PASTE_VIEW_ID.equals(viewId));
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#paste(javax.faces.context.FacesContext, java.lang.String, int)
*/
public boolean paste(final FacesContext fc, String viewId, final int action)
{
final ServiceRegistry serviceRegistry = getServiceRegistry();
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
if (super.canCopyToViewId(viewId) || WORKSPACE_PASTE_VIEW_ID.equals(viewId) || FORUMS_PASTE_VIEW_ID.equals(viewId) ||
FORUM_PASTE_VIEW_ID.equals(viewId))
{
NavigationBean navigator = (NavigationBean)FacesHelper.getManagedBean(fc, NavigationBean.BEAN_NAME);
final NodeRef destRef = new NodeRef(Repository.getStoreRef(), navigator.getCurrentNodeId());
final DictionaryService dd = serviceRegistry.getDictionaryService();
final NodeService nodeService = serviceRegistry.getNodeService();
final FileFolderService fileFolderService = serviceRegistry.getFileFolderService();
final CopyService copyService = serviceRegistry.getCopyService();
final MultilingualContentService multilingualContentService = serviceRegistry.getMultilingualContentService();
final boolean isPrimaryParent;
final ChildAssociationRef assocRef;
if (getParent() == null)
{
assocRef = nodeService.getPrimaryParent(getNodeRef());
isPrimaryParent = true;
}
else
{
NodeRef parentNodeRef = getParent();
List<ChildAssociationRef> assocList = nodeService.getParentAssocs(getNodeRef());
ChildAssociationRef foundRef = null;
if (assocList != null)
{
for (ChildAssociationRef assocListEntry : assocList)
{
if (parentNodeRef.equals(assocListEntry.getParentRef()))
{
foundRef = assocListEntry;
break;
}
}
}
assocRef = foundRef;
isPrimaryParent = parentNodeRef.equals(nodeService.getPrimaryParent(getNodeRef()).getParentRef());
}
// initial name to attempt the copy of the item with
String name = getName();
String translationPrefix = "";
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
{
// copy as link was specifically requested by the user
String linkTo = Application.getMessage(fc, MSG_LINK_TO);
name = linkTo + ' ' + name;
}
// Loop until we find a target name that doesn't exist
for(;;)
{
try
{
final String currentTranslationPrefix = translationPrefix;
final String currentName = name;
// attempt each copy/paste in its own transaction
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
if (getMode() == ClipboardStatus.COPY)
{
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
{
// LINK operation
if (logger.isDebugEnabled())
logger.debug("Attempting to link node ID: " + getNodeRef() + " into node: " + destRef.toString());
// we create a special Link Object node that has a property to reference the original
// create the node using the nodeService (can only use FileFolderService for content)
if (checkExists(currentName + LINK_NODE_EXTENSION, destRef) == false)
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2, 1.0f);
String newName = currentName + LINK_NODE_EXTENSION;
props.put(ContentModel.PROP_NAME, newName);
props.put(ContentModel.PROP_LINK_DESTINATION, getNodeRef());
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT))
{
// create File Link node
ChildAssociationRef childRef = nodeService.createNode(
destRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(assocRef.getQName().getNamespaceURI(), newName),
ApplicationModel.TYPE_FILELINK,
props);
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(2, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, currentName);
titledProps.put(ContentModel.PROP_DESCRIPTION, currentName);
nodeService.addAspect(childRef.getChildRef(), ContentModel.ASPECT_TITLED, titledProps);
}
else
{
// create Folder link node
ChildAssociationRef childRef = nodeService.createNode(
destRef,
ContentModel.ASSOC_CONTAINS,
assocRef.getQName(),
ApplicationModel.TYPE_FOLDERLINK,
props);
// apply the uifacets aspect - icon, title and description props
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4, 1.0f);
uiFacetsProps.put(ApplicationModel.PROP_ICON, "space-icon-link");
uiFacetsProps.put(ContentModel.PROP_TITLE, currentName);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, currentName);
nodeService.addAspect(childRef.getChildRef(), ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
}
}
}
else
{
// COPY operation
if (logger.isDebugEnabled())
logger.debug("Attempting to copy node: " + getNodeRef() + " into node ID: " + destRef.toString());
// first check that we are not attempting to copy a duplicate into the same parent
if (destRef.equals(assocRef.getParentRef()) && currentName.equals(getName()))
{
// manually change the name if this occurs
throw new FileExistsException(destRef, currentName);
}
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
// copy the file/folder
fileFolderService.copy(
getNodeRef(),
destRef,
currentName);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.copyTranslationContainer(getNodeRef(), destRef, currentTranslationPrefix);
}
else
{
// copy the node
if (checkExists(currentName, destRef) == false)
{
copyService.copyAndRename(
getNodeRef(),
destRef,
ContentModel.ASSOC_CONTAINS,
assocRef.getQName(),
true);
}
}
}
}
else
{
// MOVE operation
if (logger.isDebugEnabled())
logger.debug("Attempting to move node: " + getNodeRef() + " into node ID: " + destRef.toString());
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
// move the file/folder
fileFolderService.moveFrom(getNodeRef(), getParent(), destRef, currentName);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.moveTranslationContainer(getNodeRef(), destRef);
}
else
{
if (isPrimaryParent)
{
// move the node
nodeService.moveNode(getNodeRef(), destRef, ContentModel.ASSOC_CONTAINS, assocRef.getQName());
}
else
{
nodeService.removeChild(getParent(), getNodeRef());
nodeService.addChild(destRef, getNodeRef(), assocRef.getTypeQName(), assocRef.getQName());
}
}
}
return null;
}
});
// We got here without error, so no need to loop with a new name
break;
}
catch (FileExistsException fileExistsErr)
{
// If mode is COPY, have another go around the loop with a new name
if (getMode() == ClipboardStatus.COPY)
{
String copyOf = Application.getMessage(fc, MSG_COPY_OF);
name = copyOf + ' ' + name;
translationPrefix = copyOf + ' ' + translationPrefix;
}
else
{
// we should not rename an item when it is being moved - so exit
throw fileExistsErr;
}
}
}
return true;
}
else
{
return false;
}
}
}
package org.alfresco.web.bean.clipboard;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.FacesHelper;
import org.alfresco.web.bean.NavigationBean;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem;
/**
* Class representing a 'workspace' store protocol clipboard item
*
* @author Kevin Roast
*/
public class WorkspaceClipboardItem extends AbstractClipboardItem
{
private static final long serialVersionUID = -1686557602737846009L;
private static final String WORKSPACE_PASTE_VIEW_ID = "/jsp/browse/browse.jsp";
private static final String FORUMS_PASTE_VIEW_ID = "/jsp/forums/forums.jsp";
private static final String FORUM_PASTE_VIEW_ID = "/jsp/forums/forum.jsp";
private static final String MSG_LINK_TO = "link_to";
// File extension to use for link nodes
private static final String LINK_NODE_EXTENSION = ".url";
/**
* @param ref
* @param mode
*/
public WorkspaceClipboardItem(NodeRef ref, ClipboardStatus mode, List<String> customPasteViewIds)
{
super(ref, mode, customPasteViewIds);
}
/**
* @param ref
* @param mode
*/
public WorkspaceClipboardItem(NodeRef ref, NodeRef parent, ClipboardStatus mode, List<String> customPasteViewIds)
{
super(ref, parent, mode, customPasteViewIds);
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#supportsLink()
*/
public boolean supportsLink()
{
return true;
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#canCopyToViewId(java.lang.String)
*/
public boolean canCopyToViewId(String viewId)
{
return super.canCopyToViewId(viewId) || (WORKSPACE_PASTE_VIEW_ID.equals(viewId) ||
FORUMS_PASTE_VIEW_ID.equals(viewId) || FORUM_PASTE_VIEW_ID.equals(viewId));
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#canMoveToViewId(java.lang.String)
*/
public boolean canMoveToViewId(String viewId)
{
return super.canMoveToViewId(viewId) || (WORKSPACE_PASTE_VIEW_ID.equals(viewId) || FORUMS_PASTE_VIEW_ID.equals(viewId) ||
FORUM_PASTE_VIEW_ID.equals(viewId));
}
/**
* @see org.alfresco.web.bean.clipboard.ClipboardItem#paste(javax.faces.context.FacesContext, java.lang.String, int)
*/
public boolean paste(final FacesContext fc, String viewId, final int action)
{
final ServiceRegistry serviceRegistry = getServiceRegistry();
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
if (super.canCopyToViewId(viewId) || WORKSPACE_PASTE_VIEW_ID.equals(viewId) || FORUMS_PASTE_VIEW_ID.equals(viewId) ||
FORUM_PASTE_VIEW_ID.equals(viewId))
{
NavigationBean navigator = (NavigationBean)FacesHelper.getManagedBean(fc, NavigationBean.BEAN_NAME);
final NodeRef destRef = new NodeRef(Repository.getStoreRef(), navigator.getCurrentNodeId());
final DictionaryService dd = serviceRegistry.getDictionaryService();
final NodeService nodeService = serviceRegistry.getNodeService();
final FileFolderService fileFolderService = serviceRegistry.getFileFolderService();
final CopyService copyService = serviceRegistry.getCopyService();
final MultilingualContentService multilingualContentService = serviceRegistry.getMultilingualContentService();
final boolean isPrimaryParent;
final ChildAssociationRef assocRef;
if (getParent() == null)
{
assocRef = nodeService.getPrimaryParent(getNodeRef());
isPrimaryParent = true;
}
else
{
NodeRef parentNodeRef = getParent();
List<ChildAssociationRef> assocList = nodeService.getParentAssocs(getNodeRef());
ChildAssociationRef foundRef = null;
if (assocList != null)
{
for (ChildAssociationRef assocListEntry : assocList)
{
if (parentNodeRef.equals(assocListEntry.getParentRef()))
{
foundRef = assocListEntry;
break;
}
}
}
assocRef = foundRef;
isPrimaryParent = parentNodeRef.equals(nodeService.getPrimaryParent(getNodeRef()).getParentRef());
}
// initial name to attempt the copy of the item with
String name = getName();
String translationPrefix = "";
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
{
// copy as link was specifically requested by the user
String linkTo = Application.getMessage(fc, MSG_LINK_TO);
name = linkTo + ' ' + name;
}
// Loop until we find a target name that doesn't exist
for(;;)
{
try
{
final String currentTranslationPrefix = translationPrefix;
final String currentName = name;
// attempt each copy/paste in its own transaction
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
if (getMode() == ClipboardStatus.COPY)
{
if (action == UIClipboardShelfItem.ACTION_PASTE_LINK)
{
// LINK operation
if (logger.isDebugEnabled())
logger.debug("Attempting to link node ID: " + getNodeRef() + " into node: " + destRef.toString());
// we create a special Link Object node that has a property to reference the original
// create the node using the nodeService (can only use FileFolderService for content)
if (checkExists(currentName + LINK_NODE_EXTENSION, destRef) == false)
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>(2, 1.0f);
String newName = currentName + LINK_NODE_EXTENSION;
props.put(ContentModel.PROP_NAME, newName);
props.put(ContentModel.PROP_LINK_DESTINATION, getNodeRef());
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT))
{
// create File Link node
ChildAssociationRef childRef = nodeService.createNode(
destRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(assocRef.getQName().getNamespaceURI(), newName),
ApplicationModel.TYPE_FILELINK,
props);
// apply the titled aspect - title and description
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(2, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, currentName);
titledProps.put(ContentModel.PROP_DESCRIPTION, currentName);
nodeService.addAspect(childRef.getChildRef(), ContentModel.ASPECT_TITLED, titledProps);
}
else
{
// create Folder link node
ChildAssociationRef childRef = nodeService.createNode(
destRef,
ContentModel.ASSOC_CONTAINS,
assocRef.getQName(),
ApplicationModel.TYPE_FOLDERLINK,
props);
// apply the uifacets aspect - icon, title and description props
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(4, 1.0f);
uiFacetsProps.put(ApplicationModel.PROP_ICON, "space-icon-link");
uiFacetsProps.put(ContentModel.PROP_TITLE, currentName);
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, currentName);
nodeService.addAspect(childRef.getChildRef(), ApplicationModel.ASPECT_UIFACETS, uiFacetsProps);
}
}
}
else
{
// COPY operation
if (logger.isDebugEnabled())
logger.debug("Attempting to copy node: " + getNodeRef() + " into node ID: " + destRef.toString());
// first check that we are not attempting to copy a duplicate into the same parent
if (destRef.equals(assocRef.getParentRef()) && currentName.equals(getName()))
{
// manually change the name if this occurs
throw new FileExistsException(destRef, currentName);
}
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
// copy the file/folder
fileFolderService.copy(
getNodeRef(),
destRef,
currentName);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.copyTranslationContainer(getNodeRef(), destRef, currentTranslationPrefix);
}
else
{
// copy the node
if (checkExists(currentName, destRef) == false)
{
copyService.copyAndRename(
getNodeRef(),
destRef,
ContentModel.ASSOC_CONTAINS,
assocRef.getQName(),
true);
}
}
}
}
else
{
// MOVE operation
if (logger.isDebugEnabled())
logger.debug("Attempting to move node: " + getNodeRef() + " into node ID: " + destRef.toString());
if (dd.isSubClass(getType(), ContentModel.TYPE_CONTENT) ||
dd.isSubClass(getType(), ContentModel.TYPE_FOLDER))
{
// move the file/folder
fileFolderService.moveFrom(getNodeRef(), getParent(), destRef, currentName);
}
else if(dd.isSubClass(getType(), ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
// copy the mlContainer and its translations
multilingualContentService.moveTranslationContainer(getNodeRef(), destRef);
}
else
{
if (isPrimaryParent)
{
// move the node
nodeService.moveNode(getNodeRef(), destRef, ContentModel.ASSOC_CONTAINS, assocRef.getQName());
}
else
{
nodeService.removeChild(getParent(), getNodeRef());
nodeService.addChild(destRef, getNodeRef(), assocRef.getTypeQName(), assocRef.getQName());
}
}
}
return null;
}
});
// We got here without error, so no need to loop with a new name
break;
}
catch (FileExistsException fileExistsErr)
{
// If mode is COPY, have another go around the loop with a new name
if (getMode() == ClipboardStatus.COPY)
{
String copyOf = Application.getMessage(fc, MSG_COPY_OF);
name = copyOf + ' ' + name;
translationPrefix = copyOf + ' ' + translationPrefix;
}
else
{
// we should not rename an item when it is being moved - so exit
throw fileExistsErr;
}
}
}
return true;
}
else
{
return false;
}
}
}

View File

@@ -1,175 +1,175 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCCheckoutFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 1137163500648349730L;
public static final String LBL_SAVE = "save";
public static final String LBL_CHECKOUT = "check_out";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CCCheckoutFileDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return checkoutFile(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CHECKOUT);
}
@Override
public String getContainerTitle()
{
final Node document = property.getDocument();
if (document != null){
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, LBL_CHECKOUT) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ document.getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
return null;
}
/**
* Action called upon completion of the Check Out file page
*/
public String checkoutFile(FacesContext context, String outcome)
{
boolean checkoutSuccessful = false;
final Node node = property.getDocument();
if (node != null)
{
try
{
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: " + property.getCopyLocation());
logger.debug("Selected Space Id: " + property.getSelectedSpaceId());
}
NodeRef workingCopyRef = null;
if (property.getCopyLocation().equals(CCProperties.COPYLOCATION_OTHER) && property.getSelectedSpaceId() != null)
{
// checkout to a arbituary parent Space
NodeRef destRef = property.getSelectedSpaceId();
ChildAssociationRef childAssocRef = getNodeService().getPrimaryParent(destRef);
workingCopyRef = property.getVersionOperationsService().checkout(node.getNodeRef(), destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName());
}
else
{
// checkout the content to the current space
workingCopyRef = property.getVersionOperationsService().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 (property.isWorkflowAction() && property.getWorkflowTaskId() != null && (property.getWorkflowTaskId().equals("null") == false))
{
WorkflowTask task = property.getWorkflowService().getTaskById(property.getWorkflowTaskId());
if (task != null)
{
NodeRef workflowPackage = (NodeRef) task.properties.get(WorkflowModel.ASSOC_PACKAGE);
if (workflowPackage != null)
{
getNodeService().addChild(workflowPackage, workingCopyRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName
.createValidLocalName((String) getNodeService().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);
property.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", FileTypeImageUtils.getFileTypeImage(workingCopy.getName(), false));
// mark as successful
checkoutSuccessful = true;
}
catch (Throwable err)
{
Utils.addErrorMessage(Application.getMessage(context, MSG_ERROR_CHECKOUT) + err.getMessage(), err);
ReportedException.throwIfNecessary(err);
}
}
else
{
logger.warn("WARNING: checkoutFile called without a current Document!");
}
// determine which page to show next if the checkout was successful.
if (checkoutSuccessful)
{
// If a check-in rule is present in the space
// the document was checked out to the working copy would have
// already disappeared!
if (getNodeService().exists(property.getWorkingDocument().getNodeRef()))
{
// go to the page that allows the user to download the content
// for editing
outcome = "dialog:checkoutFileLink"; // "checkoutFileLink";
// //checkout-file-link.jsp
// currentAction = Action.CHECKOUT_FILE_LINK;
}
else
{
// show a page telling the user that the content has already
// been checked in
outcome = "dialog:workingCopyMissing";// "workingCopyMissing";
// //
// working-copy-missing.jsp
// currentAction = Action.WORKING_COPY_MISSING;
}
}
return outcome;
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.repo.workflow.WorkflowModel;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.servlet.DownloadContentServlet;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCCheckoutFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 1137163500648349730L;
public static final String LBL_SAVE = "save";
public static final String LBL_CHECKOUT = "check_out";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CCCheckoutFileDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return checkoutFile(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CHECKOUT);
}
@Override
public String getContainerTitle()
{
final Node document = property.getDocument();
if (document != null){
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, LBL_CHECKOUT) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ document.getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
return null;
}
/**
* Action called upon completion of the Check Out file page
*/
public String checkoutFile(FacesContext context, String outcome)
{
boolean checkoutSuccessful = false;
final Node node = property.getDocument();
if (node != null)
{
try
{
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: " + property.getCopyLocation());
logger.debug("Selected Space Id: " + property.getSelectedSpaceId());
}
NodeRef workingCopyRef = null;
if (property.getCopyLocation().equals(CCProperties.COPYLOCATION_OTHER) && property.getSelectedSpaceId() != null)
{
// checkout to a arbituary parent Space
NodeRef destRef = property.getSelectedSpaceId();
ChildAssociationRef childAssocRef = getNodeService().getPrimaryParent(destRef);
workingCopyRef = property.getVersionOperationsService().checkout(node.getNodeRef(), destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName());
}
else
{
// checkout the content to the current space
workingCopyRef = property.getVersionOperationsService().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 (property.isWorkflowAction() && property.getWorkflowTaskId() != null && (property.getWorkflowTaskId().equals("null") == false))
{
WorkflowTask task = property.getWorkflowService().getTaskById(property.getWorkflowTaskId());
if (task != null)
{
NodeRef workflowPackage = (NodeRef) task.properties.get(WorkflowModel.ASSOC_PACKAGE);
if (workflowPackage != null)
{
getNodeService().addChild(workflowPackage, workingCopyRef, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, QName
.createValidLocalName((String) getNodeService().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);
property.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", FileTypeImageUtils.getFileTypeImage(workingCopy.getName(), false));
// mark as successful
checkoutSuccessful = true;
}
catch (Throwable err)
{
Utils.addErrorMessage(Application.getMessage(context, MSG_ERROR_CHECKOUT) + err.getMessage(), err);
ReportedException.throwIfNecessary(err);
}
}
else
{
logger.warn("WARNING: checkoutFile called without a current Document!");
}
// determine which page to show next if the checkout was successful.
if (checkoutSuccessful)
{
// If a check-in rule is present in the space
// the document was checked out to the working copy would have
// already disappeared!
if (getNodeService().exists(property.getWorkingDocument().getNodeRef()))
{
// go to the page that allows the user to download the content
// for editing
outcome = "dialog:checkoutFileLink"; // "checkoutFileLink";
// //checkout-file-link.jsp
// currentAction = Action.CHECKOUT_FILE_LINK;
}
else
{
// show a page telling the user that the content has already
// been checked in
outcome = "dialog:workingCopyMissing";// "workingCopyMissing";
// //
// working-copy-missing.jsp
// currentAction = Action.WORKING_COPY_MISSING;
}
}
return outcome;
}
}

View File

@@ -1,90 +1,90 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCCheckoutFileLinkDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -4732775752517417543L;
public static final String MSG_CHECKOUT_OF = "check_out_of";
public static final String LBL_UNDO_CHECKOUT = "undo_checkout";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CCCheckoutFileLinkDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return checkoutFileOK(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_CHECKOUT_OF) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_UNDO_CHECKOUT);
}
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "ok");
}
@Override
public String cancel()
{
undoCheckout();
resetState();
super.cancel();
return "browse";
}
/**
* Action called upon completion of the Check Out file Link download page
*/
public String checkoutFileOK(FacesContext context, String outcome)
{
Node node = property.getWorkingDocument();
if (node != null)
{
// reset the underlying node
if (this.browseBean.getDocument() != null)
{
this.browseBean.getDocument().reset();
}
// clean up and clear action context
resetState();
property.setDocument(null);
property.setWorkingDocument(null);
// currentAction = Action.NONE;
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + ":browse";
}
else
{
logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
}
return outcome;
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCCheckoutFileLinkDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -4732775752517417543L;
public static final String MSG_CHECKOUT_OF = "check_out_of";
public static final String LBL_UNDO_CHECKOUT = "undo_checkout";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CCCheckoutFileLinkDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return checkoutFileOK(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_CHECKOUT_OF) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_UNDO_CHECKOUT);
}
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), "ok");
}
@Override
public String cancel()
{
undoCheckout();
resetState();
super.cancel();
return "browse";
}
/**
* Action called upon completion of the Check Out file Link download page
*/
public String checkoutFileOK(FacesContext context, String outcome)
{
Node node = property.getWorkingDocument();
if (node != null)
{
// reset the underlying node
if (this.browseBean.getDocument() != null)
{
this.browseBean.getDocument().reset();
}
// clean up and clear action context
resetState();
property.setDocument(null);
property.setWorkingDocument(null);
// currentAction = Action.NONE;
outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + ":browse";
}
else
{
logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
}
return outcome;
}
}

View File

@@ -1,44 +1,44 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -1145049277343144264L;
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
public static final String LBL_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return super.cancel();
}
@Override
public String cancel()
{
property.setDocument(null);
property.setWorkingDocument(null);
resetState();
return super.cancel();
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CLOSE);
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_LEFT_QUOTE) + property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -1145049277343144264L;
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
public static final String LBL_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return super.cancel();
}
@Override
public String cancel()
{
property.setDocument(null);
property.setWorkingDocument(null);
resetState();
return super.cancel();
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CLOSE);
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_LEFT_QUOTE) + property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
}

View File

@@ -1,39 +1,39 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditHtmlInlineDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 5971155828037579931L;
public static final String LBL_SAVE = "save";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return editInline(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_SAVE);
}
@Override
public String getContainerTitle()
{
return property.getDocument().getName();
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditHtmlInlineDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 5971155828037579931L;
public static final String LBL_SAVE = "save";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return editInline(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_SAVE);
}
@Override
public String getContainerTitle()
{
return property.getDocument().getName();
}
}

View File

@@ -1,39 +1,39 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditTextInlineDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 4657371875928010937L;
public static final String LBL_SAVE = "save";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return editInline(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_SAVE);
}
@Override
public String getContainerTitle()
{
return property.getDocument().getName();
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
public class CCEditTextInlineDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 4657371875928010937L;
public static final String LBL_SAVE = "save";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return editInline(context, outcome);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_SAVE);
}
@Override
public String getContainerTitle()
{
return property.getDocument().getName();
}
}

View File

@@ -1,406 +1,406 @@
package org.alfresco.web.bean.coci;
import java.io.File;
import java.io.Serializable;
import javax.faces.context.FacesContext;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
public class CCProperties implements Serializable
{
private static final long serialVersionUID = -79530354521757202L;
/** The VersionOperationsService to be used by the bean */
transient protected CheckOutCheckInService versionOperationsService;
/** The VersionQueryService to be used by the bean */
transient protected VersionService versionQueryService;
/** The ContentService to be used by the bean */
transient protected ContentService contentService;
/** The WorkflowService to be used by the bean */
transient protected WorkflowService workflowService;
/** Content of the document returned from in-line editing */
private String editorOutput;
/** Content of the document used for HTML in-line editing */
private String documentContent;
/** The working copy of the document we are checking out */
private Node workingDocument;
/** The current document */
private Node document;
/** transient form and upload properties */
private File file;
private String fileName;
private String webdavUrl;
private String cifsPath;
private boolean keepCheckedOut = false;
private boolean minorChange = true;
private boolean isWorkflowAction = false;
private String workflowTaskId;
private NodeRef selectedSpaceId = null;
/** constants for copy location selection */
public static final String COPYLOCATION_CURRENT = "current";
public static final String COPYLOCATION_OTHER = "other";
private String versionNotes = "";
private String copyLocation = COPYLOCATION_CURRENT;
/**
* @return Returns the VersionOperationsService.
*/
public CheckOutCheckInService getVersionOperationsService()
{
//check for null in cluster environment
if (versionOperationsService == null)
{
versionOperationsService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCheckOutCheckInService();
}
return versionOperationsService;
}
/**
* @param versionOperationsService
* The VersionOperationsService to set.
*/
public void setVersionOperationsService(CheckOutCheckInService versionOperationsService)
{
this.versionOperationsService = versionOperationsService;
}
/**
* @return Returns the VersionQueryService.
*/
public VersionService getVersionQueryService()
{
if (this.versionQueryService == null)
{
this.versionQueryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getVersionService();
}
return this.versionQueryService;
}
/**
* @param versionQueryService
* The VersionQueryService to set.
*/
public void setVersionQueryService(VersionService versionQueryService)
{
this.versionQueryService = versionQueryService;
}
/**
* @return Returns the ContentService.
*/
public ContentService getContentService()
{
//check for null in cluster environment
if (contentService == null)
{
contentService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
}
return 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 workflowService
*/
public WorkflowService getWorkflowService()
{
//check for null for cluster environment
if (workflowService == null)
{
workflowService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getWorkflowService();
}
return workflowService;
}
/**
* @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;
}
/**
* @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 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;
}
/**
* @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 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 the file
*/
public File getFile()
{
return file;
}
/**
* @param file the file to set
*/
public void setFile(File file)
{
this.file = file;
}
/**
* @return the fileName
*/
public String getFileName()
{
return fileName;
}
/**
* @param fileName the fileName to set
*/
public void setFileName(String fileName)
{
this.fileName = fileName;
}
/**
* @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 the isWorkflowAction
*/
public boolean isWorkflowAction()
{
return isWorkflowAction;
}
/**
* @param isWorkflowAction the isWorkflowAction to set
*/
public void setWorkflowAction(boolean isWorkflowAction)
{
this.isWorkflowAction = isWorkflowAction;
}
/**
* @return the workflowTaskId
*/
public String getWorkflowTaskId()
{
return workflowTaskId;
}
/**
* @param workflowTaskId the workflowTaskId to set
*/
public void setWorkflowTaskId(String workflowTaskId)
{
this.workflowTaskId = workflowTaskId;
}
/**
* @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 copy location. Either the current or other space.
*/
public String getCopyLocation()
{
if (this.getFileName() == null || this.getFileName().length() == 0)
{
return this.copyLocation;
}
else
{
return CCProperties.COPYLOCATION_OTHER;
}
}
/**
* @param copyLocation
* The copy location. Either the current or other space.
*/
public void setCopyLocation(String copyLocation)
{
this.copyLocation = copyLocation;
}
/**
* @return Returns WebDav url for online editing. If webdav online editing didn't yet started, returns null
*/
public String getWebdavUrl()
{
return webdavUrl;
}
/**
* @param webdavUrl The webdav url. Using only for online editing
*/
public void setWebdavUrl(String webdavUrl)
{
this.webdavUrl = webdavUrl;
}
/**
* @return Returns CIFS path for online editing. If cifs online editing didn't yet started, returns null
*/
public String getCifsPath()
{
return cifsPath;
}
/**
* @param cifsPath The cifs path. Using only for online editing
*/
public void setCifsPath(String cifsPath)
{
this.cifsPath = cifsPath;
}
}
package org.alfresco.web.bean.coci;
import java.io.File;
import java.io.Serializable;
import javax.faces.context.FacesContext;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
public class CCProperties implements Serializable
{
private static final long serialVersionUID = -79530354521757202L;
/** The VersionOperationsService to be used by the bean */
transient protected CheckOutCheckInService versionOperationsService;
/** The VersionQueryService to be used by the bean */
transient protected VersionService versionQueryService;
/** The ContentService to be used by the bean */
transient protected ContentService contentService;
/** The WorkflowService to be used by the bean */
transient protected WorkflowService workflowService;
/** Content of the document returned from in-line editing */
private String editorOutput;
/** Content of the document used for HTML in-line editing */
private String documentContent;
/** The working copy of the document we are checking out */
private Node workingDocument;
/** The current document */
private Node document;
/** transient form and upload properties */
private File file;
private String fileName;
private String webdavUrl;
private String cifsPath;
private boolean keepCheckedOut = false;
private boolean minorChange = true;
private boolean isWorkflowAction = false;
private String workflowTaskId;
private NodeRef selectedSpaceId = null;
/** constants for copy location selection */
public static final String COPYLOCATION_CURRENT = "current";
public static final String COPYLOCATION_OTHER = "other";
private String versionNotes = "";
private String copyLocation = COPYLOCATION_CURRENT;
/**
* @return Returns the VersionOperationsService.
*/
public CheckOutCheckInService getVersionOperationsService()
{
//check for null in cluster environment
if (versionOperationsService == null)
{
versionOperationsService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getCheckOutCheckInService();
}
return versionOperationsService;
}
/**
* @param versionOperationsService
* The VersionOperationsService to set.
*/
public void setVersionOperationsService(CheckOutCheckInService versionOperationsService)
{
this.versionOperationsService = versionOperationsService;
}
/**
* @return Returns the VersionQueryService.
*/
public VersionService getVersionQueryService()
{
if (this.versionQueryService == null)
{
this.versionQueryService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getVersionService();
}
return this.versionQueryService;
}
/**
* @param versionQueryService
* The VersionQueryService to set.
*/
public void setVersionQueryService(VersionService versionQueryService)
{
this.versionQueryService = versionQueryService;
}
/**
* @return Returns the ContentService.
*/
public ContentService getContentService()
{
//check for null in cluster environment
if (contentService == null)
{
contentService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService();
}
return 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 workflowService
*/
public WorkflowService getWorkflowService()
{
//check for null for cluster environment
if (workflowService == null)
{
workflowService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getWorkflowService();
}
return workflowService;
}
/**
* @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;
}
/**
* @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 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;
}
/**
* @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 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 the file
*/
public File getFile()
{
return file;
}
/**
* @param file the file to set
*/
public void setFile(File file)
{
this.file = file;
}
/**
* @return the fileName
*/
public String getFileName()
{
return fileName;
}
/**
* @param fileName the fileName to set
*/
public void setFileName(String fileName)
{
this.fileName = fileName;
}
/**
* @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 the isWorkflowAction
*/
public boolean isWorkflowAction()
{
return isWorkflowAction;
}
/**
* @param isWorkflowAction the isWorkflowAction to set
*/
public void setWorkflowAction(boolean isWorkflowAction)
{
this.isWorkflowAction = isWorkflowAction;
}
/**
* @return the workflowTaskId
*/
public String getWorkflowTaskId()
{
return workflowTaskId;
}
/**
* @param workflowTaskId the workflowTaskId to set
*/
public void setWorkflowTaskId(String workflowTaskId)
{
this.workflowTaskId = workflowTaskId;
}
/**
* @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 copy location. Either the current or other space.
*/
public String getCopyLocation()
{
if (this.getFileName() == null || this.getFileName().length() == 0)
{
return this.copyLocation;
}
else
{
return CCProperties.COPYLOCATION_OTHER;
}
}
/**
* @param copyLocation
* The copy location. Either the current or other space.
*/
public void setCopyLocation(String copyLocation)
{
this.copyLocation = copyLocation;
}
/**
* @return Returns WebDav url for online editing. If webdav online editing didn't yet started, returns null
*/
public String getWebdavUrl()
{
return webdavUrl;
}
/**
* @param webdavUrl The webdav url. Using only for online editing
*/
public void setWebdavUrl(String webdavUrl)
{
this.webdavUrl = webdavUrl;
}
/**
* @return Returns CIFS path for online editing. If cifs online editing didn't yet started, returns null
*/
public String getCifsPath()
{
return cifsPath;
}
/**
* @param cifsPath The cifs path. Using only for online editing
*/
public void setCifsPath(String cifsPath)
{
this.cifsPath = cifsPath;
}
}

View File

@@ -1,101 +1,101 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCUndoCheckoutFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -6957120889259486975L;
public static final String LBL_UNDO_CHECKOUT = "undo_checkout";
public static final String MSG_UNDO_CHECKOUT_FOR = "undo_checkout_for";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CheckinCheckoutDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return undoCheckoutFile(context, outcome);
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_UNDO_CHECKOUT_FOR) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_UNDO_CHECKOUT);
}
/**
* 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(FacesContext context, String outcome)
{
Node node = property.getDocument();
if (node != null)
{
try
{
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
{
this.property.getVersionOperationsService().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!");
}
resetState();
}
catch (Throwable err)
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err);
ReportedException.throwIfNecessary(err);
}
}
else
{
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
}
return outcome + ":browse";
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class CCUndoCheckoutFileDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = -6957120889259486975L;
public static final String LBL_UNDO_CHECKOUT = "undo_checkout";
public static final String MSG_UNDO_CHECKOUT_FOR = "undo_checkout_for";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
private static Log logger = LogFactory.getLog(CheckinCheckoutDialog.class);
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
return undoCheckoutFile(context, outcome);
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_UNDO_CHECKOUT_FOR) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_UNDO_CHECKOUT);
}
/**
* 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(FacesContext context, String outcome)
{
Node node = property.getDocument();
if (node != null)
{
try
{
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
{
this.property.getVersionOperationsService().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!");
}
resetState();
}
catch (Throwable err)
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err);
ReportedException.throwIfNecessary(err);
}
}
else
{
logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
}
return outcome + ":browse";
}
}

View File

@@ -1,46 +1,46 @@
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
public class CCWorkingCopyMissingDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 8067485292477557683L;
public static final String MSG_WORKING_COPY_FOR = "working_copy_for";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
public static final String LBL_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION);
return getDefaultCancelOutcome();
}
@Override
public String cancel()
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION);
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + ":browse";
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_WORKING_COPY_FOR) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CLOSE);
}
}
package org.alfresco.web.bean.coci;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
public class CCWorkingCopyMissingDialog extends CheckinCheckoutDialog
{
private static final long serialVersionUID = 8067485292477557683L;
public static final String MSG_WORKING_COPY_FOR = "working_copy_for";
private final static String MSG_LEFT_QUOTE = "left_qoute";
private final static String MSG_RIGHT_QUOTE = "right_quote";
public static final String LBL_CLOSE = "close";
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION);
return getDefaultCancelOutcome();
}
@Override
public String cancel()
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove(AlfrescoNavigationHandler.EXTERNAL_CONTAINER_SESSION);
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + ":browse";
}
@Override
public String getContainerTitle()
{
FacesContext fc = FacesContext.getCurrentInstance();
return Application.getMessage(fc, MSG_WORKING_COPY_FOR) + " " + Application.getMessage(fc, MSG_LEFT_QUOTE)
+ property.getDocument().getName() + Application.getMessage(fc, MSG_RIGHT_QUOTE);
}
@Override
public String getCancelButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), LBL_CLOSE);
}
}

View File

@@ -1,330 +1,330 @@
package org.alfresco.web.bean.content;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigService;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
/**
* Bean implementation for the "Add Content" dialog
*
* @author gavinc
*/
public class AddContentDialog extends BaseContentWizard
{
private final static String MSG_OK = "ok";
private static final long serialVersionUID = 3593557546118692687L;
protected List<String> inlineEditableMimeTypes;
protected File file;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// Try and extract metadata from the file
ContentReader cr = new FileContentReader(this.file);
cr.setMimetype(this.mimeType);
cr.setEncoding(this.encoding);
// create properties for content type
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(5, 1.0f);
if (Repository.extractMetadata(FacesContext.getCurrentInstance(), cr, contentProps))
{
this.author = (String)(contentProps.get(ContentModel.PROP_AUTHOR));
this.title = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_TITLE));
this.description = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_DESCRIPTION));
}
// default the title to the file name if not set
if (this.title == null)
{
this.title = this.fileName;
}
// determine whether inline editing should be enabled by default.
// if the mime type of the added file is in the list of mime types
// configured in "Content Wizards" then enable inline editing
List<String> mimeTypes = getInlineEditableMimeTypes();
if (mimeTypes.contains(this.mimeType))
{
this.inlineEdit = true;
}
saveContent(this.file, null);
// return default outcome
return outcome;
}
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
clearUpload();
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
clearUpload();
// as we were successful, go to the set properties dialog if asked
// to otherwise just return
if (this.showOtherProperties)
{
// check whether the created node is checked out, if a 'check out'
// rule is present in the space the new node will be and an
// attempt to modify the properties will cause an error (ALF-438)
if (getNodeService().hasAspect(this.createdNode, ContentModel.ASPECT_LOCKABLE))
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_NODE_LOCKED));
return outcome;
}
else
{
// we are going to immediately edit the properties so we need
// to setup the BrowseBean context appropriately
this.browseBean.setDocument(new Node(this.createdNode));
return "dialog:setContentProperties";
}
}
else
{
return outcome;
}
}
@Override
protected String getDefaultFinishOutcome()
{
// as we are using this dialog outside the dialog framework
// just go back to the main page
return "dialog:close:browse";
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @return Returns the message to display when a file has been uploaded
*/
public String getFileUploadSuccessMsg()
{
// NOTE: This is a far from ideal solution but will do until we have
// a pure JSF upload solution working. This method is only called
// after a file is uploaded, so we can calculate the mime type and
// determine whether to enable inline editing in here.
FacesContext fc = FacesContext.getCurrentInstance();
// Identify the mimetype as best as we can
this.mimeType = Repository.getMimeTypeForFile(fc, this.fileName, this.file);
// Identify the encoding as best we can (only really important for text based formats)
this.encoding = "UTF-8";
InputStream is = null;
try
{
if (this.file != null)
{
is = new BufferedInputStream(new FileInputStream(this.file));
this.encoding = Repository.guessEncoding(fc, is, this.mimeType);
}
}
catch (Throwable e)
{
// Not terminal
logger.error("Failed to get encoding from file: " + this.fileName, e);
}
finally
{
try { is.close(); } catch (Throwable e) {} // Includes NPE
}
// Offer inline editing for HTML only
this.inlineEdit = (this.mimeType.equals(MimetypeMap.MIMETYPE_HTML));
// get the file upload message
String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success");
return MessageFormat.format(msg, new Object[] {Utils.encode(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);
}
}
// ------------------------------------------------------------------------------
// Action event handlers
/**
* Action listener called when the add content dialog is called
*/
public void start(ActionEvent event)
{
// NOTE: this is a temporary solution to allow us to use the new dialog
// framework beans outside of the dialog framework, we need to do
// this because the uploading requires a separate non-JSF form, this
// approach can not be used in the current dialog framework. Until
// we have a pure JSF upload solution we need this initialisation
init(null);
}
/**
* Action handler called when the user wishes to remove an uploaded file
*/
public String removeUploadedFile()
{
clearUpload();
// also clear the file name
this.fileName = null;
// refresh the current page
return null;
}
/**
* Action handler called when the dialog is cancelled
*/
public String cancel()
{
clearUpload();
return "dialog:close";
}
// ------------------------------------------------------------------------------
// Helper Methods
/**
* Deletes the uploaded file and removes the FileUploadBean from the session
*/
protected void clearUpload()
{
// delete the temporary file we uploaded earlier
if (this.file != null)
{
this.file.delete();
}
this.file = null;
// remove the file upload bean from the session
FacesContext ctx = FacesContext.getCurrentInstance();
ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
}
protected List<String> getInlineEditableMimeTypes()
{
if ((this.inlineEditableMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.inlineEditableMimeTypes = new ArrayList<String>(8);
// get the create mime types list from the config
ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance());
Config wizardCfg = svc.getConfig("Content Wizards");
if (wizardCfg != null)
{
ConfigElement typesCfg = wizardCfg.getConfigElement("create-mime-types");
if (typesCfg != null)
{
for (ConfigElement child : typesCfg.getChildren())
{
String currentMimeType = child.getAttribute("name");
this.inlineEditableMimeTypes.add(currentMimeType);
}
}
}
}
return this.inlineEditableMimeTypes;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_OK);
}
@Override
protected String formatErrorMessage(Throwable exception)
{
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_content"),
exception.getMessage());
}
}
}
package org.alfresco.web.bean.content;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigService;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.FileUploadBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
/**
* Bean implementation for the "Add Content" dialog
*
* @author gavinc
*/
public class AddContentDialog extends BaseContentWizard
{
private final static String MSG_OK = "ok";
private static final long serialVersionUID = 3593557546118692687L;
protected List<String> inlineEditableMimeTypes;
protected File file;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// Try and extract metadata from the file
ContentReader cr = new FileContentReader(this.file);
cr.setMimetype(this.mimeType);
cr.setEncoding(this.encoding);
// create properties for content type
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(5, 1.0f);
if (Repository.extractMetadata(FacesContext.getCurrentInstance(), cr, contentProps))
{
this.author = (String)(contentProps.get(ContentModel.PROP_AUTHOR));
this.title = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_TITLE));
this.description = DefaultTypeConverter.INSTANCE.convert(String.class, contentProps.get(ContentModel.PROP_DESCRIPTION));
}
// default the title to the file name if not set
if (this.title == null)
{
this.title = this.fileName;
}
// determine whether inline editing should be enabled by default.
// if the mime type of the added file is in the list of mime types
// configured in "Content Wizards" then enable inline editing
List<String> mimeTypes = getInlineEditableMimeTypes();
if (mimeTypes.contains(this.mimeType))
{
this.inlineEdit = true;
}
saveContent(this.file, null);
// return default outcome
return outcome;
}
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
clearUpload();
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
clearUpload();
// as we were successful, go to the set properties dialog if asked
// to otherwise just return
if (this.showOtherProperties)
{
// check whether the created node is checked out, if a 'check out'
// rule is present in the space the new node will be and an
// attempt to modify the properties will cause an error (ALF-438)
if (getNodeService().hasAspect(this.createdNode, ContentModel.ASPECT_LOCKABLE))
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_NODE_LOCKED));
return outcome;
}
else
{
// we are going to immediately edit the properties so we need
// to setup the BrowseBean context appropriately
this.browseBean.setDocument(new Node(this.createdNode));
return "dialog:setContentProperties";
}
}
else
{
return outcome;
}
}
@Override
protected String getDefaultFinishOutcome()
{
// as we are using this dialog outside the dialog framework
// just go back to the main page
return "dialog:close:browse";
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* @return Returns the message to display when a file has been uploaded
*/
public String getFileUploadSuccessMsg()
{
// NOTE: This is a far from ideal solution but will do until we have
// a pure JSF upload solution working. This method is only called
// after a file is uploaded, so we can calculate the mime type and
// determine whether to enable inline editing in here.
FacesContext fc = FacesContext.getCurrentInstance();
// Identify the mimetype as best as we can
this.mimeType = Repository.getMimeTypeForFile(fc, this.fileName, this.file);
// Identify the encoding as best we can (only really important for text based formats)
this.encoding = "UTF-8";
InputStream is = null;
try
{
if (this.file != null)
{
is = new BufferedInputStream(new FileInputStream(this.file));
this.encoding = Repository.guessEncoding(fc, is, this.mimeType);
}
}
catch (Throwable e)
{
// Not terminal
logger.error("Failed to get encoding from file: " + this.fileName, e);
}
finally
{
try { is.close(); } catch (Throwable e) {} // Includes NPE
}
// Offer inline editing for HTML only
this.inlineEdit = (this.mimeType.equals(MimetypeMap.MIMETYPE_HTML));
// get the file upload message
String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success");
return MessageFormat.format(msg, new Object[] {Utils.encode(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);
}
}
// ------------------------------------------------------------------------------
// Action event handlers
/**
* Action listener called when the add content dialog is called
*/
public void start(ActionEvent event)
{
// NOTE: this is a temporary solution to allow us to use the new dialog
// framework beans outside of the dialog framework, we need to do
// this because the uploading requires a separate non-JSF form, this
// approach can not be used in the current dialog framework. Until
// we have a pure JSF upload solution we need this initialisation
init(null);
}
/**
* Action handler called when the user wishes to remove an uploaded file
*/
public String removeUploadedFile()
{
clearUpload();
// also clear the file name
this.fileName = null;
// refresh the current page
return null;
}
/**
* Action handler called when the dialog is cancelled
*/
public String cancel()
{
clearUpload();
return "dialog:close";
}
// ------------------------------------------------------------------------------
// Helper Methods
/**
* Deletes the uploaded file and removes the FileUploadBean from the session
*/
protected void clearUpload()
{
// delete the temporary file we uploaded earlier
if (this.file != null)
{
this.file.delete();
}
this.file = null;
// remove the file upload bean from the session
FacesContext ctx = FacesContext.getCurrentInstance();
ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
}
protected List<String> getInlineEditableMimeTypes()
{
if ((this.inlineEditableMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
this.inlineEditableMimeTypes = new ArrayList<String>(8);
// get the create mime types list from the config
ConfigService svc = Application.getConfigService(FacesContext.getCurrentInstance());
Config wizardCfg = svc.getConfig("Content Wizards");
if (wizardCfg != null)
{
ConfigElement typesCfg = wizardCfg.getConfigElement("create-mime-types");
if (typesCfg != null)
{
for (ConfigElement child : typesCfg.getChildren())
{
String currentMimeType = child.getAttribute("name");
this.inlineEditableMimeTypes.add(currentMimeType);
}
}
}
}
return this.inlineEditableMimeTypes;
}
@Override
public String getFinishButtonLabel()
{
return Application.getMessage(FacesContext.getCurrentInstance(), MSG_OK);
}
@Override
protected String formatErrorMessage(Throwable exception)
{
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_content"),
exception.getMessage());
}
}
}

View File

@@ -1,260 +1,260 @@
package org.alfresco.web.bean.content;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigService;
/**
* Bean implementation for the "Create Content Wizard" dialog
*
* @author gavinc
*/
public class CreateContentWizard extends BaseContentWizard
{
private static final long serialVersionUID = -2740634368271194418L;
protected String content = null;
protected List<SelectItem> createMimeTypes;
private static Log logger = LogFactory.getLog(CreateContentWizard.class);
// ------------------------------------------------------------------------------
// Wizard implementation
@Override
public String finish()
{
String result = super.finish();
return result;
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
saveContent(null, this.content);
// return the default outcome
return outcome;
}
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
this.content = null;
this.inlineEdit = true;
this.mimeType = MimetypeMap.MIMETYPE_HTML;
}
@Override
public boolean getNextButtonDisabled()
{
// TODO: Allow the next button state to be configured so that
// wizard implementations don't have to worry about
// checking step numbers
boolean disabled = false;
int step = Application.getWizardManager().getCurrentStep();
switch(step)
{
case 1:
{
disabled = (this.fileName == null || this.fileName.length() == 0);
break;
}
}
return disabled;
}
@Override
public boolean getFinishButtonDisabled()
{
boolean disabled = false;
int step = Application.getWizardManager().getCurrentStep();
switch(step)
{
case 1:
{
disabled = (this.fileName == null || this.fileName.length() == 0);
break;
}
}
return disabled;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// as we were successful, go to the set properties dialog if asked
// to otherwise just return
if (this.showOtherProperties)
{
// check whether the created node is checked out, if a 'check out'
// rule is present in the space the new node will be and an
// attempt to modify the properties will cause an error (ALF-438)
if (getNodeService().hasAspect(this.createdNode, ContentModel.ASPECT_LOCKABLE))
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_NODE_LOCKED));
return outcome;
}
else
{
// we are going to immediately edit the properties so we need
// to setup the BrowseBean context appropriately
this.browseBean.setDocument(new Node(this.createdNode));
return getDefaultFinishOutcome() + AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"dialog:setContentProperties";
}
}
else
{
return outcome;
}
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* @return Returns the content from the edited form.
*/
public String getContent()
{
return this.content;
}
/**
* @param content The content to edit (should be clear initially)
*/
public void setContent(String content)
{
this.content = content;
}
/**
* @return Returns a list of mime types to allow the user to select from
*/
public List<SelectItem> getCreateMimeTypes()
{
if ((this.createMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
FacesContext context = FacesContext.getCurrentInstance();
// add the well known object type to start with
this.createMimeTypes = new ArrayList<SelectItem>(5);
// add the configured create mime types to the list
ConfigService svc = Application.getConfigService(context);
Config wizardCfg = svc.getConfig("Content Wizards");
if (wizardCfg != null)
{
ConfigElement typesCfg = wizardCfg.getConfigElement("create-mime-types");
if (typesCfg != null)
{
for (ConfigElement child : typesCfg.getChildren())
{
String currentMimeType = child.getAttribute("name");
if (currentMimeType != null)
{
String label = getSummaryMimeType(currentMimeType);
this.createMimeTypes.add(new SelectItem(currentMimeType, label));
}
}
// make sure the list is sorted by the label
QuickSort sorter = new QuickSort(this.objectTypes, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
else
{
logger.warn("Could not find 'create-mime-types' configuration element");
}
}
else
{
logger.warn("Could not find 'Content Wizards' configuration section");
}
}
return this.createMimeTypes;
}
/**
* @return Returns the summary data for the wizard.
*/
public String getSummary()
{
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
// TODO: show first few lines of content here?
return buildSummary(
new String[] {bundle.getString("file_name"),
bundle.getString("type"),
bundle.getString("content_type")},
new String[] {Utils.encode(this.fileName), getSummaryObjectType(),
getSummaryMimeType(this.mimeType)});
}
// ------------------------------------------------------------------------------
// Action event handlers
/**
* Create content type value changed by the user
*/
public void createContentChanged(ValueChangeEvent event)
{
// clear the content as HTML is not compatible with the plain text box etc.
this.content = null;
}
@Override
protected String formatErrorMessage(Throwable exception)
{
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_content"),
exception.getMessage());
}
}
}
package org.alfresco.web.bean.content;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.data.IDataContainer;
import org.alfresco.web.data.QuickSort;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigElement;
import org.springframework.extensions.config.ConfigService;
/**
* Bean implementation for the "Create Content Wizard" dialog
*
* @author gavinc
*/
public class CreateContentWizard extends BaseContentWizard
{
private static final long serialVersionUID = -2740634368271194418L;
protected String content = null;
protected List<SelectItem> createMimeTypes;
private static Log logger = LogFactory.getLog(CreateContentWizard.class);
// ------------------------------------------------------------------------------
// Wizard implementation
@Override
public String finish()
{
String result = super.finish();
return result;
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
saveContent(null, this.content);
// return the default outcome
return outcome;
}
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
this.content = null;
this.inlineEdit = true;
this.mimeType = MimetypeMap.MIMETYPE_HTML;
}
@Override
public boolean getNextButtonDisabled()
{
// TODO: Allow the next button state to be configured so that
// wizard implementations don't have to worry about
// checking step numbers
boolean disabled = false;
int step = Application.getWizardManager().getCurrentStep();
switch(step)
{
case 1:
{
disabled = (this.fileName == null || this.fileName.length() == 0);
break;
}
}
return disabled;
}
@Override
public boolean getFinishButtonDisabled()
{
boolean disabled = false;
int step = Application.getWizardManager().getCurrentStep();
switch(step)
{
case 1:
{
disabled = (this.fileName == null || this.fileName.length() == 0);
break;
}
}
return disabled;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// as we were successful, go to the set properties dialog if asked
// to otherwise just return
if (this.showOtherProperties)
{
// check whether the created node is checked out, if a 'check out'
// rule is present in the space the new node will be and an
// attempt to modify the properties will cause an error (ALF-438)
if (getNodeService().hasAspect(this.createdNode, ContentModel.ASPECT_LOCKABLE))
{
Utils.addErrorMessage(Application.getMessage(FacesContext.getCurrentInstance(), MSG_NODE_LOCKED));
return outcome;
}
else
{
// we are going to immediately edit the properties so we need
// to setup the BrowseBean context appropriately
this.browseBean.setDocument(new Node(this.createdNode));
return getDefaultFinishOutcome() + AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"dialog:setContentProperties";
}
}
else
{
return outcome;
}
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* @return Returns the content from the edited form.
*/
public String getContent()
{
return this.content;
}
/**
* @param content The content to edit (should be clear initially)
*/
public void setContent(String content)
{
this.content = content;
}
/**
* @return Returns a list of mime types to allow the user to select from
*/
public List<SelectItem> getCreateMimeTypes()
{
if ((this.createMimeTypes == null) || (Application.isDynamicConfig(FacesContext.getCurrentInstance())))
{
FacesContext context = FacesContext.getCurrentInstance();
// add the well known object type to start with
this.createMimeTypes = new ArrayList<SelectItem>(5);
// add the configured create mime types to the list
ConfigService svc = Application.getConfigService(context);
Config wizardCfg = svc.getConfig("Content Wizards");
if (wizardCfg != null)
{
ConfigElement typesCfg = wizardCfg.getConfigElement("create-mime-types");
if (typesCfg != null)
{
for (ConfigElement child : typesCfg.getChildren())
{
String currentMimeType = child.getAttribute("name");
if (currentMimeType != null)
{
String label = getSummaryMimeType(currentMimeType);
this.createMimeTypes.add(new SelectItem(currentMimeType, label));
}
}
// make sure the list is sorted by the label
QuickSort sorter = new QuickSort(this.objectTypes, "label", true, IDataContainer.SORT_CASEINSENSITIVE);
sorter.sort();
}
else
{
logger.warn("Could not find 'create-mime-types' configuration element");
}
}
else
{
logger.warn("Could not find 'Content Wizards' configuration section");
}
}
return this.createMimeTypes;
}
/**
* @return Returns the summary data for the wizard.
*/
public String getSummary()
{
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
// TODO: show first few lines of content here?
return buildSummary(
new String[] {bundle.getString("file_name"),
bundle.getString("type"),
bundle.getString("content_type")},
new String[] {Utils.encode(this.fileName), getSummaryObjectType(),
getSummaryMimeType(this.mimeType)});
}
// ------------------------------------------------------------------------------
// Action event handlers
/**
* Create content type value changed by the user
*/
public void createContentChanged(ValueChangeEvent event)
{
// clear the content as HTML is not compatible with the plain text box etc.
this.content = null;
}
@Override
protected String formatErrorMessage(Throwable exception)
{
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), "error_content"),
exception.getMessage());
}
}
}

View File

@@ -1,155 +1,155 @@
package org.alfresco.web.bean.content;
import java.text.MessageFormat;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Delete Content" dialog
*
* @author gavinc
*/
public class DeleteContentDialog extends BaseDialogBean
{
private static final long serialVersionUID = 4199496011879649213L;
transient private MultilingualContentService multilingualContentService;
private static final Log logger = LogFactory.getLog(DeleteContentDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// get the content to delete
Node node = this.browseBean.getDocument();
if (node != null)
{
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(node.getType()))
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete multilingual container: " + node.getId() + " and its translations" );
// delete the mlContainer and its translations
getMultilingualContentService().deleteTranslationContainer(node.getNodeRef());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete content node: " + node.getId());
// delete the node
this.getNodeService().deleteNode(node.getNodeRef());
}
}
else
{
logger.warn("WARNING: delete called without a current Document!");
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// clear action context
this.browseBean.setDocument(null);
// setting the outcome will show the browse view again
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
@Override
protected String getErrorMessageId()
{
return "error_delete_file";
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Returns the confirmation to display to the user before deleting the content.
*
* @return The formatted message to display
*/
public String getConfirmMessage()
{
String fileConfirmMsg = null;
Node document = this.browseBean.getDocument();
if(document.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_ml_container_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_empty_translation_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_translation_confirm");
}
else
{
String strHasMultipleParents = this.parameters.get("hasMultipleParents");
if (strHasMultipleParents != null && "true".equals(strHasMultipleParents))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_multiple_parents_confirm");
}
else
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_confirm");
}
}
return MessageFormat.format(fileConfirmMsg,
new Object[] {document.getName()});
}
/**
* @param multilingualContentService the Multilingual Content Service to set
*/
public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
protected MultilingualContentService getMultilingualContentService()
{
if (multilingualContentService == null)
{
multilingualContentService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getMultilingualContentService();
}
return multilingualContentService;
}
}
package org.alfresco.web.bean.content;
import java.text.MessageFormat;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.ml.MultilingualContentService;
import org.alfresco.web.app.AlfrescoNavigationHandler;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean implementation for the "Delete Content" dialog
*
* @author gavinc
*/
public class DeleteContentDialog extends BaseDialogBean
{
private static final long serialVersionUID = 4199496011879649213L;
transient private MultilingualContentService multilingualContentService;
private static final Log logger = LogFactory.getLog(DeleteContentDialog.class);
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
// get the content to delete
Node node = this.browseBean.getDocument();
if (node != null)
{
if(ContentModel.TYPE_MULTILINGUAL_CONTAINER.equals(node.getType()))
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete multilingual container: " + node.getId() + " and its translations" );
// delete the mlContainer and its translations
getMultilingualContentService().deleteTranslationContainer(node.getNodeRef());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Trying to delete content node: " + node.getId());
// delete the node
this.getNodeService().deleteNode(node.getNodeRef());
}
}
else
{
logger.warn("WARNING: delete called without a current Document!");
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// clear action context
this.browseBean.setDocument(null);
// setting the outcome will show the browse view again
return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
}
@Override
protected String getErrorMessageId()
{
return "error_delete_file";
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
/**
* Returns the confirmation to display to the user before deleting the content.
*
* @return The formatted message to display
*/
public String getConfirmMessage()
{
String fileConfirmMsg = null;
Node document = this.browseBean.getDocument();
if(document.getType().equals(ContentModel.TYPE_MULTILINGUAL_CONTAINER))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_ml_container_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_empty_translation_confirm");
}
else if(document.hasAspect(ContentModel.ASPECT_MULTILINGUAL_DOCUMENT))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_translation_confirm");
}
else
{
String strHasMultipleParents = this.parameters.get("hasMultipleParents");
if (strHasMultipleParents != null && "true".equals(strHasMultipleParents))
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_multiple_parents_confirm");
}
else
{
fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(),
"delete_file_confirm");
}
}
return MessageFormat.format(fileConfirmMsg,
new Object[] {document.getName()});
}
/**
* @param multilingualContentService the Multilingual Content Service to set
*/
public void setMultilingualContentService(MultilingualContentService multilingualContentService)
{
this.multilingualContentService = multilingualContentService;
}
protected MultilingualContentService getMultilingualContentService()
{
if (multilingualContentService == null)
{
multilingualContentService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getMultilingualContentService();
}
return multilingualContentService;
}
}

View File

@@ -1,306 +1,306 @@
package org.alfresco.web.bean.content;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
/**
* Bean implementation of the "Edit Content Properties" dialog.
*
* @author gavinc
*/
public class EditContentPropertiesDialog extends BaseDialogBean
{
private static final long serialVersionUID = -5681296528149487178L;
protected static final String TEMP_PROP_MIMETYPE = "mimetype";
protected static final String TEMP_PROP_ENCODING = "encoding";
protected Node editableNode;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// setup the editable node
this.editableNode = initEditableNode();
if(editableNode != null)
{
// special case for Mimetype - since this is a sub-property of the ContentData object
// we must extract it so it can be edited in the client, then we check for it later
// and create a new ContentData object to wrap it and it's associated URL
ContentData content = (ContentData)this.editableNode.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
this.editableNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype());
this.editableNode.getProperties().put(TEMP_PROP_ENCODING, content.getEncoding());
}
}
}
/**
* Init the editable Node
*/
protected Node initEditableNode()
{
final Node document = this.browseBean.getDocument();
if (document != null)
{
return new Node(document.getNodeRef());
}
return null;
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
NodeRef nodeRef = this.editableNode.getNodeRef();
Map<String, Object> editedProps = this.editableNode.getProperties();
// get the name and move the node as necessary
String name = (String) editedProps.get(ContentModel.PROP_NAME);
if (name != null)
{
getFileFolderService().rename(nodeRef, name);
}
// we need to put all the properties from the editable bag back into
// the format expected by the repository
Map<QName, Serializable> repoProps = this.getNodeService().getProperties(nodeRef);
// Extract and deal with the special mimetype property for ContentData
String mimetype = (String) editedProps.get(TEMP_PROP_MIMETYPE);
if (mimetype != null)
{
// remove temporary prop from list so it isn't saved with the others
editedProps.remove(TEMP_PROP_MIMETYPE);
ContentData contentData = (ContentData)editedProps.get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentData = ContentData.setMimetype(contentData, mimetype);
editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData);
}
}
// Extract and deal with the special encoding property for ContentData
String encoding = (String) editedProps.get(TEMP_PROP_ENCODING);
if (encoding != null)
{
// remove temporary prop from list so it isn't saved with the others
editedProps.remove(TEMP_PROP_ENCODING);
ContentData contentData = (ContentData) editedProps.get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentData = ContentData.setEncoding(contentData, encoding);
editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData);
}
}
// add the "author" aspect if required, properties will get set below
if (this.getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_AUTHOR) == false)
{
this.getNodeService().addAspect(nodeRef, ContentModel.ASPECT_AUTHOR, null);
}
// add the "titled" aspect if required, properties will get set below
if (this.getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false)
{
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
}
// add the remaining properties
Iterator<String> iterProps = editedProps.keySet().iterator();
while (iterProps.hasNext())
{
String propName = iterProps.next();
QName qname = QName.createQName(propName);
// make sure the property is represented correctly
Serializable propValue = (Serializable)editedProps.get(propName);
// check for empty strings when using number types, set to null in this case
if (propValue instanceof String)
{
PropertyDefinition propDef = this.getDictionaryService().getProperty(qname);
if (((String)propValue).length() == 0)
{
if (propDef != null)
{
if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) ||
propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.INT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.LONG))
{
propValue = null;
}
}
}
// handle locale strings to Locale objects
else if (propDef != null && propDef.getDataType().getName().equals(DataTypeDefinition.LOCALE))
{
propValue = I18NUtil.parseLocale((String)propValue);
}
}
repoProps.put(qname, propValue);
}
// send the properties back to the repository
this.getNodeService().setProperties(nodeRef, repoProps);
// we also need to persist any association changes that may have been made
// add any associations added in the UI
Map<String, Map<String, AssociationRef>> addedAssocs = this.editableNode.getAddedAssociations();
for (Map<String, AssociationRef> typedAssoc : addedAssocs.values())
{
for (AssociationRef assoc : typedAssoc.values())
{
this.getNodeService().createAssociation(assoc.getSourceRef(), assoc.getTargetRef(), assoc.getTypeQName());
}
}
// remove any association removed in the UI
Map<String, Map<String, AssociationRef>> removedAssocs = this.editableNode.getRemovedAssociations();
for (Map<String, AssociationRef> typedAssoc : removedAssocs.values())
{
for (AssociationRef assoc : typedAssoc.values())
{
this.getNodeService().removeAssociation(assoc.getSourceRef(), assoc.getTargetRef(), assoc.getTypeQName());
}
}
// add any child associations added in the UI
Map<String, Map<String, ChildAssociationRef>> addedChildAssocs = this.editableNode.getAddedChildAssociations();
for (Map<String, ChildAssociationRef> typedAssoc : addedChildAssocs.values())
{
for (ChildAssociationRef assoc : typedAssoc.values())
{
this.getNodeService().addChild(assoc.getParentRef(), assoc.getChildRef(), assoc.getTypeQName(), assoc.getTypeQName());
}
}
// remove any child association removed in the UI
Map<String, Map<String, ChildAssociationRef>> removedChildAssocs = this.editableNode.getRemovedChildAssociations();
for (Map<String, ChildAssociationRef> typedAssoc : removedChildAssocs.values())
{
for (ChildAssociationRef assoc : typedAssoc.values())
{
this.getNodeService().removeChild(assoc.getParentRef(), assoc.getChildRef());
}
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// reset the document held by the browse bean as it's just been updated
this.browseBean.getDocument().reset();
return outcome;
}
/**
* Formats the error message to display if an error occurs during finish processing
*
* @param exception The exception
* @return The formatted message
*/
@Override
protected String formatErrorMessage(Throwable exception)
{
if(editableNode != null)
{
// special case for Mimetype - since this is a sub-property of the ContentData object
// we must extract it so it can be edited in the client, then we check for it later
// and create a new ContentData object to wrap it and it's associated URL
ContentData content = (ContentData)this.editableNode.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
this.editableNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype());
this.editableNode.getProperties().put(TEMP_PROP_ENCODING, content.getEncoding());
}
}
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else if (exception instanceof InvalidNodeRefException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF),
new Object[] {this.browseBean.getDocument().getId()});
}
else
{
return super.formatErrorMessage(exception);
}
}
@Override
protected String getErrorOutcome(Throwable exception)
{
if (exception instanceof InvalidNodeRefException)
{
// this failure means the node no longer exists - we cannot show
// the content properties screen again so go back to the main page
return "browse";
}
else
{
return super.getErrorOutcome(exception);
}
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* Returns the node being edited
*
* @return The node being edited
*/
public Node getEditableNode()
{
return this.editableNode;
}
}
package org.alfresco.web.bean.content;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
/**
* Bean implementation of the "Edit Content Properties" dialog.
*
* @author gavinc
*/
public class EditContentPropertiesDialog extends BaseDialogBean
{
private static final long serialVersionUID = -5681296528149487178L;
protected static final String TEMP_PROP_MIMETYPE = "mimetype";
protected static final String TEMP_PROP_ENCODING = "encoding";
protected Node editableNode;
// ------------------------------------------------------------------------------
// Dialog implementation
@Override
public void init(Map<String, String> parameters)
{
super.init(parameters);
// setup the editable node
this.editableNode = initEditableNode();
if(editableNode != null)
{
// special case for Mimetype - since this is a sub-property of the ContentData object
// we must extract it so it can be edited in the client, then we check for it later
// and create a new ContentData object to wrap it and it's associated URL
ContentData content = (ContentData)this.editableNode.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
this.editableNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype());
this.editableNode.getProperties().put(TEMP_PROP_ENCODING, content.getEncoding());
}
}
}
/**
* Init the editable Node
*/
protected Node initEditableNode()
{
final Node document = this.browseBean.getDocument();
if (document != null)
{
return new Node(document.getNodeRef());
}
return null;
}
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
NodeRef nodeRef = this.editableNode.getNodeRef();
Map<String, Object> editedProps = this.editableNode.getProperties();
// get the name and move the node as necessary
String name = (String) editedProps.get(ContentModel.PROP_NAME);
if (name != null)
{
getFileFolderService().rename(nodeRef, name);
}
// we need to put all the properties from the editable bag back into
// the format expected by the repository
Map<QName, Serializable> repoProps = this.getNodeService().getProperties(nodeRef);
// Extract and deal with the special mimetype property for ContentData
String mimetype = (String) editedProps.get(TEMP_PROP_MIMETYPE);
if (mimetype != null)
{
// remove temporary prop from list so it isn't saved with the others
editedProps.remove(TEMP_PROP_MIMETYPE);
ContentData contentData = (ContentData)editedProps.get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentData = ContentData.setMimetype(contentData, mimetype);
editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData);
}
}
// Extract and deal with the special encoding property for ContentData
String encoding = (String) editedProps.get(TEMP_PROP_ENCODING);
if (encoding != null)
{
// remove temporary prop from list so it isn't saved with the others
editedProps.remove(TEMP_PROP_ENCODING);
ContentData contentData = (ContentData) editedProps.get(ContentModel.PROP_CONTENT);
if (contentData != null)
{
contentData = ContentData.setEncoding(contentData, encoding);
editedProps.put(ContentModel.PROP_CONTENT.toString(), contentData);
}
}
// add the "author" aspect if required, properties will get set below
if (this.getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_AUTHOR) == false)
{
this.getNodeService().addAspect(nodeRef, ContentModel.ASPECT_AUTHOR, null);
}
// add the "titled" aspect if required, properties will get set below
if (this.getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_TITLED) == false)
{
getNodeService().addAspect(nodeRef, ContentModel.ASPECT_TITLED, null);
}
// add the remaining properties
Iterator<String> iterProps = editedProps.keySet().iterator();
while (iterProps.hasNext())
{
String propName = iterProps.next();
QName qname = QName.createQName(propName);
// make sure the property is represented correctly
Serializable propValue = (Serializable)editedProps.get(propName);
// check for empty strings when using number types, set to null in this case
if (propValue instanceof String)
{
PropertyDefinition propDef = this.getDictionaryService().getProperty(qname);
if (((String)propValue).length() == 0)
{
if (propDef != null)
{
if (propDef.getDataType().getName().equals(DataTypeDefinition.DOUBLE) ||
propDef.getDataType().getName().equals(DataTypeDefinition.FLOAT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.INT) ||
propDef.getDataType().getName().equals(DataTypeDefinition.LONG))
{
propValue = null;
}
}
}
// handle locale strings to Locale objects
else if (propDef != null && propDef.getDataType().getName().equals(DataTypeDefinition.LOCALE))
{
propValue = I18NUtil.parseLocale((String)propValue);
}
}
repoProps.put(qname, propValue);
}
// send the properties back to the repository
this.getNodeService().setProperties(nodeRef, repoProps);
// we also need to persist any association changes that may have been made
// add any associations added in the UI
Map<String, Map<String, AssociationRef>> addedAssocs = this.editableNode.getAddedAssociations();
for (Map<String, AssociationRef> typedAssoc : addedAssocs.values())
{
for (AssociationRef assoc : typedAssoc.values())
{
this.getNodeService().createAssociation(assoc.getSourceRef(), assoc.getTargetRef(), assoc.getTypeQName());
}
}
// remove any association removed in the UI
Map<String, Map<String, AssociationRef>> removedAssocs = this.editableNode.getRemovedAssociations();
for (Map<String, AssociationRef> typedAssoc : removedAssocs.values())
{
for (AssociationRef assoc : typedAssoc.values())
{
this.getNodeService().removeAssociation(assoc.getSourceRef(), assoc.getTargetRef(), assoc.getTypeQName());
}
}
// add any child associations added in the UI
Map<String, Map<String, ChildAssociationRef>> addedChildAssocs = this.editableNode.getAddedChildAssociations();
for (Map<String, ChildAssociationRef> typedAssoc : addedChildAssocs.values())
{
for (ChildAssociationRef assoc : typedAssoc.values())
{
this.getNodeService().addChild(assoc.getParentRef(), assoc.getChildRef(), assoc.getTypeQName(), assoc.getTypeQName());
}
}
// remove any child association removed in the UI
Map<String, Map<String, ChildAssociationRef>> removedChildAssocs = this.editableNode.getRemovedChildAssociations();
for (Map<String, ChildAssociationRef> typedAssoc : removedChildAssocs.values())
{
for (ChildAssociationRef assoc : typedAssoc.values())
{
this.getNodeService().removeChild(assoc.getParentRef(), assoc.getChildRef());
}
}
return outcome;
}
@Override
protected String doPostCommitProcessing(FacesContext context, String outcome)
{
// reset the document held by the browse bean as it's just been updated
this.browseBean.getDocument().reset();
return outcome;
}
/**
* Formats the error message to display if an error occurs during finish processing
*
* @param exception The exception
* @return The formatted message
*/
@Override
protected String formatErrorMessage(Throwable exception)
{
if(editableNode != null)
{
// special case for Mimetype - since this is a sub-property of the ContentData object
// we must extract it so it can be edited in the client, then we check for it later
// and create a new ContentData object to wrap it and it's associated URL
ContentData content = (ContentData)this.editableNode.getProperties().get(ContentModel.PROP_CONTENT);
if (content != null)
{
this.editableNode.getProperties().put(TEMP_PROP_MIMETYPE, content.getMimetype());
this.editableNode.getProperties().put(TEMP_PROP_ENCODING, content.getEncoding());
}
}
if (exception instanceof FileExistsException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_EXISTS),
((FileExistsException)exception).getName());
}
else if (exception instanceof InvalidNodeRefException)
{
return MessageFormat.format(Application.getMessage(
FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF),
new Object[] {this.browseBean.getDocument().getId()});
}
else
{
return super.formatErrorMessage(exception);
}
}
@Override
protected String getErrorOutcome(Throwable exception)
{
if (exception instanceof InvalidNodeRefException)
{
// this failure means the node no longer exists - we cannot show
// the content properties screen again so go back to the main page
return "browse";
}
else
{
return super.getErrorOutcome(exception);
}
}
@Override
public boolean getFinishButtonDisabled()
{
return false;
}
// ------------------------------------------------------------------------------
// Bean getters and setters
/**
* Returns the node being edited
*
* @return The node being edited
*/
public Node getEditableNode()
{
return this.editableNode;
}
}

View File

@@ -1,160 +1,160 @@
package org.alfresco.web.bean.content;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.actions.handlers.SimpleWorkflowHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
public class EditSimpleWorkflowDialog extends BaseDialogBean
{
private static final long serialVersionUID = 7203447561571625990L;
private static final String MSG_ERROR_UPDATE_SIMPLEWORKFLOW = "error_update_simpleworkflow";
protected Map<String, Serializable> workflowProperties;
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
saveWorkflow();
return outcome;
}
public boolean getFinishButtonDisabled()
{
return false;
}
public Node getNode()
{
return this.browseBean.getDocument();
}
public Node getDocument()
{
return this.getNode();
}
public String saveWorkflow()
{
String outcome = "cancel";
try
{
Map<QName, Serializable> updateProps = getNodeService().getProperties(getNode().getNodeRef());
// update the simple workflow properties
// set the approve step name
updateProps.put(ApplicationModel.PROP_APPROVE_STEP, workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_STEP_NAME));
// specify whether the approve step will copy or move the content
boolean approveMove = true;
String approveAction = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_ACTION);
if (approveAction != null && approveAction.equals("copy"))
{
approveMove = false;
}
updateProps.put(ApplicationModel.PROP_APPROVE_MOVE, Boolean.valueOf(approveMove));
// create node ref representation of the destination folder
updateProps.put(ApplicationModel.PROP_APPROVE_FOLDER, workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_FOLDER));
// determine whether there should be a reject step
boolean requireReject = true;
String rejectStepPresent = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT);
if (rejectStepPresent != null && rejectStepPresent.equals("no"))
{
requireReject = false;
}
if (requireReject)
{
// set the reject step name
updateProps.put(ApplicationModel.PROP_REJECT_STEP, workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_STEP_NAME));
// specify whether the reject step will copy or move the content
boolean rejectMove = true;
String rejectAction = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_ACTION);
if (rejectAction != null && rejectAction.equals("copy"))
{
rejectMove = false;
}
updateProps.put(ApplicationModel.PROP_REJECT_MOVE, Boolean.valueOf(rejectMove));
// create node ref representation of the destination folder
updateProps.put(ApplicationModel.PROP_REJECT_FOLDER, workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_FOLDER));
}
else
{
// set all the reject properties to null to signify there should
// be no reject step
updateProps.put(ApplicationModel.PROP_REJECT_STEP, null);
updateProps.put(ApplicationModel.PROP_REJECT_MOVE, null);
updateProps.put(ApplicationModel.PROP_REJECT_FOLDER, null);
}
// set the properties on the node
getNodeService().setProperties(getNode().getNodeRef(), updateProps);
getNode().reset();
}
catch (Throwable e)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE_SIMPLEWORKFLOW), e.getMessage()), e);
ReportedException.throwIfNecessary(e);
}
return outcome;
}
public Map<String, Serializable> getWorkflowProperties()
{
if (this.workflowProperties == null && getNode().hasAspect(ApplicationModel.ASPECT_SIMPLE_WORKFLOW))
{
// get the exisiting properties for the node
Map<String, Object> props = getNode().getProperties();
String approveStepName = (String) props.get(ApplicationModel.PROP_APPROVE_STEP.toString());
String rejectStepName = (String) props.get(ApplicationModel.PROP_REJECT_STEP.toString());
Boolean approveMove = (Boolean) props.get(ApplicationModel.PROP_APPROVE_MOVE.toString());
Boolean rejectMove = (Boolean) props.get(ApplicationModel.PROP_REJECT_MOVE.toString());
NodeRef approveFolder = (NodeRef) props.get(ApplicationModel.PROP_APPROVE_FOLDER.toString());
NodeRef rejectFolder = (NodeRef) props.get(ApplicationModel.PROP_REJECT_FOLDER.toString());
// put the workflow properties in a separate map for use by the JSP
this.workflowProperties = new HashMap<String, Serializable>(7);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_STEP_NAME, approveStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_ACTION, approveMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_FOLDER, approveFolder);
if (rejectStepName == null || rejectMove == null || rejectFolder == null)
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT, "no");
}
else
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT, "yes");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_NAME, rejectStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_ACTION, rejectMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_FOLDER, rejectFolder);
}
}
return this.workflowProperties;
}
}
package org.alfresco.web.bean.content;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.alfresco.model.ApplicationModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.actions.handlers.SimpleWorkflowHandler;
import org.alfresco.web.bean.dialog.BaseDialogBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.ui.common.ReportedException;
import org.alfresco.web.ui.common.Utils;
public class EditSimpleWorkflowDialog extends BaseDialogBean
{
private static final long serialVersionUID = 7203447561571625990L;
private static final String MSG_ERROR_UPDATE_SIMPLEWORKFLOW = "error_update_simpleworkflow";
protected Map<String, Serializable> workflowProperties;
@Override
protected String finishImpl(FacesContext context, String outcome) throws Exception
{
saveWorkflow();
return outcome;
}
public boolean getFinishButtonDisabled()
{
return false;
}
public Node getNode()
{
return this.browseBean.getDocument();
}
public Node getDocument()
{
return this.getNode();
}
public String saveWorkflow()
{
String outcome = "cancel";
try
{
Map<QName, Serializable> updateProps = getNodeService().getProperties(getNode().getNodeRef());
// update the simple workflow properties
// set the approve step name
updateProps.put(ApplicationModel.PROP_APPROVE_STEP, workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_STEP_NAME));
// specify whether the approve step will copy or move the content
boolean approveMove = true;
String approveAction = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_ACTION);
if (approveAction != null && approveAction.equals("copy"))
{
approveMove = false;
}
updateProps.put(ApplicationModel.PROP_APPROVE_MOVE, Boolean.valueOf(approveMove));
// create node ref representation of the destination folder
updateProps.put(ApplicationModel.PROP_APPROVE_FOLDER, workflowProperties.get(SimpleWorkflowHandler.PROP_APPROVE_FOLDER));
// determine whether there should be a reject step
boolean requireReject = true;
String rejectStepPresent = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT);
if (rejectStepPresent != null && rejectStepPresent.equals("no"))
{
requireReject = false;
}
if (requireReject)
{
// set the reject step name
updateProps.put(ApplicationModel.PROP_REJECT_STEP, workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_STEP_NAME));
// specify whether the reject step will copy or move the content
boolean rejectMove = true;
String rejectAction = (String) workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_ACTION);
if (rejectAction != null && rejectAction.equals("copy"))
{
rejectMove = false;
}
updateProps.put(ApplicationModel.PROP_REJECT_MOVE, Boolean.valueOf(rejectMove));
// create node ref representation of the destination folder
updateProps.put(ApplicationModel.PROP_REJECT_FOLDER, workflowProperties.get(SimpleWorkflowHandler.PROP_REJECT_FOLDER));
}
else
{
// set all the reject properties to null to signify there should
// be no reject step
updateProps.put(ApplicationModel.PROP_REJECT_STEP, null);
updateProps.put(ApplicationModel.PROP_REJECT_MOVE, null);
updateProps.put(ApplicationModel.PROP_REJECT_FOLDER, null);
}
// set the properties on the node
getNodeService().setProperties(getNode().getNodeRef(), updateProps);
getNode().reset();
}
catch (Throwable e)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE_SIMPLEWORKFLOW), e.getMessage()), e);
ReportedException.throwIfNecessary(e);
}
return outcome;
}
public Map<String, Serializable> getWorkflowProperties()
{
if (this.workflowProperties == null && getNode().hasAspect(ApplicationModel.ASPECT_SIMPLE_WORKFLOW))
{
// get the exisiting properties for the node
Map<String, Object> props = getNode().getProperties();
String approveStepName = (String) props.get(ApplicationModel.PROP_APPROVE_STEP.toString());
String rejectStepName = (String) props.get(ApplicationModel.PROP_REJECT_STEP.toString());
Boolean approveMove = (Boolean) props.get(ApplicationModel.PROP_APPROVE_MOVE.toString());
Boolean rejectMove = (Boolean) props.get(ApplicationModel.PROP_REJECT_MOVE.toString());
NodeRef approveFolder = (NodeRef) props.get(ApplicationModel.PROP_APPROVE_FOLDER.toString());
NodeRef rejectFolder = (NodeRef) props.get(ApplicationModel.PROP_REJECT_FOLDER.toString());
// put the workflow properties in a separate map for use by the JSP
this.workflowProperties = new HashMap<String, Serializable>(7);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_STEP_NAME, approveStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_ACTION, approveMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_APPROVE_FOLDER, approveFolder);
if (rejectStepName == null || rejectMove == null || rejectFolder == null)
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT, "no");
}
else
{
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_PRESENT, "yes");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_STEP_NAME, rejectStepName);
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_ACTION, rejectMove ? "move" : "copy");
this.workflowProperties.put(SimpleWorkflowHandler.PROP_REJECT_FOLDER, rejectFolder);
}
}
return this.workflowProperties;
}
}

View File

@@ -1,43 +1,43 @@
package org.alfresco.web.bean.content;
import java.util.Set;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.wizard.BaseInviteUsersWizard;
/**
* Concrete implementation providing the ability to invite users to content.
*
* @author gavinc
*/
public class InviteContentUsersWizard extends BaseInviteUsersWizard
{
private static final long serialVersionUID = 9198783146031469545L;
@Override
protected Set<String> getPermissionsForType()
{
// Let the permission service do the caching to allow for dynamic model updates, etc.
return this.permissionService.getSettablePermissions(getNode().getType());
}
@Override
protected Node getNode()
{
return this.browseBean.getDocument();
}
@Override
protected String getEmailTemplateXPath()
{
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "/" +
Application.getNotifyEmailTemplatesFolderName(fc) + "//*";
return xpath;
}
}
package org.alfresco.web.bean.content;
import java.util.Set;
import javax.faces.context.FacesContext;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.wizard.BaseInviteUsersWizard;
/**
* Concrete implementation providing the ability to invite users to content.
*
* @author gavinc
*/
public class InviteContentUsersWizard extends BaseInviteUsersWizard
{
private static final long serialVersionUID = 9198783146031469545L;
@Override
protected Set<String> getPermissionsForType()
{
// Let the permission service do the caching to allow for dynamic model updates, etc.
return this.permissionService.getSettablePermissions(getNode().getType());
}
@Override
protected Node getNode()
{
return this.browseBean.getDocument();
}
@Override
protected String getEmailTemplateXPath()
{
FacesContext fc = FacesContext.getCurrentInstance();
String xpath = Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getEmailTemplatesFolderName(fc) + "/" +
Application.getNotifyEmailTemplatesFolderName(fc) + "//*";
return xpath;
}
}

View File

@@ -1,29 +1,29 @@
package org.alfresco.web.bean.content;
import org.alfresco.web.app.AlfrescoNavigationHandler;
/**
* Bean implementation of the "Set Content Properties" dialog.
*
* @author gavinc
*/
public class SetContentPropertiesDialog extends EditContentPropertiesDialog
{
private static final long serialVersionUID = -7705362669371767349L;
@Override
protected String getDefaultCancelOutcome()
{
return super.getDefaultCancelOutcome() +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"browse";
}
@Override
protected String getDefaultFinishOutcome()
{
return super.getDefaultFinishOutcome() +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"browse";
}
}
package org.alfresco.web.bean.content;
import org.alfresco.web.app.AlfrescoNavigationHandler;
/**
* Bean implementation of the "Set Content Properties" dialog.
*
* @author gavinc
*/
public class SetContentPropertiesDialog extends EditContentPropertiesDialog
{
private static final long serialVersionUID = -7705362669371767349L;
@Override
protected String getDefaultCancelOutcome()
{
return super.getDefaultCancelOutcome() +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"browse";
}
@Override
protected String getDefaultFinishOutcome()
{
return super.getDefaultFinishOutcome() +
AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
"browse";
}
}

Some files were not shown because too many files have changed in this diff Show More