David Draper 508c880dea Merged THOR1_SPRINTS to HEAD
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
2012-03-22 16:44:48 +00:00

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;
}
}