Moving to root below branch label

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2005-12-08 07:13:07 +00:00
commit d051d1153c
920 changed files with 98871 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Lighweight client side representation of the repository data dictionary.
* This allows service calls to be kept to a minimum and for bean access, thus enabling JSF
* value binding expressions.
*
* @author gavinc
*/
public final class DataDictionary
{
private static Log logger = LogFactory.getLog(DataDictionary.class);
private DictionaryService dictionaryService;
private NamespaceService namespaceService;
private Map<QName, TypeDefinition> types = new HashMap<QName, TypeDefinition>(11, 1.0f);
/**
* Constructor
*
* @param dictionaryService The dictionary service to use to retrieve the data
*/
public DataDictionary(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Returns the type definition for the type represented by the given qname
*
* @param type The qname of the type to lookup the definition for
* @return The type definition for the requested type
*/
public TypeDefinition getTypeDef(QName type)
{
TypeDefinition typeDef = types.get(type);
if (typeDef == null)
{
typeDef = this.dictionaryService.getType(type);
if (typeDef != null)
{
types.put(type, typeDef);
}
}
return typeDef;
}
/**
* Returns the type definition for the type represented by the given qname
* and for all the given aspects
*
* @param type The type to retrieve the definition for
* @param optionalAspects A list of aspects to retrieve the definition for
* @return A unified type definition of the given type and aspects
*/
public TypeDefinition getTypeDef(QName type, Collection<QName> optionalAspects)
{
return this.dictionaryService.getAnonymousType(type, optionalAspects);
}
/**
* Returns the property definition for the given property on the given node
*
* @param node The node from which to get the property
* @param property The property to find the definition for
* @return The property definition or null if the property is not known
*/
public PropertyDefinition getPropertyDefinition(Node node, String property)
{
PropertyDefinition propDef = null;
TypeDefinition typeDef = getTypeDef(node.getType(), node.getAspects());
if (typeDef != null)
{
Map<QName, PropertyDefinition> properties = typeDef.getProperties();
propDef = properties.get(Repository.resolveToQName(property));
}
return propDef;
}
/**
* Returns the association definition for the given association on the given node
*
* @param node The node from which to get the association
* @param association The association to find the definition for
* @return The association definition or null if the association is not known
*/
public AssociationDefinition getAssociationDefinition(Node node, String association)
{
AssociationDefinition assocDef = null;
TypeDefinition typeDef = getTypeDef(node.getType(), node.getAspects());
if (typeDef != null)
{
Map<QName, AssociationDefinition> assocs = typeDef.getAssociations();
assocDef = assocs.get(Repository.resolveToQName(association));
}
return assocDef;
}
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
/**
* Lighweight client side representation of a node held in the repository, which
* is modelled as a map for use in the data tables.
*
* @author gavinc
*/
public class MapNode extends Node implements Map<String, Object>
{
private static final long serialVersionUID = 4051322327734433079L;
private boolean propsInitialised = false;
/**
* Constructor
*
* @param nodeRef The NodeRef this Node wrapper represents
*/
public MapNode(NodeRef nodeRef)
{
super(nodeRef);
}
/**
* Constructor
*
* @param nodeRef The NodeRef this Node wrapper represents
* @param nodeService The node service to use to retrieve data for this node
* @param initProps True to immediately init the properties of the node, false to do nothing
*/
public MapNode(NodeRef nodeRef, NodeService nodeService, boolean initProps)
{
super(nodeRef);
if (initProps == true)
{
getProperties();
}
}
// ------------------------------------------------------------------------------
// Map implementation - allows the Node bean to be accessed using JSF expression syntax
/**
* @see java.util.Map#clear()
*/
public void clear()
{
getProperties().clear();
}
/**
* @see java.util.Map#containsKey(java.lang.Object)
*/
public boolean containsKey(Object key)
{
return getProperties().containsKey(key);
}
/**
* @see java.util.Map#containsValue(java.lang.Object)
*/
public boolean containsValue(Object value)
{
return getProperties().containsKey(value);
}
/**
* @see java.util.Map#entrySet()
*/
public Set entrySet()
{
return getProperties().entrySet();
}
/**
* @see java.util.Map#get(java.lang.Object)
*/
public Object get(Object key)
{
Object obj = null;
// there are some things that aren't available as properties
// but from method calls, so for these handle them individually
Map<String, Object> props = getProperties();
if (propsInitialised == false)
{
// well known properties required as publically accessable map attributes
props.put("id", this.getId());
props.put("name", this.getName()); // TODO: perf test pulling back single prop here instead of all!
props.put("nodeRef", this.getNodeRef());
propsInitialised = true;
}
return props.get(key);
}
/**
* @see java.util.Map#isEmpty()
*/
public boolean isEmpty()
{
return getProperties().isEmpty();
}
/**
* @see java.util.Map#keySet()
*/
public Set keySet()
{
return getProperties().keySet();
}
/**
* @see java.util.Map#put(K, V)
*/
public Object put(String key, Object value)
{
return getProperties().put(key, value);
}
/**
* @see java.util.Map#putAll(java.util.Map)
*/
public void putAll(Map t)
{
getProperties().putAll(t);
}
/**
* @see java.util.Map#remove(java.lang.Object)
*/
public Object remove(Object key)
{
return getProperties().remove(key);
}
/**
* @see java.util.Map#size()
*/
public int size()
{
return getProperties().size();
}
/**
* @see java.util.Map#values()
*/
public Collection values()
{
return getProperties().values();
}
}

View File

@@ -0,0 +1,426 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.faces.context.FacesContext;
import org.alfresco.service.ServiceRegistry;
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.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Lighweight client side representation of a node held in the repository.
*
* @author gavinc
*/
public class Node implements Serializable
{
private static final long serialVersionUID = 3544390322739034169L;
protected static Log logger = LogFactory.getLog(Node.class);
protected NodeRef nodeRef;
private String name;
private QName type;
private String path;
private String id;
private Set<QName> aspects = null;
private Map<String, Boolean> permissions;
protected QNameNodeMap<String, Object> properties;
protected boolean propsRetrieved = false;
protected ServiceRegistry services = null;
private boolean childAssocsRetrieved = false;
private QNameNodeMap childAssociations;
private Map<String, Map<String, ChildAssociationRef>> childAssociationsAdded;
private Map<String, Map<String, ChildAssociationRef>> childAssociationsRemoved;
private boolean assocsRetrieved = false;
private QNameNodeMap associations;
private Map<String, Map<String, AssociationRef>> associationsAdded;
private Map<String, Map<String, AssociationRef>> associationsRemoved;
/**
* Constructor
*
* @param nodeRef The NodeRef this Node wrapper represents
*/
public Node(NodeRef nodeRef)
{
if (nodeRef == null)
{
throw new IllegalArgumentException("NodeRef must be supplied for creation of a Node.");
}
this.nodeRef = nodeRef;
this.id = nodeRef.getId();
this.properties = new QNameNodeMap<String, Object>(getServiceRegistry().getNamespaceService(), this);
}
/**
* @return All the properties known about this node.
*/
public Map<String, Object> getProperties()
{
if (this.propsRetrieved == false)
{
Map<QName, Serializable> props = getServiceRegistry().getNodeService().getProperties(this.nodeRef);
for (QName qname: props.keySet())
{
Serializable propValue = props.get(qname);
this.properties.put(qname.toString(), propValue);
}
this.propsRetrieved = true;
}
return this.properties;
}
/**
* @return All the associations this node has as a Map, using the association
* type as the key
*/
public final Map getAssociations()
{
if (this.assocsRetrieved == false)
{
associations = new QNameNodeMap(getServiceRegistry().getNamespaceService(), this);
List<AssociationRef> assocs = getServiceRegistry().getNodeService().getTargetAssocs(this.nodeRef, RegexQNamePattern.MATCH_ALL);
for (AssociationRef assocRef: assocs)
{
String assocName = assocRef.getTypeQName().toString();
List list = (List)this.associations.get(assocName);
// create the list if this is first association with 'assocName'
if (list == null)
{
list = new ArrayList<AssociationRef>();
this.associations.put(assocName, list);
}
// add the association to the list
list.add(assocRef);
}
this.assocsRetrieved = true;
}
return this.associations;
}
/**
* Returns all the associations added to this node in this UI session
*
* @return Map of Maps of AssociationRefs
*/
public final Map<String, Map<String, AssociationRef>> getAddedAssociations()
{
if (this.associationsAdded == null)
{
this.associationsAdded = new HashMap<String, Map<String, AssociationRef>>();
}
return this.associationsAdded;
}
/**
* Returns all the associations removed from this node is this UI session
*
* @return Map of Maps of AssociationRefs
*/
public final Map<String, Map<String, AssociationRef>> getRemovedAssociations()
{
if (this.associationsRemoved == null)
{
this.associationsRemoved = new HashMap<String, Map<String, AssociationRef>>();
}
return this.associationsRemoved;
}
/**
* @return All the child associations this node has as a Map, using the association
* type as the key
*/
public final Map getChildAssociations()
{
if (this.childAssocsRetrieved == false)
{
this.childAssociations = new QNameNodeMap(getServiceRegistry().getNamespaceService(), this);
List<ChildAssociationRef> assocs = getServiceRegistry().getNodeService().getChildAssocs(this.nodeRef);
for (ChildAssociationRef assocRef: assocs)
{
String assocName = assocRef.getTypeQName().toString();
List list = (List)this.childAssociations.get(assocName);
// create the list if this is first association with 'assocName'
if (list == null)
{
list = new ArrayList<ChildAssociationRef>();
this.childAssociations.put(assocName, list);
}
// add the association to the list
list.add(assocRef);
}
this.childAssocsRetrieved = true;
}
return this.childAssociations;
}
/**
* Returns all the child associations added to this node in this UI session
*
* @return Map of Maps of ChildAssociationRefs
*/
public final Map<String, Map<String, ChildAssociationRef>> getAddedChildAssociations()
{
if (this.childAssociationsAdded == null)
{
this.childAssociationsAdded = new HashMap<String, Map<String, ChildAssociationRef>>();
}
return this.childAssociationsAdded;
}
/**
* Returns all the child associations removed from this node is this UI session
*
* @return Map of Maps of ChildAssociationRefs
*/
public final Map<String, Map<String, ChildAssociationRef>> getRemovedChildAssociations()
{
if (this.childAssociationsRemoved == null)
{
this.childAssociationsRemoved = new HashMap<String, Map<String, ChildAssociationRef>>();
}
return this.childAssociationsRemoved;
}
/**
* Register a property resolver for the named property.
*
* @param name Name of the property this resolver is for
* @param resolver Property resolver to register
*/
public final void addPropertyResolver(String name, NodePropertyResolver resolver)
{
this.properties.addPropertyResolver(name, resolver);
}
/**
* Determines whether the given property name is held by this node
*
* @param propertyName Property to test existence of
* @return true if property exists, false otherwise
*/
public final boolean hasProperty(String propertyName)
{
return getProperties().containsKey(propertyName);
}
/**
* @return Returns the NodeRef this Node object represents
*/
public final NodeRef getNodeRef()
{
return this.nodeRef;
}
/**
* @return Returns the type.
*/
public final QName getType()
{
if (this.type == null)
{
this.type = getServiceRegistry().getNodeService().getType(this.nodeRef);
}
return type;
}
/**
* @return The display name for the node
*/
public final String getName()
{
if (this.name == null)
{
// try and get the name from the properties first
this.name = (String)getProperties().get("cm:name");
// if we didn't find it as a property get the name from the association name
if (this.name == null)
{
this.name = getServiceRegistry().getNodeService().getPrimaryParent(this.nodeRef).getQName().getLocalName();
}
}
return this.name;
}
/**
* @return The list of aspects applied to this node
*/
public final Set<QName> getAspects()
{
if (this.aspects == null)
{
this.aspects = getServiceRegistry().getNodeService().getAspects(this.nodeRef);
}
return this.aspects;
}
/**
* @param aspect The aspect to test for
* @return true if the node has the aspect false otherwise
*/
public final boolean hasAspect(QName aspect)
{
Set aspects = getAspects();
return aspects.contains(aspect);
}
/**
* Return whether the current user has the specified access permission on this Node
*
* @param permission Permission to validate against
*
* @return true if the permission is applied to the node for this user, false otherwise
*/
public final boolean hasPermission(String permission)
{
Boolean valid = null;
if (permissions != null)
{
valid = permissions.get(permission);
}
else
{
permissions = new HashMap<String, Boolean>(5, 1.0f);
}
if (valid == null)
{
PermissionService service = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getPermissionService();
valid = Boolean.valueOf(service.hasPermission(this.nodeRef, permission) == AccessStatus.ALLOWED);
permissions.put(permission, valid);
}
return valid.booleanValue();
}
/**
* @return The GUID for the node
*/
public final String getId()
{
return this.id;
}
/**
* @return The path for the node
*/
public final String getPath()
{
if (this.path == null)
{
this.path = getServiceRegistry().getNodeService().getPath(this.nodeRef).toString();
}
return this.path;
}
/**
* Resets the state of the node to force re-retrieval of the data
*/
public void reset()
{
this.name = null;
this.type = null;
this.path = null;
this.properties.clear();
this.propsRetrieved = false;
this.aspects = null;
this.permissions = null;
this.associations = null;
this.associationsAdded = null;
this.associationsRemoved = null;
this.assocsRetrieved = false;
this.childAssociations = null;
this.childAssociationsAdded = null;
this.childAssociationsRemoved = null;
this.childAssocsRetrieved = false;
}
/**
* Override Object.toString() to provide useful debug output
*/
public String toString()
{
if (getServiceRegistry().getNodeService() != null)
{
if (getServiceRegistry().getNodeService().exists(nodeRef))
{
return "Node Type: " + getType() +
"\nNode Properties: " + this.getProperties().toString() +
"\nNode Aspects: " + this.getAspects().toString();
}
else
{
return "Node no longer exists: " + nodeRef;
}
}
else
{
return super.toString();
}
}
protected ServiceRegistry getServiceRegistry()
{
if (this.services == null)
{
this.services = Repository.getServiceRegistry(FacesContext.getCurrentInstance());
}
return this.services;
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
/**
* Simple interface used to implement small classes capable of calculating dynamic property values
* for Nodes at runtime. This allows bean responsible for building large lists of Nodes to
* encapsulate the code needed to retrieve non-standard Node properties. The values are then
* calculated on demand by the property resolver.
*
* When a node is reset() the standard and other props are cleared. If property resolvers are used
* then the non-standard props will be restored automatically as well.
*
* @author Kevin Roast
*/
public interface NodePropertyResolver
{
/**
* Get the property value for this resolver
*
* @param node Node this property is for
*
* @return property value
*/
public Object get(Node node);
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QNameMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A extension of the repo QNameMap to provide custom property resolving support for Node wrappers.
*
* @author Kevin Roast
*/
public final class QNameNodeMap<K,V> extends QNameMap implements Map, Cloneable
{
private Node parent = null;
private Map<String, NodePropertyResolver> resolvers = new HashMap<String, NodePropertyResolver>(11, 1.0f);
/**
* Constructor
*
* @param parent Parent Node of the QNameNodeMap
*/
public QNameNodeMap(NamespacePrefixResolver resolver, Node parent)
{
super(resolver);
if (parent == null)
{
throw new IllegalArgumentException("Parent Node cannot be null!");
}
this.parent = parent;
}
/**
* Register a property resolver for the named property.
*
* @param name Name of the property this resolver is for
* @param resolver Property resolver to register
*/
public void addPropertyResolver(String name, NodePropertyResolver resolver)
{
this.resolvers.put(name, resolver);
}
/**
* @see java.util.Map#containsKey(java.lang.Object)
*/
public boolean containsKey(Object key)
{
return (this.contents.containsKey(Repository.resolveToQNameString((String)key)) ||
this.resolvers.containsKey(key));
}
/**
* @see java.util.Map#get(java.lang.Object)
*/
public Object get(Object key)
{
String qnameKey = Repository.resolveToQNameString(key.toString());
Object obj = this.contents.get(qnameKey);
if (obj == null)
{
// if a property resolver exists for this property name then invoke it
NodePropertyResolver resolver = this.resolvers.get(key.toString());
if (resolver != null)
{
obj = resolver.get(this.parent);
// cache the result
// obviously the cache is useless if the result is null, in most cases it shouldn't be
this.contents.put(qnameKey, obj);
}
}
return obj;
}
/**
* Perform a get without using property resolvers
*
* @param key item key
* @return object
*/
public Object getRaw(Object key)
{
return this.contents.get(Repository.resolveToQNameString((String)key));
}
/**
* Shallow copy the map by copying keys and values into a new QNameNodeMap
*/
public Object clone()
{
QNameNodeMap map = new QNameNodeMap(this.resolver, this.parent);
map.putAll(this);
if (this.resolvers.size() != 0)
{
map.resolvers = (Map)((HashMap)this.resolvers).clone();
}
return map;
}
}

View File

@@ -0,0 +1,620 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.configuration.ConfigurableService;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.metadata.MetadataExtracter;
import org.alfresco.repo.content.metadata.MetadataExtracterRegistry;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.web.app.Application;
import org.alfresco.web.ui.common.Utils;
import org.apache.log4j.Logger;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.jsf.FacesContextUtils;
/**
* Helper class for accessing repository objects, convert values, escape values and service utilities.
*
* @author gavinc
* @author kevinr
*/
public final class Repository
{
/** I18N error messages */
public static final String ERROR_NODEREF = "error_noderef";
public static final String ERROR_GENERIC = "error_generic";
public static final String ERROR_NOHOME = "error_homespace";
public static final String ERROR_SEARCH = "error_search";
private static final String METADATA_EXTACTER_REGISTRY = "metadataExtracterRegistry";
private static Logger logger = Logger.getLogger(Repository.class);
/** cache of client StoreRef */
private static StoreRef storeRef = null;
/** reference to Person folder */
private static NodeRef peopleRef = null;
/** reference to System folder */
private static NodeRef systemRef = null;
/** reference to the namespace service */
private static NamespaceService namespaceService = null;
/**
* Private constructor
*/
private Repository()
{
}
/**
* Returns a store reference object
*
* @return A StoreRef object
*/
public static StoreRef getStoreRef()
{
return storeRef;
}
/**
* Returns a store reference object.
* This method is used to setup the cached value by the ContextListener initialisation methods
*
* @return The StoreRef object
*/
public static StoreRef getStoreRef(ServletContext context)
{
storeRef = Application.getRepositoryStoreRef(context);
return storeRef;
}
/**
* Helper to get the display name for a Node.
* The method will attempt to use the "name" attribute, if not found it will revert to using
* the QName.getLocalName() retrieved from the primary parent relationship.
*
* @param ref NodeRef
*
* @return display name string for the specified Node.
*/
public static String getNameForNode(NodeService nodeService, NodeRef ref)
{
String name = null;
// try to find a display "name" property for this node
Object nameProp = nodeService.getProperty(ref, ContentModel.PROP_NAME);
if (nameProp != null)
{
name = nameProp.toString();
}
else
{
// revert to using QName if not found
QName qname = nodeService.getPrimaryParent(ref).getQName();
if (qname != null)
{
name = qname.getLocalName();
}
}
return name;
}
/**
* Escape a QName value so it can be used in lucene search strings
*
* @param qName QName to escape
*
* @return escaped value
*/
public static String escapeQName(QName qName)
{
String string = qName.toString();
StringBuilder buf = new StringBuilder(string.length() + 4);
for (int i = 0; i < string.length(); i++)
{
char c = string.charAt(i);
if ((c == '{') || (c == '}') || (c == ':') || (c == '-'))
{
buf.append('\\');
}
buf.append(c);
}
return buf.toString();
}
/**
* Return whether a Node is currently locked
*
* @param node The Node wrapper to test against
* @param lockService The LockService to use
*
* @return whether a Node is currently locked
*/
public static Boolean isNodeLocked(Node node, LockService lockService)
{
Boolean locked = Boolean.FALSE;
if (node.hasAspect(ContentModel.ASPECT_LOCKABLE))
{
LockStatus lockStatus = lockService.getLockStatus(node.getNodeRef());
if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
{
locked = Boolean.TRUE;
}
}
return locked;
}
/**
* Return whether a Node is currently locked by the current user
*
* @param node The Node wrapper to test against
* @param lockService The LockService to use
*
* @return whether a Node is currently locked by the current user
*/
public static Boolean isNodeOwnerLocked(Node node, LockService lockService)
{
Boolean locked = Boolean.FALSE;
if (node.hasAspect(ContentModel.ASPECT_LOCKABLE) &&
lockService.getLockStatus(node.getNodeRef()) == LockStatus.LOCK_OWNER)
{
locked = Boolean.TRUE;
}
return locked;
}
/**
* Return whether a WorkingCopy Node is owned by the current User
*
* @param node The Node wrapper to test against
* @param lockService The LockService to use
*
* @return whether a WorkingCopy Node is owned by the current User
*/
public static Boolean isNodeOwner(Node node, LockService lockService)
{
Boolean locked = Boolean.FALSE;
if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
{
Object obj = node.getProperties().get("workingCopyOwner");
if (obj instanceof String)
{
User user = Application.getCurrentUser(FacesContext.getCurrentInstance());
if ( ((String)obj).equals(user.getUserName()))
{
locked = Boolean.TRUE;
}
}
}
return locked;
}
/**
* Return the human readable form of the specified node Path. Fast version of the method that
* simply converts QName localname components to Strings.
*
* @param path Path to extract readable form from, excluding the final element
*
* @return human readable form of the Path excluding the final element
*/
public static String getDisplayPath(Path path)
{
StringBuilder buf = new StringBuilder(64);
for (int i=0; i<path.size()-1; i++)
{
String elementString = null;
Path.Element element = path.get(i);
if (element instanceof Path.ChildAssocElement)
{
ChildAssociationRef elementRef = ((Path.ChildAssocElement)element).getRef();
if (elementRef.getParentRef() != null)
{
elementString = elementRef.getQName().getLocalName();
}
}
else
{
elementString = element.getElementString();
}
if (elementString != null)
{
buf.append("/");
buf.append(elementString);
}
}
return buf.toString();
}
/**
* Resolve a Path by converting each element into its display NAME attribute
*
* @param path Path to convert
* @param separator Separator to user between path elements
* @param prefix To prepend to the path
*
* @return Path converted using NAME attribute on each element
*/
public static String getNamePath(NodeService nodeService, Path path, NodeRef rootNode, String separator, String prefix)
{
StringBuilder buf = new StringBuilder(128);
// ignore root node check if not passed in
boolean foundRoot = (rootNode == null);
buf.append(prefix);
// skip first element as it represents repo root '/'
for (int i=1; i<path.size(); i++)
{
Path.Element element = path.get(i);
String elementString = null;
if (element instanceof Path.ChildAssocElement)
{
ChildAssociationRef elementRef = ((Path.ChildAssocElement)element).getRef();
if (elementRef.getParentRef() != null)
{
// only append if we've found the root already
if (foundRoot == true)
{
Object nameProp = nodeService.getProperty(elementRef.getChildRef(), ContentModel.PROP_NAME);
if (nameProp != null)
{
elementString = nameProp.toString();
}
else
{
elementString = element.getElementString();
}
}
// either we've found root already or may have now
// check after as we want to skip the root as it represents the CIFS share name
foundRoot = (foundRoot || elementRef.getChildRef().equals(rootNode));
}
}
else
{
elementString = element.getElementString();
}
if (elementString != null)
{
buf.append(separator);
buf.append(elementString);
}
}
return buf.toString();
}
/**
* Return the mimetype code for the specified file name.
* <p>
* The file extension will be extracted from the filename and used to lookup the mimetype.
*
* @param context FacesContext
* @param filename Non-null filename to process
*
* @return mimetype for the specified filename - falls back to 'application/octet-stream' if not found.
*/
public static String getMimeTypeForFileName(FacesContext context, String filename)
{
// base the mimetype from the file extension
MimetypeService mimetypeService = (MimetypeService)getServiceRegistry(context).getMimetypeService();
// fall back to binary mimetype if no match found
String mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = filename.lastIndexOf('.');
if (extIndex != -1)
{
String ext = filename.substring(extIndex + 1).toLowerCase();
String mt = mimetypeService.getMimetypesByExtension().get(ext);
if (mt != null)
{
mimetype = mt;
}
}
return mimetype;
}
/**
* Return a UserTransaction instance
*
* @param context FacesContext
*
* @return UserTransaction
*/
public static UserTransaction getUserTransaction(FacesContext context)
{
TransactionService transactionService = getServiceRegistry(context).getTransactionService();
return transactionService.getUserTransaction();
}
/**
* Return a UserTransaction instance
*
* @param context FacesContext
* @param readonly Transaction readonly state
*
* @return UserTransaction
*/
public static UserTransaction getUserTransaction(FacesContext context, boolean readonly)
{
TransactionService transactionService = getServiceRegistry(context).getTransactionService();
return transactionService.getUserTransaction(readonly);
}
/**
* Return the Repository Service Registry
*
* @param context Faces Context
* @return the Service Registry
*/
public static ServiceRegistry getServiceRegistry(FacesContext context)
{
return (ServiceRegistry)FacesContextUtils.getRequiredWebApplicationContext(
context).getBean(ServiceRegistry.SERVICE_REGISTRY);
}
/**
* Return the Repository Service Registry
*
* @param context Servlet Context
* @return the Service Registry
*/
public static ServiceRegistry getServiceRegistry(ServletContext context)
{
return (ServiceRegistry)WebApplicationContextUtils.getRequiredWebApplicationContext(
context).getBean(ServiceRegistry.SERVICE_REGISTRY);
}
/**
* Return the Configurable Service
*
* @return the configurable service
*/
public static ConfigurableService getConfigurableService(FacesContext context)
{
return (ConfigurableService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("configurableService");
}
/**
* Return the Metadata Extracter Registry
*
* @param context Faces Context
* @return the MetadataExtracterRegistry
*/
public static MetadataExtracterRegistry getMetadataExtracterRegistry(FacesContext context)
{
return (MetadataExtracterRegistry)FacesContextUtils.getRequiredWebApplicationContext(
context).getBean(METADATA_EXTACTER_REGISTRY);
}
/**
* Extracts the metadata of a "raw" piece of content into a map.
*
* @param context Faces Context
* @param reader Content reader for the source content to extract from
* @param destination Map of metadata to set metadata values into
* @return True if an extracter was found
*/
public static boolean extractMetadata(FacesContext context, ContentReader reader, Map<QName, Serializable> destination)
{
// check that source mimetype is available
String mimetype = reader.getMimetype();
if (mimetype == null)
{
throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader);
}
// look for a transformer
MetadataExtracter extracter = getMetadataExtracterRegistry(context).getExtracter(mimetype);
if (extracter == null)
{
// No metadata extracter is not a failure, but we flag it
return false;
}
// we have a transformer, so do it
extracter.extract(reader, destination);
return true;
}
/**
* Query a list of Person type nodes from the repo
* It is currently assumed that all Person nodes exist below the Repository root node
*
* @param context Faces Context
* @param nodeService The node service
* @param searchService used to perform the search
* @return List of Person node objects
*/
public static List<Node> getUsers(FacesContext context, NodeService nodeService, SearchService searchService)
{
List<Node> personNodes = null;
UserTransaction tx = null;
try
{
tx = Repository.getUserTransaction(context, true);
tx.begin();
PersonService personService = (PersonService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("personService");
NodeRef peopleRef = personService.getPeopleContainer();
// TODO: better to perform an XPath search or a get for a specific child type here?
List<ChildAssociationRef> childRefs = nodeService.getChildAssocs(peopleRef);
personNodes = new ArrayList<Node>(childRefs.size());
for (ChildAssociationRef ref: childRefs)
{
// create our Node representation from the NodeRef
NodeRef nodeRef = ref.getChildRef();
if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_PERSON))
{
// create our Node representation
MapNode node = new MapNode(nodeRef);
// set data binding properties
// this will also force initialisation of the props now during the UserTransaction
// it is much better for performance to do this now rather than during page bind
Map<String, Object> props = node.getProperties();
props.put("fullName", ((String)props.get("firstName")) + ' ' + ((String)props.get("lastName")));
NodeRef homeFolderNodeRef = (NodeRef)props.get("homeFolder");
if (homeFolderNodeRef != null)
{
props.put("homeSpace", homeFolderNodeRef);
}
personNodes.add(node);
}
}
// commit the transaction
tx.commit();
}
catch (InvalidNodeRefException refErr)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_NODEREF), new Object[] {"root"}) );
personNodes = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
catch (Exception err)
{
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
context, Repository.ERROR_GENERIC), err.getMessage()), err );
personNodes = Collections.<Node>emptyList();
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
}
return personNodes;
}
/**
* Convert a property of unknown type to a String value. A native String value will be
* returned directly, else toString() will be executed, null is returned as null.
*
* @param value Property value
*
* @return value to String or null
*/
public static String safePropertyToString(Serializable value)
{
if (value == null)
{
return null;
}
else if (value instanceof String)
{
return (String)value;
}
else
{
return value.toString();
}
}
/**
* Creates a QName representation for the given String.
* If the String has no namespace the Alfresco namespace is added.
* If the String has a prefix an attempt to resolve the prefix to the
* full URI will be made.
*
* @param str The string to convert
* @return A QName representation of the given string
*/
public static QName resolveToQName(String str)
{
return QName.resolveToQName(getNamespaceService(), str);
}
/**
* Creates a string representation of a QName for the given string.
* If the given string already has a namespace, either a URL or a prefix,
* nothing the given string is returned. If it does not have a namespace
* the Alfresco namespace is added.
*
* @param str The string to convert
* @return A QName String representation of the given string
*/
public static String resolveToQNameString(String str)
{
return QName.resolveToQNameString(getNamespaceService(), str);
}
/**
* Returns an instance of the namespace service
*
* @return The NamespaceService
*/
private static NamespaceService getNamespaceService()
{
if (namespaceService == null)
{
ServiceRegistry svcReg = getServiceRegistry(FacesContext.getCurrentInstance());
namespaceService = svcReg.getNamespaceService();
}
return namespaceService;
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.web.bean.repository;
import java.util.List;
import javax.faces.context.FacesContext;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.configuration.ConfigurableService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
/**
* Bean that represents the currently logged in user
*
* @author gavinc
*/
public final class User
{
private String homeSpaceId;
private String userName;
private String ticket;
private NodeRef person;
private String fullName = null;
private Boolean administrator = null;
/** cached ref to our user preferences node */
private NodeRef preferencesFolderRef = null;
/**
* Constructor
*
* @param userName constructor for the user
*/
public User(String userName, String ticket, NodeRef person)
{
if (userName == null || ticket == null || person == null)
{
throw new IllegalArgumentException("All user details are mandatory!");
}
this.userName = userName;
this.ticket = ticket;
this.person = person;
}
/**
* @return The user name
*/
public String getUserName()
{
return this.userName;
}
/**
* Return the full name of the Person this User represents
*
* @param service NodeService to use
*
* @return The full name
*/
public String getFullName(NodeService service)
{
if (this.fullName == null)
{
this.fullName = service.getProperty(this.person, ContentModel.PROP_FIRSTNAME) + " " +
service.getProperty(this.person, ContentModel.PROP_LASTNAME);
}
return this.fullName;
}
/**
* @return Retrieves the user's home space (this may be the id of the company home space)
*/
public String getHomeSpaceId()
{
return this.homeSpaceId;
}
/**
* @param homeSpaceId Sets the id of the users home space
*/
public void setHomeSpaceId(String homeSpaceId)
{
this.homeSpaceId = homeSpaceId;
}
/**
* @return Returns the ticket.
*/
public String getTicket()
{
return this.ticket;
}
/**
* @return Returns the person NodeRef
*/
public NodeRef getPerson()
{
return this.person;
}
/**
* @return If the current user has Admin Authority
*/
public boolean isAdmin()
{
if (administrator == null)
{
administrator = Repository.getServiceRegistry(FacesContext.getCurrentInstance())
.getAuthorityService().hasAdminAuthority();
}
return administrator;
}
/**
* Get or create the node used to store user preferences.
* Utilises the 'configurable' aspect on the Person linked to this user.
*/
public synchronized NodeRef getUserPreferencesRef()
{
if (this.preferencesFolderRef == null)
{
FacesContext fc = FacesContext.getCurrentInstance();
ServiceRegistry registry = Repository.getServiceRegistry(fc);
NodeService nodeService = registry.getNodeService();
SearchService searchService = registry.getSearchService();
NamespaceService namespaceService = registry.getNamespaceService();
ConfigurableService configurableService = Repository.getConfigurableService(fc);
NodeRef person = Application.getCurrentUser(fc).getPerson();
if (nodeService.hasAspect(person, ContentModel.ASPECT_CONFIGURABLE) == false)
{
// create the configuration folder for this Person node
configurableService.makeConfigurable(person);
}
// target of the assoc is the configurations folder ref
NodeRef configRef = configurableService.getConfigurationFolder(person);
if (configRef == null)
{
throw new IllegalStateException("Unable to find associated 'configurations' folder for node: " + person);
}
String xpath = NamespaceService.APP_MODEL_PREFIX + ":" + "preferences";
List<NodeRef> nodes = searchService.selectNodes(
configRef,
xpath,
null,
namespaceService,
false);
NodeRef prefRef;
if (nodes.size() == 1)
{
prefRef = nodes.get(0);
}
else
{
// create the preferences Node for this user
ChildAssociationRef childRef = nodeService.createNode(
configRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.APP_MODEL_1_0_URI, "preferences"),
ContentModel.TYPE_CMOBJECT);
prefRef = childRef.getChildRef();
}
this.preferencesFolderRef = prefRef;
}
return this.preferencesFolderRef;
}
}