mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
Performance improvement: prevent unnecessary 304 revalidation requests for thumbnails in detailed view of My-Documents and Recently Modified Documents dashlets Fixed bean config problem (caused by r34662) Fix build break Refactored revalidation code to remove previously added WebScripts that are now surplus to requirements Performance improvement: prevent unnecessary 304 revalidation for avatars on site colleagues dashlet Performance improvement: prevent unnecessary 304 revalidation for avatars on following/follwers pages Performance improvement: prevent unnecessary 304 revalidation for avatars in activity feeds Performance improvement: prevent unecessary 304 revalidation for user avatar thumbnails in header WebScript Prevent 304 revalidations for unchanged thumbnails in document library, web preview and search git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@34698 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
419 lines
14 KiB
Java
419 lines
14 KiB
Java
/**
|
|
*
|
|
*/
|
|
package org.alfresco.repo.jscript.app;
|
|
|
|
import java.io.Serializable;
|
|
import java.text.MessageFormat;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.service.ServiceRegistry;
|
|
import org.alfresco.service.cmr.lock.LockService;
|
|
import org.alfresco.service.cmr.lock.LockStatus;
|
|
import org.alfresco.service.cmr.model.FileFolderService;
|
|
import org.alfresco.service.cmr.model.FileInfo;
|
|
import org.alfresco.service.cmr.repository.ContentReader;
|
|
import org.alfresco.service.cmr.repository.ContentService;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.cmr.security.AccessPermission;
|
|
import org.alfresco.service.cmr.security.AccessStatus;
|
|
import org.alfresco.service.cmr.security.PermissionService;
|
|
import org.alfresco.service.cmr.security.PublicServiceAccessService;
|
|
import org.alfresco.service.namespace.NamespaceException;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.util.ISO8601DateFormat;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
import org.json.simple.JSONArray;
|
|
import org.json.simple.JSONAware;
|
|
import org.json.simple.JSONObject;
|
|
import org.springframework.extensions.surf.util.URLEncoder;
|
|
|
|
/**
|
|
* JSON Conversion Component
|
|
*
|
|
* @author Roy Wetherall
|
|
*/
|
|
public class JSONConversionComponent
|
|
{
|
|
/** Content download API URL template */
|
|
private final static String CONTENT_DOWNLOAD_API_URL = "/api/node/content/{0}/{1}/{2}/{3}";
|
|
|
|
/** Logger */
|
|
private static Log logger = LogFactory.getLog(JSONConversionComponent.class);
|
|
|
|
/** Registered decorators */
|
|
protected Map<QName, PropertyDecorator> propertyDecorators = new HashMap<QName, PropertyDecorator>(3);
|
|
|
|
/** User permissions */
|
|
protected String[] userPermissions;
|
|
|
|
/** Services */
|
|
protected NodeService nodeService;
|
|
protected PublicServiceAccessService publicServiceAccessService;
|
|
protected NamespaceService namespaceService;
|
|
protected FileFolderService fileFolderService;
|
|
protected LockService lockService;
|
|
protected ContentService contentService;
|
|
protected PermissionService permissionService;
|
|
|
|
/**
|
|
* @param nodeService node service
|
|
*/
|
|
public void setNodeService(NodeService nodeService)
|
|
{
|
|
this.nodeService = nodeService;
|
|
}
|
|
|
|
/**
|
|
* @param publicServiceAccessService public service access service
|
|
*/
|
|
public void setPublicServiceAccessService(PublicServiceAccessService publicServiceAccessService)
|
|
{
|
|
this.publicServiceAccessService = publicServiceAccessService;
|
|
}
|
|
|
|
/**
|
|
* @param namespaceService namespace service
|
|
*/
|
|
public void setNamespaceService(NamespaceService namespaceService)
|
|
{
|
|
this.namespaceService = namespaceService;
|
|
}
|
|
|
|
/**
|
|
* @param fileFolderService file folder service
|
|
*/
|
|
public void setFileFolderService(FileFolderService fileFolderService)
|
|
{
|
|
this.fileFolderService = fileFolderService;
|
|
}
|
|
|
|
/**
|
|
* @param lockService lock service
|
|
*/
|
|
public void setLockService(LockService lockService)
|
|
{
|
|
this.lockService = lockService;
|
|
}
|
|
|
|
/**
|
|
* @param permissionService permission service
|
|
*/
|
|
public void setPermissionService(PermissionService permissionService)
|
|
{
|
|
this.permissionService = permissionService;
|
|
}
|
|
|
|
/**
|
|
* @param userPermissions user permissions
|
|
*/
|
|
public void setUserPermissions(String[] userPermissions)
|
|
{
|
|
this.userPermissions = userPermissions;
|
|
}
|
|
|
|
/**
|
|
* @param contentService content service
|
|
*/
|
|
public void setContentService(ContentService contentService)
|
|
{
|
|
this.contentService = contentService;
|
|
}
|
|
|
|
/**
|
|
* Register a property decorator;
|
|
*
|
|
* @param propertyDecorator
|
|
*/
|
|
public void registerPropertyDecorator(PropertyDecorator propertyDecorator)
|
|
{
|
|
for (QName propertyName : propertyDecorator.getPropertyNames())
|
|
{
|
|
propertyDecorators.put(propertyName, propertyDecorator);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a node reference to a JSON string. Selects the correct converter based on selection
|
|
* implementation.
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
public String toJSON(NodeRef nodeRef, boolean useShortQNames)
|
|
{
|
|
JSONObject json = new JSONObject();
|
|
|
|
if (this.nodeService.exists(nodeRef) == true)
|
|
{
|
|
if (publicServiceAccessService.hasAccess(ServiceRegistry.NODE_SERVICE.getLocalName(), "getProperties", nodeRef) == AccessStatus.ALLOWED)
|
|
{
|
|
// Get node info
|
|
FileInfo nodeInfo = fileFolderService.getFileInfo(nodeRef);
|
|
|
|
// Set root values
|
|
setRootValues(nodeInfo, json, useShortQNames);
|
|
|
|
// add permissions
|
|
json.put("permissions", permissionsToJSON(nodeRef));
|
|
|
|
// add properties
|
|
json.put("properties", propertiesToJSON(nodeRef, useShortQNames));
|
|
|
|
// add aspects
|
|
json.put("aspects", apsectsToJSON(nodeRef, useShortQNames));
|
|
}
|
|
}
|
|
|
|
return json.toJSONString();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeInfo
|
|
* @param rootJSONObject
|
|
* @param useShortQNames
|
|
* @throws JSONException
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected void setRootValues(FileInfo nodeInfo, JSONObject rootJSONObject, boolean useShortQNames)
|
|
{
|
|
NodeRef nodeRef = nodeInfo.getNodeRef();
|
|
|
|
rootJSONObject.put("nodeRef", nodeInfo.getNodeRef().toString());
|
|
rootJSONObject.put("type", nameToString(nodeInfo.getType(), useShortQNames));
|
|
rootJSONObject.put("isContainer", nodeInfo.isFolder()); //node.getIsContainer() || node.getIsLinkToContainer());
|
|
rootJSONObject.put("isLocked", isLocked(nodeInfo.getNodeRef()));
|
|
|
|
rootJSONObject.put("isLink", nodeInfo.isLink());
|
|
if (nodeInfo.isLink() == true)
|
|
{
|
|
NodeRef targetNodeRef = nodeInfo.getLinkNodeRef();
|
|
if (targetNodeRef != null)
|
|
{
|
|
rootJSONObject.put("linkedNode", toJSON(targetNodeRef, useShortQNames));
|
|
}
|
|
}
|
|
|
|
// TODO should this be moved to the property output since we may have more than one content property
|
|
// or a non-standard content property
|
|
|
|
if (nodeInfo.isFolder() == false)
|
|
{
|
|
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
|
|
|
if (reader != null)
|
|
{
|
|
String contentURL = MessageFormat.format(
|
|
CONTENT_DOWNLOAD_API_URL, new Object[]{
|
|
nodeRef.getStoreRef().getProtocol(),
|
|
nodeRef.getStoreRef().getIdentifier(),
|
|
nodeRef.getId(),
|
|
URLEncoder.encode(nodeInfo.getName())});
|
|
|
|
rootJSONObject.put("contentURL", contentURL);
|
|
rootJSONObject.put("mimetype", reader.getMimetype());
|
|
rootJSONObject.put("encoding", reader.getEncoding());
|
|
rootJSONObject.put("size", reader.getSize());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @return
|
|
* @throws JSONException
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected JSONObject permissionsToJSON(NodeRef nodeRef)
|
|
{
|
|
JSONObject permissionsJSON = new JSONObject();
|
|
if (AccessStatus.ALLOWED.equals(permissionService.hasPermission(nodeRef, PermissionService.READ_PERMISSIONS)) == true)
|
|
{
|
|
permissionsJSON.put("inherited", permissionService.getInheritParentPermissions(nodeRef));
|
|
permissionsJSON.put("roles", allSetPermissionsToJSON(nodeRef));
|
|
permissionsJSON.put("user", userPermissionsToJSON(nodeRef));
|
|
}
|
|
return permissionsJSON;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @return
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected JSONObject userPermissionsToJSON(NodeRef nodeRef)
|
|
{
|
|
JSONObject userPermissionJSON = new JSONObject();
|
|
for (String userPermission : this.userPermissions)
|
|
{
|
|
boolean hasPermission = AccessStatus.ALLOWED.equals(permissionService.hasPermission(nodeRef, userPermission));
|
|
userPermissionJSON.put(userPermission, hasPermission);
|
|
}
|
|
return userPermissionJSON;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @param useShortQNames
|
|
* @return
|
|
* @throws JSONException
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected JSONObject propertiesToJSON(NodeRef nodeRef, boolean useShortQNames)
|
|
{
|
|
JSONObject propertiesJSON = new JSONObject();
|
|
|
|
Map<QName, Serializable> properties = nodeService.getProperties(nodeRef);
|
|
for (QName propertyName : properties.keySet())
|
|
{
|
|
try
|
|
{
|
|
String key = nameToString(propertyName, useShortQNames);
|
|
Serializable value = properties.get(propertyName);
|
|
|
|
if (value != null)
|
|
{
|
|
// Has a decorator has been registered for this property?
|
|
if (propertyDecorators.containsKey(propertyName) == true)
|
|
{
|
|
JSONAware jsonAware = propertyDecorators.get(propertyName).decorate(propertyName, nodeRef, value);
|
|
if (jsonAware != null)
|
|
{
|
|
propertiesJSON.put(key, jsonAware);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Built-in data type processing
|
|
if (value instanceof Date)
|
|
{
|
|
JSONObject dateObj = new JSONObject();
|
|
dateObj.put("value", JSONObject.escape(value.toString()));
|
|
dateObj.put("iso8601", JSONObject.escape(ISO8601DateFormat.format((Date)value)));
|
|
propertiesJSON.put(key, dateObj);
|
|
}
|
|
else if (value instanceof List)
|
|
{
|
|
propertiesJSON.put(key, value);
|
|
}
|
|
else
|
|
{
|
|
propertiesJSON.put(key, value.toString());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
propertiesJSON.put(key, null);
|
|
}
|
|
}
|
|
catch (NamespaceException ne)
|
|
{
|
|
// ignore properties that do not have a registered namespace
|
|
if (logger.isDebugEnabled() == true)
|
|
{
|
|
logger.debug("Ignoring property '" + propertyName + "' as its namespace is not registered");
|
|
}
|
|
}
|
|
}
|
|
|
|
return propertiesJSON;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @param useShortQNames
|
|
* @return
|
|
* @throws JSONException
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected JSONArray apsectsToJSON(NodeRef nodeRef, boolean useShortQNames)
|
|
{
|
|
JSONArray aspectsJSON = new JSONArray();
|
|
|
|
Set<QName> aspects = this.nodeService.getAspects(nodeRef);
|
|
for (QName aspect : aspects)
|
|
{
|
|
aspectsJSON.add(nameToString(aspect, useShortQNames));
|
|
}
|
|
|
|
return aspectsJSON;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @return
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
protected JSONArray allSetPermissionsToJSON(NodeRef nodeRef)
|
|
{
|
|
Set<AccessPermission> acls = permissionService.getAllSetPermissions(nodeRef);
|
|
JSONArray permissions = new JSONArray();
|
|
for (AccessPermission permission : acls)
|
|
{
|
|
StringBuilder buf = new StringBuilder(64);
|
|
buf.append(permission.getAccessStatus())
|
|
.append(';')
|
|
.append(permission.getAuthority())
|
|
.append(';')
|
|
.append(permission.getPermission())
|
|
.append(';').append(permission.isSetDirectly() ? "DIRECT" : "INHERITED");
|
|
permissions.add(buf.toString());
|
|
}
|
|
return permissions;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param qname
|
|
* @param isShortName
|
|
* @return
|
|
*/
|
|
private String nameToString(QName qname, boolean isShortName)
|
|
{
|
|
String result = null;
|
|
if (isShortName == true)
|
|
{
|
|
result = qname.toPrefixString(namespaceService);
|
|
}
|
|
else
|
|
{
|
|
result = qname.toString();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param nodeRef
|
|
* @return
|
|
*/
|
|
private boolean isLocked(NodeRef nodeRef)
|
|
{
|
|
boolean locked = false;
|
|
|
|
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_LOCKABLE) == true)
|
|
{
|
|
LockStatus lockStatus = lockService.getLockStatus(nodeRef);
|
|
if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
|
|
{
|
|
locked = true;
|
|
}
|
|
}
|
|
|
|
return locked;
|
|
}
|
|
}
|