mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)
101313: Merge RA-SPRINT2 to HEAD-BUG-FIX (5.1) 99991: RA-85: Move webscript backing bean classes git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@101455 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -20,24 +20,44 @@ package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
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.repository.Path;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.slingshot.web.scripts.NodeBrowserScript;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AccessPermission;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.OwnableService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.springframework.extensions.surf.util.URLEncoder;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
@@ -45,15 +65,341 @@ import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest
|
||||
/**
|
||||
* Admin Console NodeBrowser WebScript POST controller.
|
||||
* <p>
|
||||
* Implements a low-level node browser client for the Admin Console tool. Extends
|
||||
* the slingshot NodeBrowserScript WebScript to share the useful value wrapper classes.
|
||||
* Implements a low-level node browser client for the Admin Console tool.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
* @since 5.1
|
||||
*/
|
||||
public class NodeBrowserPost extends NodeBrowserScript implements Serializable
|
||||
public class NodeBrowserPost extends DeclarativeWebScript implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 8464392337270665212L;
|
||||
|
||||
// stores and node
|
||||
transient private List<StoreRef> stores = null;
|
||||
|
||||
// supporting repository services
|
||||
transient private TransactionService transactionService;
|
||||
transient private NodeService nodeService;
|
||||
transient private DictionaryService dictionaryService;
|
||||
transient private SearchService searchService;
|
||||
transient private NamespaceService namespaceService;
|
||||
transient private PermissionService permissionService;
|
||||
transient private OwnableService ownableService;
|
||||
|
||||
/**
|
||||
* @param transactionService transaction service
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
protected TransactionService getTransactionService()
|
||||
{
|
||||
return transactionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
protected NodeService getNodeService()
|
||||
{
|
||||
return nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchService search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
protected SearchService getSearchService()
|
||||
{
|
||||
return searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dictionaryService dictionary service
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
protected DictionaryService getDictionaryService()
|
||||
{
|
||||
return dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param namespaceService namespace service
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
protected NamespaceService getNamespaceService()
|
||||
{
|
||||
return this.namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param permissionService permission service
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
protected PermissionService getPermissionService()
|
||||
{
|
||||
return permissionService;
|
||||
}
|
||||
|
||||
public void setOwnableService(OwnableService ownableService)
|
||||
{
|
||||
this.ownableService = ownableService;
|
||||
}
|
||||
|
||||
protected OwnableService getOwnableService()
|
||||
{
|
||||
return ownableService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of repository stores
|
||||
*
|
||||
* @return stores
|
||||
*/
|
||||
public List<StoreRef> getStores()
|
||||
{
|
||||
if (stores == null)
|
||||
{
|
||||
stores = getNodeService().getStores();
|
||||
}
|
||||
return stores;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node type
|
||||
*
|
||||
* @return node type
|
||||
*/
|
||||
public QName getNodeType(NodeRef nodeRef)
|
||||
{
|
||||
return getNodeService().getType(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node primary path
|
||||
*
|
||||
* @return primary path
|
||||
*/
|
||||
public String getPrimaryPath(NodeRef nodeRef)
|
||||
{
|
||||
Path primaryPath = getNodeService().getPath(nodeRef);
|
||||
return ISO9075.decode(primaryPath.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node primary path
|
||||
*
|
||||
* @return primary path
|
||||
*/
|
||||
public String getPrimaryPrefixedPath(NodeRef nodeRef)
|
||||
{
|
||||
Path primaryPath = getNodeService().getPath(nodeRef);
|
||||
return ISO9075.decode(primaryPath.toPrefixString(getNamespaceService()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node primary parent reference
|
||||
*
|
||||
* @return primary parent ref
|
||||
*/
|
||||
public NodeRef getPrimaryParent(NodeRef nodeRef)
|
||||
{
|
||||
Path primaryPath = getNodeService().getPath(nodeRef);
|
||||
Path.Element element = primaryPath.last();
|
||||
NodeRef parentRef = ((Path.ChildAssocElement) element).getRef().getParentRef();
|
||||
return parentRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node aspects
|
||||
*
|
||||
* @return node aspects
|
||||
*/
|
||||
public List<Aspect> getAspects(NodeRef nodeRef)
|
||||
{
|
||||
Set<QName> qnames = getNodeService().getAspects(nodeRef);
|
||||
List<Aspect> aspects = new ArrayList<Aspect>(qnames.size());
|
||||
for (QName qname : qnames)
|
||||
{
|
||||
aspects.add(new Aspect(qname));
|
||||
}
|
||||
return aspects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node parents
|
||||
*
|
||||
* @return node parents
|
||||
*/
|
||||
public List<ChildAssociation> getParents(NodeRef nodeRef)
|
||||
{
|
||||
List<ChildAssociationRef> parents = getNodeService().getParentAssocs(nodeRef);
|
||||
List<ChildAssociation> assocs = new ArrayList<ChildAssociation>(parents.size());
|
||||
for (ChildAssociationRef ref : parents)
|
||||
{
|
||||
assocs.add(new ChildAssociation(ref));
|
||||
}
|
||||
return assocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node properties
|
||||
*
|
||||
* @return properties
|
||||
*/
|
||||
public List<Property> getProperties(NodeRef nodeRef)
|
||||
{
|
||||
Map<QName, Serializable> propertyValues = getNodeService().getProperties(nodeRef);
|
||||
List<Property> properties = new ArrayList<Property>(propertyValues.size());
|
||||
for (Map.Entry<QName, Serializable> property : propertyValues.entrySet())
|
||||
{
|
||||
properties.add(new Property(property.getKey(), property.getValue()));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the current node inherits its permissions from a parent node
|
||||
*
|
||||
* @return true => inherits permissions
|
||||
*/
|
||||
public boolean getInheritPermissions(NodeRef nodeRef)
|
||||
{
|
||||
Boolean inheritPermissions = this.getPermissionService().getInheritParentPermissions(nodeRef);
|
||||
return inheritPermissions.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node permissions
|
||||
*
|
||||
* @return the permissions
|
||||
*/
|
||||
public List<Permission> getPermissions(NodeRef nodeRef)
|
||||
{
|
||||
List<Permission> permissions = null;
|
||||
AccessStatus readPermissions = this.getPermissionService().hasPermission(nodeRef, PermissionService.READ_PERMISSIONS);
|
||||
if (readPermissions.equals(AccessStatus.ALLOWED))
|
||||
{
|
||||
List<Permission> nodePermissions = new ArrayList<Permission>();
|
||||
for (Iterator<AccessPermission> iterator = getPermissionService().getAllSetPermissions(nodeRef).iterator(); iterator
|
||||
.hasNext();)
|
||||
{
|
||||
AccessPermission ap = iterator.next();
|
||||
nodePermissions.add(new Permission(ap.getPermission(), ap.getAuthority(), ap.getAccessStatus().toString()));
|
||||
}
|
||||
permissions = nodePermissions;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Permission> noReadPermissions = new ArrayList<Permission>(1);
|
||||
noReadPermissions.add(new NoReadPermissionGranted());
|
||||
permissions = noReadPermissions;
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node permissions
|
||||
*
|
||||
* @return the permissions
|
||||
*/
|
||||
public List<Permission> getStorePermissionMasks(NodeRef nodeRef)
|
||||
{
|
||||
List<Permission> permissionMasks = new ArrayList<Permission>(1);
|
||||
permissionMasks.add(new NoStoreMask());
|
||||
return permissionMasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node children
|
||||
*
|
||||
* @return node children
|
||||
*/
|
||||
public List<ChildAssociation> getChildren(NodeRef nodeRef)
|
||||
{
|
||||
List<ChildAssociationRef> refs = getNodeService().getChildAssocs(nodeRef);
|
||||
List<ChildAssociation> assocs = new ArrayList<ChildAssociation>(refs.size());
|
||||
for (ChildAssociationRef ref : refs)
|
||||
{
|
||||
assocs.add(new ChildAssociation(ref));
|
||||
}
|
||||
return assocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current node associations
|
||||
*
|
||||
* @return associations
|
||||
*/
|
||||
public List<PeerAssociation> getAssocs(NodeRef nodeRef)
|
||||
{
|
||||
List<AssociationRef> refs = null;
|
||||
try
|
||||
{
|
||||
refs = getNodeService().getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
}
|
||||
catch (UnsupportedOperationException err)
|
||||
{
|
||||
// some stores do not support associations
|
||||
// but we doesn't want NPE in code below
|
||||
refs = new ArrayList<AssociationRef>();
|
||||
}
|
||||
List<PeerAssociation> assocs = new ArrayList<PeerAssociation>(refs.size());
|
||||
for (AssociationRef ref : refs)
|
||||
{
|
||||
assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef()));
|
||||
}
|
||||
return assocs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current source associations
|
||||
*
|
||||
* @return associations
|
||||
*/
|
||||
public List<PeerAssociation> getSourceAssocs(NodeRef nodeRef)
|
||||
{
|
||||
List<AssociationRef> refs = null;
|
||||
try
|
||||
{
|
||||
refs = getNodeService().getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL);
|
||||
}
|
||||
catch (UnsupportedOperationException err)
|
||||
{
|
||||
// some stores do not support associations
|
||||
// but we doesn't want NPE in code below
|
||||
refs = new ArrayList<AssociationRef>();
|
||||
}
|
||||
List<PeerAssociation> assocs = new ArrayList<PeerAssociation>(refs.size());
|
||||
for (AssociationRef ref : refs)
|
||||
{
|
||||
assocs.add(new PeerAssociation(ref.getTypeQName(), ref.getSourceRef(), ref.getTargetRef()));
|
||||
}
|
||||
return assocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
@@ -274,6 +620,228 @@ public class NodeBrowserPost extends NodeBrowserScript implements Serializable
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Node wrapper class
|
||||
*/
|
||||
public class Node implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 12608347204513848L;
|
||||
|
||||
private String qnamePath;
|
||||
|
||||
private String prefixedQNamePath;
|
||||
|
||||
private NodeRef nodeRef;
|
||||
|
||||
private NodeRef parentNodeRef;
|
||||
|
||||
private QNameBean childAssoc;
|
||||
|
||||
private QNameBean type;
|
||||
|
||||
public Node(NodeRef nodeRef)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
Path path = getNodeService().getPath(nodeRef);
|
||||
this.qnamePath = path.toString();
|
||||
this.prefixedQNamePath = path.toPrefixString(getNamespaceService());
|
||||
this.parentNodeRef = getPrimaryParent(nodeRef);
|
||||
ChildAssociationRef ref = getNodeService().getPrimaryParent(nodeRef);
|
||||
this.childAssoc = ref.getQName() != null ? new QNameBean(ref.getQName()) : null;
|
||||
this.type = new QNameBean(getNodeService().getType(nodeRef));
|
||||
}
|
||||
|
||||
public String getQnamePath()
|
||||
{
|
||||
return qnamePath;
|
||||
}
|
||||
|
||||
public String getPrefixedQNamePath()
|
||||
{
|
||||
return prefixedQNamePath;
|
||||
}
|
||||
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return nodeRef.getId();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return childAssoc != null ? childAssoc.getName() : "";
|
||||
}
|
||||
|
||||
public String getPrefixedName()
|
||||
{
|
||||
return childAssoc != null ? childAssoc.getPrefixedName() : "";
|
||||
}
|
||||
|
||||
public QNameBean getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setNodeRef(NodeRef nodeRef)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
}
|
||||
|
||||
public NodeRef getParentNodeRef()
|
||||
{
|
||||
return parentNodeRef;
|
||||
}
|
||||
|
||||
public void setParentNodeRef(NodeRef parentNodeRef)
|
||||
{
|
||||
this.parentNodeRef = parentNodeRef;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Qname wrapper class
|
||||
*/
|
||||
public class QNameBean implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 6982292337846270774L;
|
||||
|
||||
protected QName name;
|
||||
private String prefixString = null;
|
||||
|
||||
public QNameBean(QName name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
public String getPrefixedName()
|
||||
{
|
||||
try
|
||||
{
|
||||
return prefixString != null ? prefixString : (prefixString = name.toPrefixString(getNamespaceService()));
|
||||
}
|
||||
catch(NamespaceException e)
|
||||
{
|
||||
return name.getLocalName();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aspect wrapper class
|
||||
*/
|
||||
public class Aspect extends QNameBean implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -6448182941386934326L;
|
||||
|
||||
public Aspect(QName name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Association wrapper class
|
||||
*/
|
||||
public class Association implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1078430803027004L;
|
||||
|
||||
protected QNameBean name;
|
||||
protected QNameBean typeName;
|
||||
|
||||
public Association(QName name, QName typeName)
|
||||
{
|
||||
this.name = name != null ? new QNameBean(name) : null;
|
||||
this.typeName = new QNameBean(typeName);
|
||||
}
|
||||
|
||||
public QNameBean getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public QNameBean getTypeName()
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Child assoc wrapper class
|
||||
*/
|
||||
public class ChildAssociation extends Association implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -52439282250891063L;
|
||||
|
||||
protected NodeRef childRef;
|
||||
protected NodeRef parentRef;
|
||||
protected QNameBean childType;
|
||||
protected QNameBean parentType;
|
||||
protected boolean primary;
|
||||
|
||||
// from Association
|
||||
protected QNameBean name;
|
||||
protected QNameBean typeName;
|
||||
|
||||
public ChildAssociation(ChildAssociationRef ref)
|
||||
{
|
||||
super(ref.getQName() != null ? ref.getQName() : null,
|
||||
ref.getTypeQName() != null ? ref.getTypeQName() : null);
|
||||
|
||||
this.childRef = ref.getChildRef();
|
||||
this.parentRef = ref.getParentRef(); // could be null
|
||||
if (childRef != null)
|
||||
this.childType = new QNameBean(getNodeType(childRef));
|
||||
if (parentRef != null)
|
||||
this.parentType = new QNameBean(getNodeType(parentRef));
|
||||
this.primary = ref.isPrimary();
|
||||
}
|
||||
|
||||
public NodeRef getChildRef()
|
||||
{
|
||||
return childRef;
|
||||
}
|
||||
|
||||
public QNameBean getChildTypeName()
|
||||
{
|
||||
return childType;
|
||||
}
|
||||
|
||||
public NodeRef getParentRef()
|
||||
{
|
||||
return parentRef;
|
||||
}
|
||||
|
||||
public QNameBean getParentTypeName()
|
||||
{
|
||||
return parentType;
|
||||
}
|
||||
|
||||
public boolean isPrimary()
|
||||
{
|
||||
return primary;
|
||||
}
|
||||
|
||||
public boolean getPrimary()
|
||||
{
|
||||
return this.isPrimary();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to resolve Assoc Type and QName to short form with resolved prefix
|
||||
*/
|
||||
@@ -317,4 +885,323 @@ public class NodeBrowserPost extends NodeBrowserScript implements Serializable
|
||||
return ref.isPrimary();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Peer assoc wrapper class
|
||||
*/
|
||||
public class PeerAssociation extends Association implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 4833278311416507L;
|
||||
|
||||
protected NodeRef sourceRef;
|
||||
protected NodeRef targetRef;
|
||||
protected QNameBean sourceType;
|
||||
protected QNameBean targetType;
|
||||
|
||||
// from Association
|
||||
protected QNameBean name;
|
||||
protected QNameBean typeName;
|
||||
|
||||
public PeerAssociation(QName typeName, NodeRef sourceRef, NodeRef targetRef)
|
||||
{
|
||||
super(null, typeName);
|
||||
|
||||
this.sourceRef = sourceRef;
|
||||
this.targetRef = targetRef;
|
||||
if (sourceRef != null)
|
||||
this.sourceType = new QNameBean(getNodeType(sourceRef));
|
||||
if (targetRef != null)
|
||||
this.targetType = new QNameBean(getNodeType(targetRef));
|
||||
}
|
||||
|
||||
public NodeRef getSourceRef()
|
||||
{
|
||||
return sourceRef;
|
||||
}
|
||||
|
||||
public QNameBean getSourceTypeName()
|
||||
{
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
public NodeRef getTargetRef()
|
||||
{
|
||||
return targetRef;
|
||||
}
|
||||
|
||||
public QNameBean getTargetTypeName()
|
||||
{
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Property wrapper class
|
||||
*/
|
||||
public class Property implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 7755924782250077L;
|
||||
|
||||
private QNameBean name;
|
||||
|
||||
private boolean isCollection = false;
|
||||
|
||||
private List<Value> values;
|
||||
|
||||
private boolean residual;
|
||||
|
||||
private QNameBean typeName;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param name property name
|
||||
* @param value property values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Property(QName qname, Serializable value)
|
||||
{
|
||||
this.name = new QNameBean(qname);
|
||||
|
||||
PropertyDefinition propDef = getDictionaryService().getProperty(qname);
|
||||
if (propDef != null)
|
||||
{
|
||||
QName qn = propDef.getDataType().getName();
|
||||
typeName = qn != null ? new QNameBean(propDef.getDataType().getName()) : null;
|
||||
residual = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
residual = true;
|
||||
}
|
||||
|
||||
// handle multi/single values
|
||||
final List<Value> values;
|
||||
if (value instanceof Collection)
|
||||
{
|
||||
Collection<Serializable> oldValues = (Collection<Serializable>) value;
|
||||
values = new ArrayList<Value>(oldValues.size());
|
||||
isCollection = true;
|
||||
for (Serializable multiValue : oldValues)
|
||||
{
|
||||
values.add(new Value(multiValue instanceof QName ? new QNameBean((QName) multiValue) : multiValue));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
values = Collections.singletonList(new Value(value instanceof QName ? new QNameBean((QName) value) : value));
|
||||
}
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property name
|
||||
*
|
||||
* @return name
|
||||
*/
|
||||
public QNameBean getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public QNameBean getTypeName()
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefixed property name
|
||||
*
|
||||
* @return prefixed name
|
||||
*/
|
||||
public String getPrefixedName()
|
||||
{
|
||||
return name.getPrefixedName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property value
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public List<Value> getValues()
|
||||
{
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the property is residual
|
||||
*
|
||||
* @return true => property is not defined in dictionary
|
||||
*/
|
||||
public boolean getResidual()
|
||||
{
|
||||
return residual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the property is of ANY type
|
||||
*
|
||||
* @return true => is any
|
||||
*/
|
||||
public boolean isAny()
|
||||
{
|
||||
return (getTypeName() == null) ? false : getTypeName().getName().equals(DataTypeDefinition.ANY.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the property is a collection
|
||||
*
|
||||
* @return true => is collection
|
||||
*/
|
||||
public boolean isCollection()
|
||||
{
|
||||
return isCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value wrapper
|
||||
*/
|
||||
public class Value implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 47235536691732705L;
|
||||
|
||||
private Serializable value;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param value value
|
||||
*/
|
||||
public Value(Serializable value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public Serializable getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value datatype
|
||||
*
|
||||
* @return the value datatype
|
||||
*/
|
||||
public String getDataType()
|
||||
{
|
||||
String datatype = null;
|
||||
if (Property.this.getTypeName() != null)
|
||||
{
|
||||
datatype = Property.this.getTypeName().getName();
|
||||
}
|
||||
if (datatype == null || datatype.equals(DataTypeDefinition.ANY.toString()))
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
DataTypeDefinition dataTypeDefinition = getDictionaryService().getDataType(value.getClass());
|
||||
if (dataTypeDefinition != null)
|
||||
{
|
||||
datatype = getDictionaryService().getDataType(value.getClass()).getName().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return datatype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the value is content
|
||||
*
|
||||
* @return true => is content
|
||||
*/
|
||||
public boolean isContent()
|
||||
{
|
||||
String datatype = getDataType();
|
||||
return (datatype == null) ? false : datatype.equals(DataTypeDefinition.CONTENT.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the value is a node ref
|
||||
*
|
||||
* @return true => is node ref
|
||||
*/
|
||||
public boolean isNodeRef()
|
||||
{
|
||||
String datatype = getDataType();
|
||||
return (datatype == null) ? false : datatype.equals(DataTypeDefinition.NODE_REF.toString()) || datatype.equals(DataTypeDefinition.CATEGORY.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the value is null
|
||||
*
|
||||
* @return true => value is null
|
||||
*/
|
||||
public boolean isNullValue()
|
||||
{
|
||||
return value == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission bean
|
||||
*/
|
||||
public static class Permission implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1235536691732705L;
|
||||
|
||||
private final String permission;
|
||||
private final String authority;
|
||||
private final String accessStatus;
|
||||
|
||||
public Permission(String permission, String authority, String accessStatus)
|
||||
{
|
||||
this.permission = permission;
|
||||
this.authority = authority;
|
||||
this.accessStatus = accessStatus;
|
||||
}
|
||||
|
||||
public String getPermission()
|
||||
{
|
||||
return permission;
|
||||
}
|
||||
|
||||
public String getAuthority()
|
||||
{
|
||||
return authority;
|
||||
}
|
||||
|
||||
public String getAccessStatus()
|
||||
{
|
||||
return accessStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission representing the fact that "Read Permissions" has not been granted
|
||||
*/
|
||||
public static class NoReadPermissionGranted extends Permission implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1236786691732705L;
|
||||
|
||||
public NoReadPermissionGranted()
|
||||
{
|
||||
super(PermissionService.READ_PERMISSIONS, "[Current Authority]", "Not Granted");
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoStoreMask extends Permission implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 3125536691732705L;
|
||||
|
||||
public NoStoreMask()
|
||||
{
|
||||
super("All <No Mask>", "All", "Allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.datalist;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.DataListModel;
|
||||
import org.alfresco.repo.web.scripts.DeclarativeSpreadsheetWebScript;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
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.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.namespace.InvalidQNameException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Data List Download
|
||||
*
|
||||
* Exports the contents of a Data List as an Excel file
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public class DataListDownloadWebScript extends DeclarativeSpreadsheetWebScript
|
||||
implements InitializingBean
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(DataListDownloadWebScript.class);
|
||||
|
||||
private static final QName DATA_LIST_ITEM_TYPE = DataListModel.PROP_DATALIST_ITEM_TYPE;
|
||||
|
||||
private NodeService nodeService;
|
||||
private SiteService siteService;
|
||||
private NamespaceService namespaceService;
|
||||
private Map<QName,List<QName>> modelOrder;
|
||||
private Map<String,String> rawModelOrder;
|
||||
|
||||
public DataListDownloadWebScript()
|
||||
{
|
||||
this.filenameBase = "DataListExport";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param siteService SiteService
|
||||
*/
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param namespaceService
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
public void setModelOrder(Map<String,String> rawModelOrder)
|
||||
{
|
||||
this.rawModelOrder = rawModelOrder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
modelOrder = new HashMap<QName, List<QName>>();
|
||||
for(String key : rawModelOrder.keySet())
|
||||
{
|
||||
QName model;
|
||||
List<QName> order = new ArrayList<QName>();
|
||||
|
||||
try
|
||||
{
|
||||
model= QName.createQName(key, namespaceService);
|
||||
}
|
||||
catch(InvalidQNameException e)
|
||||
{
|
||||
logger.warn("Skipping invalid model type " + key);
|
||||
continue;
|
||||
}
|
||||
|
||||
StringTokenizer st = new StringTokenizer(rawModelOrder.get(key), ",");
|
||||
while(st.hasMoreTokens())
|
||||
{
|
||||
order.add( QName.createQName(st.nextToken(), namespaceService) );
|
||||
}
|
||||
modelOrder.put(model, order);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify the datalist
|
||||
*/
|
||||
@Override
|
||||
protected Object identifyResource(String format, WebScriptRequest req) {
|
||||
// Try to find the datalist they requested
|
||||
NodeRef list;
|
||||
Map<String,String> args = req.getServiceMatch().getTemplateVars();
|
||||
if(args.get("store_type") != null)
|
||||
{
|
||||
list = new NodeRef(
|
||||
args.get("store_type"),
|
||||
args.get("store_id"),
|
||||
args.get("id")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the site
|
||||
SiteInfo site = siteService.getSite(args.get("site"));
|
||||
if(site == null)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, "Site not found with supplied name");
|
||||
}
|
||||
|
||||
// Now find the data list container with in
|
||||
NodeRef container = nodeService.getChildByName(
|
||||
site.getNodeRef(),
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
args.get("container")
|
||||
);
|
||||
if(container == null)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, "Container not found within site");
|
||||
}
|
||||
|
||||
// Now get the data list itself
|
||||
list = nodeService.getChildByName(
|
||||
container,
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
args.get("list")
|
||||
);
|
||||
}
|
||||
if(list == null || !nodeService.exists(list))
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, "The Data List could not be found");
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't have a HTML version
|
||||
*/
|
||||
@Override
|
||||
protected boolean allowHtmlFallback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the properties, in the requested order, from
|
||||
* the data list definition
|
||||
*/
|
||||
@Override
|
||||
protected List<Pair<QName, Boolean>> buildPropertiesForHeader(
|
||||
Object resource, String format, WebScriptRequest req) {
|
||||
NodeRef list = (NodeRef)resource;
|
||||
QName type = buildType(list);
|
||||
|
||||
// Has the user given us rules for what to do
|
||||
// with this type?
|
||||
List<QName> props;
|
||||
if(modelOrder.containsKey(type))
|
||||
{
|
||||
props = modelOrder.get(type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We'll have to try to guess it for them
|
||||
// For now, just use DataList properties for the type
|
||||
TypeDefinition typeDef = dictionaryService.getType(type);
|
||||
Map<QName, PropertyDefinition> allProps = typeDef.getProperties();
|
||||
props = new ArrayList<QName>();
|
||||
|
||||
for(QName prop : allProps.keySet())
|
||||
{
|
||||
if(NamespaceService.DATALIST_MODEL_1_0_URI.equals(prop.getNamespaceURI()))
|
||||
{
|
||||
props.add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is required
|
||||
List<Pair<QName, Boolean>> properties = new ArrayList<Pair<QName,Boolean>>();
|
||||
for(QName qname : props)
|
||||
{
|
||||
properties.add(new Pair<QName, Boolean>(qname, true));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private QName buildType(NodeRef list)
|
||||
{
|
||||
String typeS = (String)nodeService.getProperty(list, DATA_LIST_ITEM_TYPE);
|
||||
if(! typeS.startsWith(NamespaceService.DATALIST_MODEL_PREFIX + ":"))
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_NOT_IMPLEMENTED, "Unexpected list type " + typeS);
|
||||
}
|
||||
QName type = QName.createQName(NamespaceService.DATALIST_MODEL_1_0_URI, typeS.substring(typeS.indexOf(':')+1));
|
||||
return type;
|
||||
}
|
||||
|
||||
private List<NodeRef> getItems(NodeRef list)
|
||||
{
|
||||
Set<QName> typeSet = new HashSet<QName>(Arrays.asList(new QName[] { buildType(list) }));
|
||||
|
||||
List<NodeRef> items = new ArrayList<NodeRef>();
|
||||
for(ChildAssociationRef ca : nodeService.getChildAssocs(list, typeSet))
|
||||
{
|
||||
items.add(ca.getChildRef());
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateBody(Object resource, CSVPrinter csv,
|
||||
List<QName> properties) throws IOException {
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "CSV not currently supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateBody(Object resource, Workbook workbook,
|
||||
Sheet sheet, List<QName> properties) throws IOException {
|
||||
NodeRef list = (NodeRef)resource;
|
||||
List<NodeRef> items = getItems(list);
|
||||
|
||||
// Our various formats
|
||||
DataFormat formatter = workbook.createDataFormat();
|
||||
|
||||
CellStyle styleInt = workbook.createCellStyle();
|
||||
styleInt.setDataFormat( formatter.getFormat("0") );
|
||||
CellStyle styleDate = workbook.createCellStyle();
|
||||
styleDate.setDataFormat( formatter.getFormat("yyyy-mm-dd") );
|
||||
CellStyle styleDouble = workbook.createCellStyle();
|
||||
styleDouble.setDataFormat( formatter.getFormat("General") );
|
||||
CellStyle styleNewLines = workbook.createCellStyle();
|
||||
styleNewLines.setWrapText(true);
|
||||
|
||||
// Export the items
|
||||
int rowNum = 1, colNum = 0;
|
||||
for(NodeRef item : items)
|
||||
{
|
||||
Row r = sheet.createRow(rowNum);
|
||||
|
||||
colNum = 0;
|
||||
for(QName prop : properties)
|
||||
{
|
||||
Cell c = r.createCell(colNum);
|
||||
|
||||
Serializable val = nodeService.getProperty(item, prop);
|
||||
if(val == null)
|
||||
{
|
||||
// Is it an association, or just missing?
|
||||
List<AssociationRef> assocs = nodeService.getTargetAssocs(item, prop);
|
||||
if(assocs.size() > 0)
|
||||
{
|
||||
StringBuffer text = new StringBuffer();
|
||||
int lines = 1;
|
||||
|
||||
for(AssociationRef ref : assocs)
|
||||
{
|
||||
NodeRef child = ref.getTargetRef();
|
||||
QName type = nodeService.getType(child);
|
||||
if(ContentModel.TYPE_PERSON.equals(type))
|
||||
{
|
||||
if(text.length() > 0) {
|
||||
text.append('\n');
|
||||
lines++;
|
||||
}
|
||||
text.append(nodeService.getProperty(
|
||||
child, ContentModel.PROP_USERNAME
|
||||
));
|
||||
}
|
||||
else if(ContentModel.TYPE_CONTENT.equals(type))
|
||||
{
|
||||
// TODO Link to the content
|
||||
if(text.length() > 0) {
|
||||
text.append('\n');
|
||||
lines++;
|
||||
}
|
||||
text.append(nodeService.getProperty(
|
||||
child, ContentModel.PROP_TITLE
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("TODO: handle " + type + " for " + child);
|
||||
}
|
||||
}
|
||||
|
||||
String v = text.toString();
|
||||
c.setCellValue( v );
|
||||
if(lines > 1)
|
||||
{
|
||||
c.setCellStyle(styleNewLines);
|
||||
r.setHeightInPoints( lines*sheet.getDefaultRowHeightInPoints() );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This property isn't set
|
||||
c.setCellType(Cell.CELL_TYPE_BLANK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular property, set
|
||||
if(val instanceof String)
|
||||
{
|
||||
c.setCellValue((String)val);
|
||||
}
|
||||
else if(val instanceof Date)
|
||||
{
|
||||
c.setCellValue((Date)val);
|
||||
c.setCellStyle(styleDate);
|
||||
}
|
||||
else if(val instanceof Integer || val instanceof Long)
|
||||
{
|
||||
double v = 0.0;
|
||||
if(val instanceof Long) v = (double)(Long)val;
|
||||
if(val instanceof Integer) v = (double)(Integer)val;
|
||||
c.setCellValue(v);
|
||||
c.setCellStyle(styleInt);
|
||||
}
|
||||
else if(val instanceof Float || val instanceof Double)
|
||||
{
|
||||
double v = 0.0;
|
||||
if(val instanceof Float) v = (double)(Float)val;
|
||||
if(val instanceof Double) v = (double)(Double)val;
|
||||
c.setCellValue(v);
|
||||
c.setCellStyle(styleDouble);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
System.err.println("TODO: handle " + val.getClass().getName() + " - " + val);
|
||||
}
|
||||
}
|
||||
|
||||
colNum++;
|
||||
}
|
||||
|
||||
rowNum++;
|
||||
}
|
||||
|
||||
// Sensible column widths please!
|
||||
colNum = 0;
|
||||
for(QName prop : properties)
|
||||
{
|
||||
sheet.autoSizeColumn(colNum);
|
||||
colNum++;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts.search;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.search.SuggesterParameters;
|
||||
import org.alfresco.service.cmr.search.SuggesterResult;
|
||||
import org.alfresco.service.cmr.search.SuggesterService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the <i>auto-suggest-search.get</i> web
|
||||
* script.
|
||||
*
|
||||
* @author Jamal Kaabi-Mofrad
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AutoSuggestSearchGet extends DeclarativeWebScript
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(AutoSuggestSearchGet.class);
|
||||
|
||||
private static final String TERM = "t";
|
||||
private static final String LIMIT = "limit";
|
||||
private static final String SUGGESTIONS = "suggestions";
|
||||
|
||||
private SuggesterService suggesterService;
|
||||
|
||||
public void setSuggesterService(SuggesterService suggesterService)
|
||||
{
|
||||
this.suggesterService = suggesterService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
|
||||
List<SearchSuggestionData> list = new ArrayList<>();
|
||||
Map<String, Object> model = new HashMap<String, Object>(1);
|
||||
model.put(SUGGESTIONS, list);
|
||||
|
||||
if (!suggesterService.isEnabled())
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
String term = req.getParameter(TERM);
|
||||
int limit = getLimit(req.getParameter(LIMIT));
|
||||
|
||||
if (term == null || term.isEmpty())
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
SuggesterResult result = suggesterService.getSuggestions(new SuggesterParameters(term, limit, false));
|
||||
List<Pair<String, Integer>> suggestedTerms = result.getSuggestions();
|
||||
for (Pair<String, Integer> pair : suggestedTerms)
|
||||
{
|
||||
list.add(new SearchSuggestionData(pair.getFirst(), pair.getSecond()));
|
||||
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Suggested terms for the [" + term + "] are: " + list);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private int getLimit(String limit)
|
||||
{
|
||||
if (limit == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(limit);
|
||||
}
|
||||
catch (NumberFormatException ne)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts.search;
|
||||
|
||||
/**
|
||||
* Basic POJO to represent a term suggestion.
|
||||
*
|
||||
* @author Jamal Kaabi-Mofrad
|
||||
* @since 5.0
|
||||
*/
|
||||
public class SearchSuggestionData
|
||||
{
|
||||
private final String term;
|
||||
private final int weight;
|
||||
|
||||
public SearchSuggestionData(String term, int weight)
|
||||
{
|
||||
this.term = term;
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public String getTerm()
|
||||
{
|
||||
return this.term;
|
||||
}
|
||||
|
||||
public int getWeight()
|
||||
{
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(100);
|
||||
builder.append("SearchSuggestionData [term=").append(this.term).append(", weight=").append(this.weight)
|
||||
.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiService;
|
||||
import org.alfresco.util.ScriptPagingDetails;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.springframework.extensions.surf.util.URLEncoder;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.json.JSONWriter;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractWikiWebScript extends DeclarativeWebScript
|
||||
{
|
||||
public static final String WIKI_SERVICE_ACTIVITY_APP_NAME = "wiki";
|
||||
|
||||
/**
|
||||
* When no maximum or paging info is given, what should we use?
|
||||
*/
|
||||
protected static final int MAX_QUERY_ENTRY_COUNT = 1000;
|
||||
|
||||
private static Log logger = LogFactory.getLog(AbstractWikiWebScript.class);
|
||||
|
||||
// Injected services
|
||||
protected NodeService nodeService;
|
||||
protected SiteService siteService;
|
||||
protected WikiService wikiService;
|
||||
protected PersonService personService;
|
||||
protected ActivityService activityService;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setWikiService(WikiService wikiService)
|
||||
{
|
||||
this.wikiService = wikiService;
|
||||
}
|
||||
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
|
||||
protected String getOrNull(JSONObject json, String key)
|
||||
{
|
||||
if (json.containsKey(key))
|
||||
{
|
||||
return (String)json.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds up a listing Paging request, based on the arguments
|
||||
* specified in the URL
|
||||
*/
|
||||
protected PagingRequest buildPagingRequest(WebScriptRequest req)
|
||||
{
|
||||
return new ScriptPagingDetails(req, MAX_QUERY_ENTRY_COUNT);
|
||||
}
|
||||
|
||||
protected void addActivityEntry(String event, WikiPageInfo wikiPage, SiteInfo site,
|
||||
WebScriptRequest req, JSONObject json)
|
||||
{
|
||||
addActivityEntry(event, wikiPage, site, req, json, Collections.<String, String>emptyMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an activity entry for the link
|
||||
*
|
||||
* @param event a String representing the event.
|
||||
* @param wikiPage the wiki page generating the activity.
|
||||
* @param site the site in which the wiki page was created.
|
||||
* @param req the {@link WebScriptRequest}.
|
||||
* @param json
|
||||
* @param additionalData any additional data required for the activity.
|
||||
*/
|
||||
protected void addActivityEntry(String event,
|
||||
WikiPageInfo wikiPage, SiteInfo site,
|
||||
WebScriptRequest req, JSONObject json,
|
||||
Map<String, String> additionalData)
|
||||
{
|
||||
// What page is this for?
|
||||
String page = req.getParameter("page");
|
||||
if (page == null && json != null)
|
||||
{
|
||||
if (json.containsKey("page"))
|
||||
{
|
||||
page = (String)json.get("page");
|
||||
}
|
||||
}
|
||||
if (page == null)
|
||||
{
|
||||
// Default
|
||||
page = "wiki";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
StringWriter activityJson = new StringWriter();
|
||||
JSONWriter activity = new JSONWriter(activityJson);
|
||||
activity.startObject();
|
||||
activity.writeValue("title", wikiPage.getTitle());
|
||||
activity.writeValue("page", page + "?title=" + URLEncoder.encodeUriComponent(wikiPage.getTitle()));
|
||||
for (Map.Entry<String, String> entry : additionalData.entrySet())
|
||||
{
|
||||
activity.writeValue(entry.getKey(), entry.getValue());
|
||||
}
|
||||
activity.endObject();
|
||||
|
||||
activityService.postActivity(
|
||||
"org.alfresco.wiki.page-" + event,
|
||||
site.getShortName(),
|
||||
WIKI_SERVICE_ACTIVITY_APP_NAME,
|
||||
activityJson.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Warn, but carry on
|
||||
logger.warn("Error adding wiki page " + event + " to activities feed", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected NodeRef personForModel(String username)
|
||||
{
|
||||
if (username == null || username.length() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Will turn into a Script Node needed of the person
|
||||
NodeRef person = personService.getPerson(username);
|
||||
return person;
|
||||
}
|
||||
catch(NoSuchPersonException e)
|
||||
{
|
||||
// This is normally caused by the person having been deleted
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Map<String, Object> renderWikiPage(WikiPageInfo page)
|
||||
{
|
||||
Map<String, Object> res = new HashMap<String, Object>();
|
||||
res.put("page", page);
|
||||
res.put("node", page.getNodeRef());
|
||||
res.put("name", page.getSystemName());
|
||||
res.put("title", page.getTitle());
|
||||
res.put("contents", page.getContents());
|
||||
res.put("tags", page.getTags());
|
||||
|
||||
// Both forms used for dates
|
||||
res.put("createdOn", page.getCreatedAt());
|
||||
res.put("modifiedOn", page.getModifiedAt());
|
||||
res.put("created", page.getCreatedAt());
|
||||
res.put("modified", page.getModifiedAt());
|
||||
|
||||
// For most things, we want blank instead of null
|
||||
for (String key : res.keySet())
|
||||
{
|
||||
if (res.get(key) == null)
|
||||
{
|
||||
res.put(key, "");
|
||||
}
|
||||
}
|
||||
|
||||
// FTL needs a script node of the people, or null if unavailable
|
||||
res.put("createdBy", personForModel(page.getCreator()));
|
||||
res.put("modifiedBy", personForModel(page.getModifier()));
|
||||
|
||||
// All done
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req,
|
||||
Status status, Cache cache)
|
||||
{
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
if (templateVars == null)
|
||||
{
|
||||
String error = "No parameters supplied";
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, error);
|
||||
}
|
||||
|
||||
|
||||
// Parse the JSON, if supplied
|
||||
JSONObject json = null;
|
||||
String contentType = req.getContentType();
|
||||
if (contentType != null && contentType.indexOf(';') != -1)
|
||||
{
|
||||
contentType = contentType.substring(0, contentType.indexOf(';'));
|
||||
}
|
||||
if (MimetypeMap.MIMETYPE_JSON.equals(contentType))
|
||||
{
|
||||
JSONParser parser = new JSONParser();
|
||||
try
|
||||
{
|
||||
json = (JSONObject)parser.parse(req.getContent().getContent());
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + io.getMessage());
|
||||
}
|
||||
catch (ParseException pe)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Invalid JSON: " + pe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get the site short name. Try quite hard to do so...
|
||||
String siteName = templateVars.get("siteId");
|
||||
if (siteName == null)
|
||||
{
|
||||
siteName = req.getParameter("site");
|
||||
}
|
||||
if (siteName == null && json != null)
|
||||
{
|
||||
if (json.containsKey("siteid"))
|
||||
{
|
||||
siteName = (String)json.get("siteid");
|
||||
}
|
||||
else if (json.containsKey("siteId"))
|
||||
{
|
||||
siteName = (String)json.get("siteId");
|
||||
}
|
||||
else if(json.containsKey("site"))
|
||||
{
|
||||
siteName = (String)json.get("site");
|
||||
}
|
||||
}
|
||||
if (siteName == null)
|
||||
{
|
||||
String error = "No site given";
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, error);
|
||||
}
|
||||
|
||||
// Grab the requested site
|
||||
SiteInfo site = siteService.getSite(siteName);
|
||||
if (site == null)
|
||||
{
|
||||
String error = "Could not find site: " + siteName;
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, error);
|
||||
}
|
||||
|
||||
String pageTitle = templateVars.get("pageTitle");
|
||||
|
||||
// Have the real work done
|
||||
return executeImpl(site, pageTitle, req, json, status, cache);
|
||||
}
|
||||
|
||||
protected abstract Map<String, Object> executeImpl(SiteInfo site,
|
||||
String pageTitle, WebScriptRequest req, JSONObject json,
|
||||
Status status, Cache cache);
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page listing page.delete webscript.
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPageDelete extends AbstractWikiWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Try to find the page
|
||||
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageTitle);
|
||||
if (page == null)
|
||||
{
|
||||
String message = "The Wiki Page could not be found";
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, message);
|
||||
}
|
||||
|
||||
// Have the page deleted
|
||||
wikiService.deleteWikiPage(page);
|
||||
|
||||
// Generate an activity for this
|
||||
addActivityEntry("deleted", page, site, req, json);
|
||||
|
||||
// Mark it as gone
|
||||
status.setCode(Status.STATUS_NO_CONTENT);
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.repo.wiki.WikiServiceImpl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page fetching page.get webscript.
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPageGet extends AbstractWikiWebScript
|
||||
{
|
||||
private static final String MSG_NOT_FOUND= "page-not-found";
|
||||
|
||||
// For matching links. Not the best pattern ever...
|
||||
private static final Pattern LINK_PATTERN = Pattern.compile("\\[\\[([^\\|#\\]]+)");
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
String strMinWikiData = req.getParameter("minWikiData");
|
||||
boolean minWikiData = strMinWikiData != null ? Boolean.parseBoolean(strMinWikiData) : false;
|
||||
|
||||
final ResourceBundle rb = getResources();
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Try to find the page
|
||||
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageTitle);
|
||||
if (page == null)
|
||||
{
|
||||
String message = "The Wiki Page could not be found";
|
||||
status.setCode(Status.STATUS_NOT_FOUND);
|
||||
status.setMessage(message);
|
||||
status.setRedirect(true);
|
||||
|
||||
// MNT-11595 Downgrading permission from Manager to Consumer, user still allowed to create WIKI pages
|
||||
// Record these
|
||||
model.put("container", site.getNodeRef());
|
||||
model.put("error", rb.getString(MSG_NOT_FOUND));
|
||||
|
||||
// Bail out
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
// Identify all the internal page links, valid and not
|
||||
// TODO This may be a candidate for the service in future
|
||||
List<String> links = new ArrayList<String>();
|
||||
List<String> pageTitles = new ArrayList<String>();
|
||||
if (page.getContents() != null)
|
||||
{
|
||||
Matcher m = LINK_PATTERN.matcher(page.getContents());
|
||||
while (m.find())
|
||||
{
|
||||
String link = m.group(1);
|
||||
if (! links.contains(link))
|
||||
{
|
||||
links.add(link);
|
||||
// build the list of available pages
|
||||
WikiPageInfo wikiPage = wikiService.getWikiPage(site.getShortName(), StringEscapeUtils.unescapeHtml(link));
|
||||
if (wikiPage != null)
|
||||
{
|
||||
pageTitles.add(wikiPage.getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All done
|
||||
model.put("page", page);
|
||||
model.put("node", page.getNodeRef());
|
||||
model.put("container", page.getContainerNodeRef());
|
||||
model.put("links", links);
|
||||
model.put("pageList", pageTitles);
|
||||
model.put("tags", page.getTags());
|
||||
model.put("siteId", site.getShortName());
|
||||
model.put("site", site);
|
||||
model.put("minWikiData", minWikiData);
|
||||
|
||||
// Double wrap
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("result", model);
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.admin.SysAdminParams;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.wiki.WikiServiceImpl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.alfresco.util.UrlUtil;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page listing pagelist.get webscript.
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPageListGet extends AbstractWikiWebScript
|
||||
{
|
||||
protected static final int RECENT_SEARCH_PERIOD_DAYS = 7;
|
||||
protected static final long ONE_DAY_MS = 24*60*60*1000;
|
||||
|
||||
// Injected services
|
||||
private SysAdminParams sysAdminParams;
|
||||
|
||||
public void setSysAdminParams(SysAdminParams sysAdminParams)
|
||||
{
|
||||
this.sysAdminParams = sysAdminParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
// Decide on what kind of request they wanted
|
||||
String filter = req.getParameter("filter");
|
||||
String strPageMetaOnly = req.getParameter("pageMetaOnly");
|
||||
boolean pageMetaOnly = strPageMetaOnly != null ? Boolean.parseBoolean(strPageMetaOnly) : false;
|
||||
|
||||
// User?
|
||||
boolean userFiltering = false;
|
||||
String user = null;
|
||||
if ("user".equals(filter) || "myPages".equals(filter))
|
||||
{
|
||||
userFiltering = true;
|
||||
user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
// Date?
|
||||
boolean dateFiltering = false;
|
||||
boolean dateIsCreated = true;
|
||||
Date from = null;
|
||||
Date to = null;
|
||||
if ("recentlyAdded".equals(filter) ||
|
||||
"recentlyCreated".equals(filter) ||
|
||||
"recentlyModified".equals(filter))
|
||||
{
|
||||
dateFiltering = true;
|
||||
if ("recentlyModified".equals(filter))
|
||||
{
|
||||
dateIsCreated = false;
|
||||
}
|
||||
|
||||
int days = RECENT_SEARCH_PERIOD_DAYS;
|
||||
String daysS = req.getParameter("days");
|
||||
if (daysS != null && daysS.length() > 0)
|
||||
{
|
||||
days = Integer.parseInt(daysS);
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
from = new Date(now.getTime() - days*ONE_DAY_MS);
|
||||
to = new Date(now.getTime() + ONE_DAY_MS);
|
||||
}
|
||||
|
||||
|
||||
// Get the links for the list
|
||||
PagingRequest paging = buildPagingRequest(req);
|
||||
PagingResults<WikiPageInfo> pages;
|
||||
if (userFiltering)
|
||||
{
|
||||
pages = wikiService.listWikiPages(site.getShortName(), user, paging);
|
||||
}
|
||||
else if (dateFiltering)
|
||||
{
|
||||
if (dateIsCreated)
|
||||
{
|
||||
pages = wikiService.listWikiPagesByCreated(site.getShortName(), from, to, paging);
|
||||
}
|
||||
else
|
||||
{
|
||||
pages = wikiService.listWikiPagesByModified(site.getShortName(), from, to, paging);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pages = wikiService.listWikiPages(site.getShortName(), paging);
|
||||
}
|
||||
|
||||
|
||||
// For each one in our page, grab details of any ignored instances
|
||||
List<Map<String,Object>> items = new ArrayList<Map<String,Object>>();
|
||||
for (WikiPageInfo page : pages.getPage())
|
||||
{
|
||||
Map<String, Object> result = renderWikiPage(page);
|
||||
items.add(result);
|
||||
}
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("pages", items);
|
||||
data.put("pageSize", paging.getMaxItems());
|
||||
data.put("startIndex", paging.getSkipCount());
|
||||
data.put("itemCount", items.size());
|
||||
|
||||
int total = items.size();
|
||||
if (pages.getTotalResultCount() != null && pages.getTotalResultCount().getFirst() != null)
|
||||
{
|
||||
total = pages.getTotalResultCount().getFirst();
|
||||
}
|
||||
data.put("total", total);
|
||||
|
||||
// We need the container node for permissions checking
|
||||
NodeRef container;
|
||||
if (pages.getPage().size() > 0)
|
||||
{
|
||||
container = pages.getPage().get(0).getContainerNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the container (if it's been created yet)
|
||||
container = siteService.getContainer(
|
||||
site.getShortName(), WikiServiceImpl.WIKI_COMPONENT);
|
||||
|
||||
if (container == null)
|
||||
{
|
||||
// Brand new site, no write operations on links have happened
|
||||
// Fudge it for now with the site itself, the first write call
|
||||
// will have the container created
|
||||
container = site.getNodeRef();
|
||||
}
|
||||
}
|
||||
|
||||
// All done
|
||||
Map<String, Object> wiki = new HashMap<String, Object>();
|
||||
wiki.put("pages", items); // Old style
|
||||
wiki.put("container", container);
|
||||
|
||||
if (userFiltering)
|
||||
{
|
||||
// We need to get all the wiki pages for "My Pages" filter otherwise
|
||||
// the links for renamed wiki pages won't be rendered correctly,
|
||||
// which were created by other users
|
||||
pages = wikiService.listWikiPages(site.getShortName(), paging);
|
||||
List<String> pageTitles = new ArrayList<String>(pages.getPage().size());
|
||||
for (WikiPageInfo page : pages.getPage())
|
||||
{
|
||||
pageTitles.add(page.getTitle());
|
||||
}
|
||||
wiki.put("pageTitles", pageTitles);
|
||||
}
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("data", data); // New style
|
||||
model.put("wiki", wiki);
|
||||
model.put("siteId", site.getShortName());
|
||||
model.put("site", site);
|
||||
model.put(TemplateService.KEY_SHARE_URL, UrlUtil.getShareUrl(sysAdminParams));
|
||||
model.put("pageMetaOnly", pageMetaOnly);
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.alfresco.service.cmr.model.FileExistsException;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page renaming move.post webscript.
|
||||
*
|
||||
* TODO Track links to pages, so we can avoid creating the "This page has been moved"
|
||||
* stubs as now, for cases where nothing links to the page being renamed. (ALF-3844)
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPageMovePost extends AbstractWikiWebScript
|
||||
{
|
||||
private static final String MSG_MOVED = "page-moved";
|
||||
private static final String MSG_MOVED_HERE = "page-moved-here";
|
||||
private static final String MSG_NOT_FOUND= "page-not-found";
|
||||
|
||||
// The 'custom0' key here refers to the org.alfresco.wiki.page-renamed {2} in activity-list.get.properties
|
||||
private static final String OLD_TITLE_KEY = "custom0";
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
final Map<String, Object> model = new HashMap<String, Object>();
|
||||
final ResourceBundle rb = getResources();
|
||||
|
||||
// Try to find the page we're renaming
|
||||
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageTitle);
|
||||
if (page == null)
|
||||
{
|
||||
String message = "The Wiki Page could not be found";
|
||||
status.setCode(Status.STATUS_NOT_FOUND);
|
||||
status.setMessage(message);
|
||||
|
||||
// Wrap and bail
|
||||
model.put("error", rb.getString(MSG_NOT_FOUND));
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("result", model);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Grab the new Title
|
||||
// The "name" in the JSON is actually the title!
|
||||
String newTitle = (String)json.get("name");
|
||||
|
||||
|
||||
// Have the page re-named, if possible
|
||||
String oldTitle = page.getTitle().length() == 0 ? pageTitle : page.getTitle();
|
||||
try
|
||||
{
|
||||
page.setTitle(newTitle);
|
||||
page = wikiService.updateWikiPage(page);
|
||||
}
|
||||
catch (FileExistsException e)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_CONFLICT, "Duplicate page name");
|
||||
}
|
||||
|
||||
|
||||
// Create the "This page has been moved" entry for the old page
|
||||
String movedContent = rb.getString(MSG_MOVED) + " [[" + page.getTitle() +
|
||||
"|" + rb.getString(MSG_MOVED_HERE) + "]].";
|
||||
wikiService.createWikiPage(site.getShortName(), oldTitle, movedContent);
|
||||
|
||||
Map<String, String> additionalData = new HashMap<String, String>();
|
||||
additionalData.put(OLD_TITLE_KEY, oldTitle);
|
||||
|
||||
// Add an activity entry for the rename
|
||||
addActivityEntry("renamed", page, site, req, json, additionalData);
|
||||
|
||||
|
||||
// All done
|
||||
model.put("name", page.getSystemName());
|
||||
model.put("title", page.getTitle());
|
||||
model.put("page", page);
|
||||
model.put("siteId", site.getShortName());
|
||||
model.put("site", site);
|
||||
|
||||
// Double wrap
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("result", model);
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page creating/editing page.put webscript.
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPagePut extends AbstractWikiWebScript
|
||||
{
|
||||
private static final String DEFAULT_PAGE_CONTENT = "This is a new page. It has no content";
|
||||
|
||||
private VersionService versionService;
|
||||
public void setVersionService(VersionService versionService)
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Grab the details of the change
|
||||
// Fetch the contents
|
||||
String contents = (String)json.get("pagecontent");
|
||||
|
||||
// Fetch the title, used only when creating
|
||||
String title;
|
||||
if (json.containsKey("title"))
|
||||
{
|
||||
title = (String)json.get("title");
|
||||
}
|
||||
else
|
||||
{
|
||||
title = pageTitle;
|
||||
}
|
||||
|
||||
// Fetch the versioning details
|
||||
boolean forceSave = json.containsKey("forceSave");
|
||||
String currentVersion = null;
|
||||
if (json.containsKey("currentVersion"))
|
||||
{
|
||||
currentVersion = (String)json.get("currentVersion");
|
||||
}
|
||||
|
||||
// Fetch the tags, if given
|
||||
List<String> tags = null;
|
||||
if (json.containsKey("tags"))
|
||||
{
|
||||
tags = new ArrayList<String>();
|
||||
if (json.get("tags").equals(""))
|
||||
{
|
||||
// Empty list given as a string, eg "tags":""
|
||||
}
|
||||
else
|
||||
{
|
||||
// Array of tags
|
||||
JSONArray tagsA = (JSONArray)json.get("tags");
|
||||
for (int i=0; i<tagsA.size(); i++)
|
||||
{
|
||||
tags.add((String)tagsA.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Are we creating or editing?
|
||||
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageTitle);
|
||||
if (page == null)
|
||||
{
|
||||
// Create the page
|
||||
page = wikiService.createWikiPage(site.getShortName(), title, contents);
|
||||
|
||||
// Add tags if given
|
||||
if (tags != null && tags.size() > 0)
|
||||
{
|
||||
page.getTags().addAll(tags);
|
||||
wikiService.updateWikiPage(page);
|
||||
}
|
||||
|
||||
// Make it versioned
|
||||
makeVersioned(page);
|
||||
|
||||
// Generate the activity
|
||||
addActivityEntry("created", page, site, req, json);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Updating, check about versioning first
|
||||
if (forceSave || pageVersionMatchesSubmitted(page, currentVersion))
|
||||
{
|
||||
// Update the page
|
||||
page.setContents(contents);
|
||||
if (tags != null)
|
||||
{
|
||||
page.getTags().clear();
|
||||
page.getTags().addAll(tags);
|
||||
}
|
||||
wikiService.updateWikiPage(page);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Editing the wrong version
|
||||
String message = "Repository version is newer.";
|
||||
throw new WebScriptException(Status.STATUS_CONFLICT, message);
|
||||
}
|
||||
|
||||
// Generate the activity
|
||||
addActivityEntry("edited", page, site, req, json);
|
||||
}
|
||||
|
||||
|
||||
// All done
|
||||
model.put("page", page);
|
||||
model.put("site", site);
|
||||
model.put("siteId", site.getShortName());
|
||||
|
||||
// Double wrap
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
result.put("result", model);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean pageVersionMatchesSubmitted(WikiPageInfo page, String currentVersion)
|
||||
{
|
||||
// If they didn't give version, it can't be right
|
||||
if (currentVersion == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab the current version
|
||||
Version version = versionService.getCurrentVersion(page.getNodeRef());
|
||||
if (version == null)
|
||||
{
|
||||
// It should be versioned already, fix that
|
||||
makeVersioned(page);
|
||||
|
||||
// Wasn't versioned before, so can't detect conflict
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the label
|
||||
if (version.getVersionLabel().equals(currentVersion))
|
||||
{
|
||||
// Match, no changes
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Someone else has edited it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void makeVersioned(WikiPageInfo page)
|
||||
{
|
||||
Map<QName,Serializable> versionProps = new HashMap<QName, Serializable>();
|
||||
versionProps.put(ContentModel.PROP_AUTO_VERSION, true);
|
||||
versionProps.put(ContentModel.PROP_AUTO_VERSION_PROPS, true);
|
||||
versionService.ensureVersioningEnabled(page.getNodeRef(), versionProps);
|
||||
}
|
||||
}
|
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.wiki;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.AspectMissingException;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.version.Version;
|
||||
import org.alfresco.service.cmr.version.VersionDoesNotExistException;
|
||||
import org.alfresco.service.cmr.version.VersionHistory;
|
||||
import org.alfresco.service.cmr.version.VersionService;
|
||||
import org.alfresco.service.cmr.wiki.WikiPageInfo;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the wiki page version fetching version.get webscript.
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 4.0
|
||||
*/
|
||||
public class WikiPageVersionGet extends AbstractWikiWebScript
|
||||
{
|
||||
// For spotting if a version string is an ID or a Label
|
||||
private static final Pattern LABEL_PATTERN = Pattern.compile("\\d+\\.\\d+");
|
||||
|
||||
private static final String PARAM_CONTENT = "content";
|
||||
|
||||
private ContentService contentService;
|
||||
private VersionService versionService;
|
||||
|
||||
public void setVersionService(VersionService versionService)
|
||||
{
|
||||
this.versionService = versionService;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(SiteInfo site, String pageTitle,
|
||||
WebScriptRequest req, JSONObject json, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Grab the version string
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String versionId = templateVars.get("versionId");
|
||||
if (versionId == null)
|
||||
{
|
||||
String error = "No versionId supplied";
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, error);
|
||||
}
|
||||
|
||||
// Try to find the page
|
||||
WikiPageInfo page = wikiService.getWikiPage(site.getShortName(), pageTitle);
|
||||
if (page == null)
|
||||
{
|
||||
String message = "The Wiki Page could not be found";
|
||||
status.setCode(Status.STATUS_NOT_FOUND);
|
||||
status.setMessage(message);
|
||||
|
||||
// Return an empty string though
|
||||
model.put(PARAM_CONTENT, "");
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
// Fetch the version history for the node
|
||||
VersionHistory versionHistory = null;
|
||||
Version version = null;
|
||||
try
|
||||
{
|
||||
versionHistory = versionService.getVersionHistory(page.getNodeRef());
|
||||
}
|
||||
catch (AspectMissingException e) {}
|
||||
|
||||
if (versionHistory == null)
|
||||
{
|
||||
// Not been versioned, return an empty string
|
||||
model.put(PARAM_CONTENT, "");
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
// Fetch the version by either ID or Label
|
||||
Matcher m = LABEL_PATTERN.matcher(versionId);
|
||||
if (m.matches())
|
||||
{
|
||||
// It's a version label like 2.3
|
||||
try
|
||||
{
|
||||
version = versionHistory.getVersion(versionId);
|
||||
}
|
||||
catch (VersionDoesNotExistException e) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a version ID like ed00bac1-f0da-4042-8598-45a0d39cb74d
|
||||
// (The ID is usually part of the NodeRef of the frozen node, but we
|
||||
// don't assume to be able to just generate the full NodeRef)
|
||||
for (Version v : versionHistory.getAllVersions())
|
||||
{
|
||||
if (v.getFrozenStateNodeRef().getId().equals(versionId))
|
||||
{
|
||||
version = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Did we find the right version in the end?
|
||||
String contents;
|
||||
if (version != null)
|
||||
{
|
||||
ContentReader reader = contentService.getReader(version.getFrozenStateNodeRef(), ContentModel.PROP_CONTENT);
|
||||
if (reader != null)
|
||||
{
|
||||
contents = reader.getContentString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// No content was stored in the version history
|
||||
contents = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No warning of the missing version, just return an empty string
|
||||
contents = "";
|
||||
}
|
||||
|
||||
// All done
|
||||
model.put(PARAM_CONTENT, contents);
|
||||
model.put("page", page);
|
||||
model.put("site", site);
|
||||
model.put("siteId", site.getShortName());
|
||||
return model;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.slingshot.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.Client;
|
||||
import org.alfresco.repo.Client.ClientType;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.web.scripts.content.ContentGet;
|
||||
import org.alfresco.service.cmr.activities.ActivityPoster;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
/**
|
||||
* Share specific ContentGet implementation.
|
||||
* <p>
|
||||
* Checks to see if:
|
||||
* a) the request is an explicit download (attachment)
|
||||
* b) the requested NodeRef within the context of a Share Site
|
||||
* <p>
|
||||
* If both tests are true then generates an Activity feed item to record the Download request.
|
||||
* All other requests and any further processing is performed by the super class.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class SlingshotContentGet extends ContentGet
|
||||
{
|
||||
protected SiteService siteService;
|
||||
private ActivityPoster poster;
|
||||
private RetryingTransactionHelper transactionHelper;
|
||||
|
||||
public void setSiteService(SiteService siteService)
|
||||
{
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
public void setPoster(ActivityPoster poster)
|
||||
{
|
||||
this.poster = poster;
|
||||
}
|
||||
|
||||
public void setTransactionHelper(RetryingTransactionHelper transactionHelper)
|
||||
{
|
||||
this.transactionHelper = transactionHelper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(final WebScriptRequest req, final WebScriptResponse res) throws IOException
|
||||
{
|
||||
// are we downloading content as an attachment?
|
||||
if (Boolean.valueOf(req.getParameter("a")))
|
||||
{
|
||||
// is this private ActivityPoster poster; node part of a Site context?
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String storeType = templateVars.get("store_type");
|
||||
String storeId = templateVars.get("store_id");
|
||||
String nodeId = templateVars.get("id");
|
||||
|
||||
// create the NodeRef and ensure it is valid
|
||||
if (storeType != null && storeId != null && nodeId != null)
|
||||
{
|
||||
final NodeRef nodeRef = new NodeRef(storeType, storeId, nodeId);
|
||||
SiteInfo site = null;
|
||||
try
|
||||
{
|
||||
site = this.siteService.getSite(nodeRef);
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// We don't have access to the site, don't post any permissions
|
||||
}
|
||||
if (site != null)
|
||||
{
|
||||
// found a valid parent Site - gather the details to post an Activity
|
||||
String filename = templateVars.get("filename");
|
||||
if (filename == null || filename.length() == 0)
|
||||
{
|
||||
filename = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
}
|
||||
final String strFilename = filename;
|
||||
final String siteName = site.getShortName();
|
||||
transactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
// post an activity - mirror the mechanism as if from the Share application
|
||||
poster.postFileFolderActivity(ActivityPoster.DOWNLOADED, null, null,
|
||||
siteName, null, nodeRef, strFilename, "documentlibrary", Client.asType(ClientType.webclient), null);
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.execute(req, res);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user