CM-690 virtualization

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@117474 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Bogdan Horje
2015-11-12 19:08:08 +00:00
parent c0f5336745
commit 4ed133e259
130 changed files with 17687 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import java.io.InputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
/**
* Dependency inversion facade of the Alfresco repository environment. It offers
* an interface to Alfresco repository capabilities needed for virtualization.
* Implementors should consider loose repository beans coupling when
* implementing the environment operations.
*
* @author Bogdan Horje
*/
public interface ActualEnvironment
{
QName getType(NodeRef nodeRef);
boolean isSubClass(QName className, QName ofClassName);
NodeRef getTargetAssocs(NodeRef nodeRef, QName aspectTypeQName);
Serializable getProperty(NodeRef nodeRef, QName qname) throws ActualEnvironmentException;
Map<QName, Serializable> getProperties(NodeRef nodeRef);
boolean hasAspect(NodeRef nodeRef, QName aspectTypeQName);
Set<QName> getAspects(NodeRef nodeRef);
String getCurrentUser();
Path getPath(NodeRef nodeRef);
ChildAssociationRef getPrimaryParent(NodeRef nodeRef);
List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern, QNamePattern qnamePattern,
int maxResults, boolean preload) throws InvalidNodeRefException;
NodeRef getChildByName(NodeRef nodeRef, QName assocTypeQName, String childName);
NamespacePrefixResolver getNamespacePrefixResolver();
InputStream openContentStream(NodeRef nodeRef) throws ActualEnvironmentException;
InputStream openContentStream(String classpath) throws ActualEnvironmentException;
ResultSet query(SearchParameters searchParameters);
Object executeScript(String classpath, Map<String, Object> model) throws ActualEnvironmentException;
Object executeScript(NodeRef templateNodeRef, Map<String, Object> model) throws ActualEnvironmentException;
Object createScriptVirtualContext(VirtualContext context) throws ActualEnvironmentException;
NodeRef findNodeRef(String referenceType, String[] reference);
NodeRef findQNamePath(String[] patheElements);
boolean exists(NodeRef nodeRef);
boolean exists(String classpath);
void delete(NodeRef nodeRef);
FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException;
ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update) throws InvalidNodeRefException,
InvalidTypeException;
void addAspect(NodeRef nodeRef, QName aspectTypeQName, Map<QName, Serializable> aspectProperties)
throws InvalidNodeRefException, InvalidAspectException;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 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.virtual;
public class ActualEnvironmentException extends VirtualizationException
{
/**
*
*/
private static final long serialVersionUID = 6411382816440744840L;
public ActualEnvironmentException()
{
super();
}
public ActualEnvironmentException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public ActualEnvironmentException(String message, Throwable cause)
{
super(message,
cause);
}
public ActualEnvironmentException(String message)
{
super(message);
}
public ActualEnvironmentException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* Dependency inversion facade of the Alfresco services. It provides access to
* the implementations of Alfresco services.
*
* @author Bogdan Horje
*/
public interface AlfrescoAPIFacet
{
@NotAuditable
ScriptService getScriptService();
@NotAuditable
NodeService getNodeService();
@NotAuditable
ContentService getContentService();
@NotAuditable
SearchService getSearchService();
@NotAuditable
DictionaryService getDictionaryService();
@NotAuditable
FileFolderService getFileFolderService();
@NotAuditable
PermissionService getPermissionService();
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import java.io.InputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.jscript.ClasspathScriptLocation;
import org.alfresco.repo.model.Repository;
import org.alfresco.repo.virtual.config.NodeRefResolver;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
public class AlfrescoEnviroment implements ActualEnvironment
{
private AlfrescoAPIFacet apiFacet;
private ServiceRegistry serviceRegistry;
private NamespacePrefixResolver namespacePrefixResolver;
private Repository repositoryHelper;
private NodeRefResolver nodeRefResolver;
public void setNodeRefResolver(NodeRefResolver nodeRefResolver)
{
this.nodeRefResolver = nodeRefResolver;
}
public void setAlfrescoAPIFacet(AlfrescoAPIFacet apiFacet)
{
this.apiFacet = apiFacet;
}
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
public void setRepositoryHelper(Repository repository)
{
this.repositoryHelper = repository;
}
@Override
public Object executeScript(String classpath, Map<String, Object> model)
{
return apiFacet.getScriptService().executeScript(new ClasspathScriptLocation(classpath.substring(1)),
model);
}
@Override
public Object executeScript(NodeRef templateNodeRef, Map<String, Object> model)
{
return apiFacet.getScriptService().executeScript(templateNodeRef,
null,
model);
}
@Override
public boolean hasAspect(final NodeRef nodeRef, final QName aspectTypeQName)
{
return apiFacet.getNodeService().hasAspect(nodeRef,
aspectTypeQName);
}
@Override
public Set<QName> getAspects(NodeRef nodeRef)
{
NodeService nodeService = apiFacet.getNodeService();
return nodeService.getAspects(nodeRef);
}
@Override
public NodeRef getTargetAssocs(NodeRef nodeRef, QName associationQName)
{
List<AssociationRef> assocs = apiFacet.getNodeService().getTargetAssocs(nodeRef,
associationQName);
if (assocs != null && assocs.size() >= 1)
{
AssociationRef associationRef = assocs.get(0);
NodeRef targetRef = associationRef.getTargetRef();
return targetRef;
}
else
{
return null;
}
}
@Override
public Serializable getProperty(NodeRef nodeRef, QName qname)
{
return apiFacet.getNodeService().getProperty(nodeRef,
qname);
}
@Override
public Map<QName, Serializable> getProperties(NodeRef nodeRef)
{
return apiFacet.getNodeService().getProperties(nodeRef);
}
@Override
public InputStream openContentStream(NodeRef nodeRef) throws ActualEnvironmentException
{
ContentReader contentReader = apiFacet.getContentService().getReader(nodeRef,
ContentModel.PROP_CONTENT);
return contentReader.getContentInputStream();
}
@Override
public InputStream openContentStream(String classpath) throws ActualEnvironmentException
{
return getClass().getResourceAsStream(classpath);
}
@Override
public ResultSet query(SearchParameters searchParameters)
{
return apiFacet.getSearchService().query(searchParameters);
}
@Override
public Object createScriptVirtualContext(VirtualContext context) throws ActualEnvironmentException
{
return new AlfrescoScriptVirtualContext(context,
serviceRegistry);
}
@Override
public QName getType(final NodeRef nodeRef)
{
return apiFacet.getNodeService().getType(nodeRef);
}
@Override
public boolean isSubClass(QName className, QName ofClassName)
{
return apiFacet.getDictionaryService().isSubClass(className,
ofClassName);
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
@Override
public NamespacePrefixResolver getNamespacePrefixResolver()
{
return namespacePrefixResolver;
}
@Override
public String getCurrentUser()
{
return serviceRegistry.getAuthenticationService().getCurrentUserName();
}
@Override
public Path getPath(NodeRef nodeRef)
{
return apiFacet.getNodeService().getPath(nodeRef);
}
@Override
public ChildAssociationRef getPrimaryParent(NodeRef nodeRef)
{
NodeService nodeService = apiFacet.getNodeService();
return nodeService.getPrimaryParent(nodeRef);
}
@Override
public List<ChildAssociationRef> getChildAssocs(NodeRef nodeRef, QNamePattern typeQNamePattern,
QNamePattern qnamePattern, int maxResults, boolean preload) throws InvalidNodeRefException
{
NodeService nodeService = apiFacet.getNodeService();
return nodeService.getChildAssocs(nodeRef,
typeQNamePattern,
qnamePattern,
maxResults,
preload);
}
@Override
public NodeRef findNodeRef(String referenceType, String[] reference)
{
return repositoryHelper.findNodeRef(referenceType,
reference);
}
@Override
public boolean exists(NodeRef nodeRef)
{
return apiFacet.getNodeService().exists(nodeRef);
}
@Override
public NodeRef getChildByName(NodeRef nodeRef, QName assocTypeQName, String childName)
{
return apiFacet.getNodeService().getChildByName(nodeRef,
assocTypeQName,
childName);
}
@Override
public void delete(NodeRef nodeRef)
{
apiFacet.getNodeService().deleteNode(nodeRef);
}
@Override
public FileInfo create(NodeRef parentNodeRef, String name, QName typeQName) throws FileExistsException
{
return apiFacet.getFileFolderService().create(parentNodeRef,
name,
typeQName);
}
@Override
public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update)
throws InvalidNodeRefException, InvalidTypeException
{
return apiFacet.getContentService().getWriter(nodeRef,
propertyQName,
update);
}
@Override
public void addAspect(NodeRef nodeRef, QName aspectTypeQName, Map<QName, Serializable> aspectProperties)
throws InvalidNodeRefException, InvalidAspectException
{
apiFacet.getNodeService().addAspect(nodeRef,
aspectTypeQName,
aspectProperties);
}
@Override
public NodeRef findQNamePath(String[] patheElements)
{
return nodeRefResolver.resolveQNameReference(patheElements);
}
@Override
public boolean exists(String classpath)
{
ClassLoader cl = this.getClass().getClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
Resource resource = resolver.getResource("classpath:" + classpath);
return resource.exists();
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.ServiceRegistry;
/**
* JavaScript API {@link VirtualContext} adapter.
*
* @author Bogdan Horje
*/
public class AlfrescoScriptVirtualContext extends BaseScopableProcessorExtension
{
// TODO: extract placeholder interface. make placeholders configurable.
public static final String CURRENT_USER_PH = "CURRENT_USER";
public static final String ACTUAL_PATH_PH = "ACTUAL_PATH";
private VirtualContext context;
private ServiceRegistry serviceRegistry;
private Map<String, String> placeholders;
public AlfrescoScriptVirtualContext(VirtualContext context, ServiceRegistry serviceRegistry)
{
super();
this.context = context;
this.serviceRegistry = serviceRegistry;
this.placeholders = createPlaceHolders();
}
// TODO: extract placeholder interface. make placeholders configurable.
private Map<String, String> createPlaceHolders()
{
Map<String, String> newPlaceholders = new HashMap<>();
String user = AuthenticationUtil.getFullyAuthenticatedUser();
// TODO: extract open-close-configurable placeholders
newPlaceholders.put(CURRENT_USER_PH,
user);
// TODO: can we replace getQnamePath usage
newPlaceholders.put(ACTUAL_PATH_PH,
getActualNode().getQnamePath());
return newPlaceholders;
}
public Map<String, String> getPlaceholders()
{
return placeholders;
}
public synchronized ScriptNode getActualNode()
{
return new ScriptNode(context.getActualNodeRef(),
serviceRegistry,
getScope());
}
public Object getParameter(String param)
{
return context.getParameter(param);
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* Implementation of the {@link AlfrescoAPIFacet} interface that provides access
* to "core" Alfresco services, i.e. services in a lower abstraction layer than
* the ones provided in the Java API, by the {@link ServiceRegistry}.
*
* @author Bogdan Horje
*/
public class CoreAPIFacet implements AlfrescoAPIFacet
{
private ScriptService scriptService;
private NodeService nodeService;
private ContentService contentService;
private SearchService searchService;
private DictionaryService dictionaryService;
private FileFolderService fileFolderService;
private PermissionService permissionService;
public void setScriptService(ScriptService scriptService)
{
this.scriptService = scriptService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
@Override
public ScriptService getScriptService()
{
return scriptService;
}
@Override
public NodeService getNodeService()
{
return nodeService;
}
@Override
public ContentService getContentService()
{
return contentService;
}
@Override
public SearchService getSearchService()
{
return searchService;
}
@Override
public DictionaryService getDictionaryService()
{
return dictionaryService;
}
@Override
public FileFolderService getFileFolderService()
{
return fileFolderService;
}
@Override
public PermissionService getPermissionService()
{
return permissionService;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
/**
* Implementation of the {@link AlfrescoAPIFacet} interface that provides access
* to Alfresco services at the level of the Java API, through its
* {@link ServiceRegistry} instance.
*
* @author Bogdan Horje
*/
public class PublicAPIFacet implements AlfrescoAPIFacet
{
private ServiceRegistry serviceRegistry;
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
@Override
public ScriptService getScriptService()
{
return serviceRegistry.getScriptService();
}
@Override
public NodeService getNodeService()
{
return serviceRegistry.getNodeService();
}
@Override
public ContentService getContentService()
{
return serviceRegistry.getContentService();
}
@Override
public SearchService getSearchService()
{
return serviceRegistry.getSearchService();
}
@Override
public DictionaryService getDictionaryService()
{
return serviceRegistry.getDictionaryService();
}
@Override
public FileFolderService getFileFolderService()
{
return serviceRegistry.getFileFolderService();
}
@Override
public PermissionService getPermissionService()
{
return serviceRegistry.getPermissionService();
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import org.alfresco.service.namespace.QName;
/**
* Virtual Content Model Constants
*
* @author Bogdan Horje
*/
public interface VirtualContentModel
{
static final String VIRTUAL_CONTENT_MODEL_1_0_URI = "http://www.alfresco.org/model/content/virtual/1.0";
static final QName ASPECT_VIRTUAL = QName.createQName(VIRTUAL_CONTENT_MODEL_1_0_URI,
"virtual");
static final QName ASPECT_VIRTUAL_DOCUMENT = QName.createQName(VIRTUAL_CONTENT_MODEL_1_0_URI,
"virtual-document");
static final QName TYPE_VIRTUAL_FOLDER_TEMPLATE = QName.createQName(VIRTUAL_CONTENT_MODEL_1_0_URI,
"virtualFolderTemplate");
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2005-2015 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.virtual;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* The context in which a virtualization process takes place.
*
* @author Bogdan Horje
*/
public class VirtualContext
{
public static final String CONTEXT_PARAM = "context";
public static final String PLACEHOLDERS_PARAM = "placeholders";
private Map<String, Object> parameters;
private NodeRef actualNodeRef;
private ActualEnvironment actualEnviroment;
public VirtualContext(VirtualContext context)
{
this(context.actualEnviroment,
context.actualNodeRef,
new HashMap<String, Object>(context.parameters));
}
public VirtualContext(ActualEnvironment actualEnviroment, NodeRef actualNodeRef)
{
this(actualEnviroment,
actualNodeRef,
new HashMap<String, Object>());
}
public VirtualContext(ActualEnvironment actualEnviroment, NodeRef actualNodeRef, Map<String, Object> parameters)
{
this.parameters = parameters;
this.parameters.put(CONTEXT_PARAM,
this);
this.actualEnviroment = actualEnviroment;
this.actualNodeRef = actualNodeRef;
}
public ActualEnvironment getActualEnviroment()
{
return actualEnviroment;
}
public NodeRef getActualNodeRef()
{
return actualNodeRef;
}
public void setParameter(String parameter, Object value)
{
parameters.put(parameter,
value);
}
public Map<String, Object> getParameters()
{
return new HashMap<>(parameters);
}
@Override
public int hashCode()
{
return actualNodeRef.hashCode();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof VirtualContext)
{
VirtualContext ctxObj = (VirtualContext) obj;
return actualNodeRef.equals(ctxObj.actualNodeRef);
}
else
{
return false;
}
}
@Override
public String toString()
{
return actualNodeRef.toString();
}
public Object getParameter(String param)
{
return parameters.get(param);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 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.virtual;
public class VirtualizationException extends RuntimeException
{
/**
*
*/
private static final long serialVersionUID = -5117143626926061650L;
public VirtualizationException()
{
super();
}
public VirtualizationException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public VirtualizationException(String message, Throwable cause)
{
super(message,
cause);
}
public VirtualizationException(String message)
{
super(message);
}
public VirtualizationException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.text.Collator;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.AlfrescoCollator;
import org.alfresco.util.Pair;
import org.springframework.extensions.surf.util.I18NUtil;
public class FileInfoPropsComparator implements Comparator<FileInfo>
{
private List<Pair<QName, Boolean>> sortProps;
private Collator collator;
public FileInfoPropsComparator(List<Pair<QName, Boolean>> sortProps)
{
this.sortProps = sortProps;
this.collator = AlfrescoCollator.getInstance(I18NUtil.getContentLocale());
}
@Override
public int compare(FileInfo n1, FileInfo n2)
{
return compareImpl(n1,
n2,
sortProps);
}
private int compareImpl(FileInfo node1In, FileInfo node2In, List<Pair<QName, Boolean>> sortProps)
{
Object pv1 = null;
Object pv2 = null;
QName sortPropQName = (QName) sortProps.get(0).getFirst();
boolean sortAscending = sortProps.get(0).getSecond();
FileInfo node1 = node1In;
FileInfo node2 = node2In;
if (sortAscending == false)
{
node1 = node2In;
node2 = node1In;
}
int result = 0;
pv1 = node1.getProperties().get(sortPropQName);
pv2 = node2.getProperties().get(sortPropQName);
if (pv1 == null)
{
if (pv2 == null && sortProps.size() > 1)
{
return compareImpl(node1In,
node2In,
sortProps.subList(1,
sortProps.size()));
}
else
{
return (pv2 == null ? 0 : -1);
}
}
else if (pv2 == null)
{
return 1;
}
if (pv1 instanceof String)
{
result = collator.compare((String) pv1,
(String) pv2); // TODO: use collation keys
// (re: performance)
}
else if (pv1 instanceof Date)
{
result = (((Date) pv1).compareTo((Date) pv2));
}
else if (pv1 instanceof Long)
{
result = (((Long) pv1).compareTo((Long) pv2));
}
else if (pv1 instanceof Integer)
{
result = (((Integer) pv1).compareTo((Integer) pv2));
}
else if (pv1 instanceof QName)
{
result = (((QName) pv1).compareTo((QName) pv2));
}
else if (pv1 instanceof Boolean)
{
result = (((Boolean) pv1).compareTo((Boolean) pv2));
}
else
{
throw new RuntimeException("Unsupported sort type: " + pv1.getClass().getName());
}
if ((result == 0) && (sortProps.size() > 1))
{
return compareImpl(node1In,
node2In,
sortProps.subList(1,
sortProps.size()));
}
return result;
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ref.AbstractProtocolMethod;
import org.alfresco.repo.virtual.ref.GetActualNodeRefMethod;
import org.alfresco.repo.virtual.ref.NodeProtocol;
import org.alfresco.repo.virtual.ref.ProtocolMethodException;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.ReferenceEncodingException;
import org.alfresco.repo.virtual.ref.VirtualProtocol;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.Path;
public class GetPathMethod extends AbstractProtocolMethod<Path>
{
private VirtualStore virtualStore;
private ActualEnvironment environment;
public GetPathMethod(VirtualStore virtualStore, ActualEnvironment actualEnvironment)
{
super();
this.virtualStore = virtualStore;
this.environment = actualEnvironment;
}
@Override
public Path execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
try
{
NodeRef actualNodeRef = reference.execute(new GetActualNodeRefMethod(environment));
Path path = null;
if (actualNodeRef == null)
{
// Although not a feature yet, pure-virtual-references should
// use an empty path as root since pure-virtual-references have
// no actual peer to use.
path = new Path();
}
else
{
path = environment.getPath(actualNodeRef);
}
Path virtualPath = virtualStore.getPath(reference);
return path.append(virtualPath);
}
catch (ReferenceEncodingException e)
{
throw new ProtocolMethodException(e);
}
}
@Override
public Path execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
Reference parent = protocol.getVirtualParentReference(reference);
NodeRef nodeRef = protocol.getNodeRef(reference);
Path nodeRefPath = environment.getPath(nodeRef);
Path parentPath = parent.execute(this);
parentPath.append(nodeRefPath.last());
return parentPath;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import org.alfresco.repo.domain.permissions.Acl;
import org.alfresco.repo.domain.permissions.traitextender.AccessControlListDAOExtension;
import org.alfresco.repo.domain.permissions.traitextender.AccessControlListDAOTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ref.GetActualNodeRefMethod;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualAccessControlListDAOExtension
extends SpringBeanExtension<AccessControlListDAOExtension, AccessControlListDAOTrait>
implements AccessControlListDAOExtension
{
private ActualEnvironment environment;
public VirtualAccessControlListDAOExtension()
{
super(AccessControlListDAOTrait.class);
}
public void setEnvironment(ActualEnvironment environment)
{
this.environment = environment;
}
@Override
public Acl getAccessControlList(NodeRef nodeRef)
{
if (Reference.isReference(nodeRef))
{
Reference vRef = Reference.fromNodeRef(nodeRef);
NodeRef actual = vRef.execute(new GetActualNodeRefMethod(environment));
return getTrait().getAccessControlList(actual);
}
return getTrait().getAccessControlList(nodeRef);
}
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.coci.traitextender.CheckOutCheckInServiceExtension;
import org.alfresco.repo.coci.traitextender.CheckOutCheckInServiceTrait;
import org.alfresco.repo.virtual.ref.GetParentReferenceMethod;
import org.alfresco.repo.virtual.ref.NodeProtocol;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualCheckOutCheckInServiceExtension extends
SpringBeanExtension<CheckOutCheckInServiceExtension, CheckOutCheckInServiceTrait> implements
CheckOutCheckInServiceExtension
{
public VirtualCheckOutCheckInServiceExtension()
{
super(CheckOutCheckInServiceTrait.class);
}
private VirtualStore virtualStore;
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
@Override
public NodeRef checkout(NodeRef nodeRef, NodeRef destinationParentNodeRef, QName destinationAssocTypeQName,
QName destinationAssocQName)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialNodeRef = virtualStore.materializeIfPossible(nodeRef);
NodeRef materialDestination = virtualStore.materializeIfPossible(destinationParentNodeRef);
NodeRef workingCopy = theTrait.checkout(materialNodeRef,
materialDestination,
destinationAssocTypeQName,
destinationAssocQName);
if (Reference.isReference(destinationParentNodeRef))
{
Reference parentReference = Reference.fromNodeRef(destinationParentNodeRef);
Reference workingCopyReference = NodeProtocol.newReference(workingCopy,
parentReference);
return workingCopyReference.toNodeRef(workingCopy.getStoreRef());
}
else
{
return workingCopy;
}
}
@Override
public NodeRef checkout(NodeRef nodeRef)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialNodeRef = virtualStore.materializeIfPossible(nodeRef);
NodeRef workingCopy = theTrait.checkout(materialNodeRef);
return virtualizeOriginalIfNeeded(nodeRef,
workingCopy);
}
@Override
public NodeRef checkin(NodeRef workingCopyNodeRef, Map<String, Serializable> versionProperties, String contentUrl,
boolean keepCheckedOut)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialWorkingCopy = virtualStore.materializeIfPossible(workingCopyNodeRef);
NodeRef materialOriginalNode = theTrait.checkin(materialWorkingCopy,
versionProperties,
contentUrl,
keepCheckedOut);
return virtualizeOriginalIfNeeded(workingCopyNodeRef,
materialOriginalNode);
}
@Override
public NodeRef checkin(NodeRef workingCopyNodeRef, Map<String, Serializable> versionProperties, String contentUrl)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialWorkingCopy = virtualStore.materializeIfPossible(workingCopyNodeRef);
NodeRef materialOriginalNode = theTrait.checkin(materialWorkingCopy,
versionProperties,
contentUrl);
return virtualizeOriginalIfNeeded(workingCopyNodeRef,
materialOriginalNode);
}
private NodeRef virtualizeOriginalIfNeeded(NodeRef workingCopyNodeRef, NodeRef materialOriginalNode)
{
if (materialOriginalNode != null && Reference.isReference(workingCopyNodeRef))
{
Reference workingCopyReference = Reference.fromNodeRef(workingCopyNodeRef);
Reference parentReference = workingCopyReference.execute(new GetParentReferenceMethod());
Reference originalReference = NodeProtocol.newReference(materialOriginalNode,
parentReference);
return originalReference.toNodeRef(materialOriginalNode.getStoreRef());
}
else
{
return materialOriginalNode;
}
}
@Override
public NodeRef checkin(NodeRef workingCopyNodeRef, Map<String, Serializable> versionProperties)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialWorkingCopy = virtualStore.materializeIfPossible(workingCopyNodeRef);
NodeRef materialOriginalNode = theTrait.checkin(materialWorkingCopy,
versionProperties);
return virtualizeOriginalIfNeeded(workingCopyNodeRef,
materialOriginalNode);
}
@Override
public NodeRef cancelCheckout(NodeRef workingCopyNodeRef)
{
return getTrait().cancelCheckout(virtualStore.materializeIfPossible(workingCopyNodeRef));
}
@Override
public NodeRef getWorkingCopy(NodeRef nodeRef)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialWorkingCopy = theTrait.getWorkingCopy(virtualStore.materializeIfPossible(nodeRef));
return virtualizeVersionIfNeeded(nodeRef,
materialWorkingCopy);
}
private NodeRef virtualizeVersionIfNeeded(NodeRef originalNodeRef, NodeRef materialVersion)
{
if (materialVersion != null && Reference.isReference(originalNodeRef)
&& !Reference.isReference(materialVersion))
{
Reference reference = Reference.fromNodeRef(originalNodeRef);
Reference parentReference = reference.execute(new GetParentReferenceMethod());
Reference workingCopyReference = NodeProtocol.newReference(materialVersion,
parentReference);
return workingCopyReference.toNodeRef(materialVersion.getStoreRef());
}
else
{
return materialVersion;
}
}
@Override
public NodeRef getCheckedOut(NodeRef nodeRef)
{
CheckOutCheckInServiceTrait theTrait = getTrait();
NodeRef materialChekedOut = theTrait.getCheckedOut(virtualStore.materializeIfPossible(nodeRef));
return virtualizeVersionIfNeeded(nodeRef,
materialChekedOut);
}
@Override
public boolean isWorkingCopy(NodeRef nodeRef)
{
return getTrait().isWorkingCopy(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public boolean isCheckedOut(NodeRef nodeRef)
{
return getTrait().isCheckedOut(virtualStore.materializeIfPossible(nodeRef));
}
}

View File

@@ -0,0 +1,40 @@
package org.alfresco.repo.virtual.bundle;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.traitextender.DefaultCopyBehaviourCallbackExtension;
import org.alfresco.repo.copy.traitextender.DefaultCopyBehaviourCallbackTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.VirtualContentModel;
import org.alfresco.service.namespace.QName;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualDefaultCopyBehaviourCallbackExtension extends
SpringBeanExtension<DefaultCopyBehaviourCallbackExtension, DefaultCopyBehaviourCallbackTrait> implements
DefaultCopyBehaviourCallbackExtension
{
private ActualEnvironment environment;
public VirtualDefaultCopyBehaviourCallbackExtension()
{
super(DefaultCopyBehaviourCallbackTrait.class);
}
public void setEnvironment(ActualEnvironment environment)
{
this.environment = environment;
}
@Override
public boolean getMustCopy(QName classQName, CopyDetails copyDetails)
{
if(environment.isSubClass(classQName, ContentModel.TYPE_FOLDER)){
if(copyDetails.getSourceNodeAspectQNames().contains(VirtualContentModel.ASPECT_VIRTUAL)){
return false;
}
}
return getTrait().getMustCopy(classQName,
copyDetails);
}
}

View File

@@ -0,0 +1,496 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.model.filefolder.traitextender.FileFolderServiceExtension;
import org.alfresco.repo.model.filefolder.traitextender.FileFolderServiceTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.repo.virtual.page.PageCollationException;
import org.alfresco.repo.virtual.page.PageCollator;
import org.alfresco.repo.virtual.page.PageCollator.PagingResultsSource;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.ReferenceEncodingException;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderServiceType;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.traitextender.SpringBeanExtension;
import org.alfresco.util.Pair;
public class VirtualFileFolderServiceExtension extends SpringBeanExtension<FileFolderServiceExtension, FileFolderServiceTrait>
implements FileFolderServiceExtension
{
private VirtualStore virtualStore;
private ActualEnvironment environment;
public VirtualFileFolderServiceExtension()
{
super(FileFolderServiceTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
public void setEnvironment(ActualEnvironment environment)
{
this.environment = environment;
}
public List<FileInfo> asFileInfos(List<Reference> references, VirtualStore virtualStore,
ActualEnvironment environment) throws VirtualizationException
{
List<FileInfo> fileInfos = new LinkedList<>();
for (Reference reference : references)
{
FileInfo fileInfo = asFileInfo(virtualStore,
environment,
reference);
fileInfos.add(fileInfo);
}
return fileInfos;
}
public FileInfo asFileInfo(VirtualStore virtualStore, ActualEnvironment environment, Reference reference)
throws VirtualizationException
{
Map<QName, Serializable> properties = virtualStore.getProperties(reference);
QName qNameType = virtualStore.getType(reference);
FileFolderServiceType type = getTrait().getType(qNameType);
boolean isFolder = type.equals(FileFolderServiceType.FOLDER);
NodeRef nodeRef = reference.toNodeRef();
return getTrait().createFileInfo(nodeRef,
qNameType,
isFolder,
false,
properties);
}
@Override
public List<FileInfo> list(NodeRef contextNodeRef)
{
if (canVirtualize(contextNodeRef))
{
Reference reference = virtualStore.virtualize(contextNodeRef);
List<Reference> virtualNodes = virtualStore.list(reference);
List<FileInfo> searchResult = asFileInfos(virtualNodes,
virtualStore,
environment);
if (mergeActualNode(reference))
{
List<FileInfo> actualSearch = getTrait().list(actualNodeFrom(reference));
searchResult.addAll(actualSearch);
}
return searchResult;
}
else
{
return getTrait().list(contextNodeRef);
}
}
protected boolean mergeActualNode(Reference reference) throws VirtualizationException
{
return virtualStore.canMaterialize(reference);
}
protected NodeRef actualNodeFrom(Reference reference) throws VirtualizationException
{
return virtualStore.materialize(reference);
}
protected boolean canVirtualize(NodeRef nodeRef) throws VirtualizationException
{
return virtualStore.canVirtualize(nodeRef);
}
private Set<QName>[] buildSearchAndIgnore(final boolean files, final boolean folders, Set<QName> ignoreQNames)
{
Set<QName>[] searchAndIgnore = (Set<QName>[]) Array.newInstance(Set.class,
3);
Pair<Set<QName>, Set<QName>> searchTypesAndIgnoreAspects = getTrait()
.buildSearchTypesAndIgnoreAspects(files,
folders,
ignoreQNames);
if (searchTypesAndIgnoreAspects != null)
{
Set<QName> searchTypesQNames = searchTypesAndIgnoreAspects.getFirst();
Set<QName> ignoreAspectsQNames = searchTypesAndIgnoreAspects.getSecond();
Set<QName> ignoreTypesQNames = null;
if ((searchTypesQNames != null || ignoreAspectsQNames != null) && ignoreQNames!=null)
{
ignoreTypesQNames = new HashSet<>(ignoreQNames);
if (searchTypesQNames != null)
{
ignoreTypesQNames.removeAll(searchTypesQNames);
}
if (ignoreAspectsQNames != null)
{
ignoreTypesQNames.removeAll(ignoreAspectsQNames);
}
}
searchAndIgnore[0] = searchTypesQNames;
searchAndIgnore[1] = ignoreTypesQNames;
searchAndIgnore[2] = ignoreAspectsQNames;
}
return searchAndIgnore;
}
@Override
public PagingResults<FileInfo> list(final NodeRef contextNodeRef, final boolean files, final boolean folders,
final String pattern, final Set<QName> ignoreQNames, final List<Pair<QName, Boolean>> sortProps,
final PagingRequest pagingRequest)
{
final FileFolderServiceTrait theTrait = getTrait();
if (canVirtualize(contextNodeRef))
{
final Reference reference = virtualStore.virtualize(contextNodeRef);
Set<QName>[] searchAndIgnore = buildSearchAndIgnore(files,
folders,
ignoreQNames);
if (mergeActualNode(reference))
{
PagingResults<Reference> virtualChildren = virtualStore.list(reference,
false,
true,
files,
folders,
pattern,
searchAndIgnore[1],
searchAndIgnore[2],
sortProps,
new PagingRequest(0));
PagingResultsSource<FileInfo> superSource = new PagingResultsSource<FileInfo>()
{
@Override
public PagingResults<FileInfo> retrieve(PagingRequest pr) throws PageCollationException
{
try
{
PagingResults<FileInfo> result = theTrait.list(actualNodeFrom(reference),
files,
folders,
pattern,
ignoreQNames,
sortProps,
pr);
return result;
}
catch (VirtualizationException e)
{
throw new PageCollationException(e);
}
}
};
FileInfoPropsComparator comparator = (sortProps != null && !sortProps.isEmpty()) ? new FileInfoPropsComparator(sortProps)
: null;
try
{
return new PageCollator<FileInfo>().collate(asFileInfoResults(environment,
virtualChildren,
virtualStore).getPage(),
superSource,
pagingRequest,
comparator);
}
catch (PageCollationException error)
{
throw new VirtualizationException(error);
}
}
else
{
PagingResults<Reference> children = virtualStore.list(reference,
true,
true,
files,
folders,
pattern,
searchAndIgnore[1],
searchAndIgnore[2],
sortProps,
pagingRequest);
return asFileInfoResults(environment,
children,
virtualStore);
}
}
else
{
return theTrait.list(contextNodeRef,
files,
folders,
pattern,
ignoreQNames,
sortProps,
pagingRequest);
}
}
public PagingResults<FileInfo> asFileInfoResults(ActualEnvironment environment,
final PagingResults<Reference> results, VirtualStore store) throws ReferenceEncodingException,
VirtualizationException
{
List<Reference> virtualPage = results.getPage();
final LinkedList<FileInfo> page = new LinkedList<FileInfo>();
for (Reference ref : virtualPage)
{
FileInfo fileInfo = asFileInfo(store,
environment,
ref);
page.add(fileInfo);
}
final boolean hasMoreItems = results.hasMoreItems();
final Pair<Integer, Integer> totalResultCount = results.getTotalResultCount();
final String queryExecutionId = results.getQueryExecutionId();
return new PagingResults<FileInfo>()
{
@Override
public List<FileInfo> getPage()
{
return page;
}
@Override
public String getQueryExecutionId()
{
return queryExecutionId;
}
@Override
public Pair<Integer, Integer> getTotalResultCount()
{
return totalResultCount;
}
@Override
public boolean hasMoreItems()
{
return hasMoreItems;
}
};
}
@Override
public PagingResults<FileInfo> list(final NodeRef rootNodeRef, final Set<QName> searchTypeQNames,
final Set<QName> ignoreAspectQNames, final List<Pair<QName, Boolean>> sortProps,
final PagingRequest pagingRequest)
{
if (canVirtualize(rootNodeRef))
{
final Reference reference = virtualStore.virtualize(rootNodeRef);
List<Pair<QName, Boolean>> sortingPropoerties = sortProps;
if (sortingPropoerties == null || sortingPropoerties.isEmpty())
{
sortingPropoerties = Arrays.asList(new Pair<QName, Boolean>(ContentModel.PROP_NAME,
true));
}
if (mergeActualNode(reference))
{
PagingResults<Reference> virtualChildren = virtualStore.list(reference,
false,
true,
searchTypeQNames,
Collections.<QName> emptySet(),
ignoreAspectQNames,
sortProps,
new PagingRequest(0));
PagingResultsSource<FileInfo> superSource = new PagingResultsSource<FileInfo>()
{
@Override
public PagingResults<FileInfo> retrieve(PagingRequest pr) throws PageCollationException
{
try
{
PagingResults<FileInfo> result = getTrait().list(actualNodeFrom(reference),
searchTypeQNames,
ignoreAspectQNames,
sortProps,
pr);
return result;
}
catch (VirtualizationException e)
{
throw new PageCollationException(e);
}
}
};
FileInfoPropsComparator comparator = new FileInfoPropsComparator(sortingPropoerties);
try
{
return new PageCollator<FileInfo>().collate(asFileInfoResults(environment,
virtualChildren,
virtualStore).getPage(),
superSource,
pagingRequest,
comparator);
}
catch (PageCollationException error)
{
throw new VirtualizationException(error);
}
}
else
{
PagingResults<Reference> children = virtualStore.list(reference,
true,
true,
searchTypeQNames,
Collections.<QName> emptySet(),
ignoreAspectQNames,
sortingPropoerties,
pagingRequest);
return asFileInfoResults(environment,
children,
virtualStore);
}
}
return getTrait().list(rootNodeRef,
searchTypeQNames,
ignoreAspectQNames,
sortProps,
pagingRequest);
}
@Override
public List<FileInfo> search(NodeRef contextNodeRef, String namePattern, boolean includeSubFolders)
{
return search(contextNodeRef,
namePattern,
true,
true,
false);
}
@Override
public List<FileInfo> search(NodeRef contextNodeRef, String namePattern, boolean fileSearch, boolean folderSearch,
boolean includeSubFolders)
{
// We merge the virtual search results wit actual results only in case
// that
// namePattern is null or *, since the right search results are obtained
// from
// searchService.selectNodes() that uses getChildAssociation from
// VirtualNodeService witch was implemented for implementing the
// download-as-zip feature issue
if (namePattern == null || namePattern.equals("*"))
{
if (canVirtualize(contextNodeRef))
{
Reference reference = virtualStore.virtualize(contextNodeRef);
List<Reference> virtualNodes = Collections.emptyList();
if (!includeSubFolders)
{
virtualNodes = virtualStore.search(reference,
namePattern,
fileSearch,
folderSearch,
false);
}
List<FileInfo> searchResult = asFileInfos(virtualNodes,
virtualStore,
environment);
if (mergeActualNode(reference))
{
List<FileInfo> actualSearch = getTrait().search(actualNodeFrom(reference),
namePattern,
fileSearch,
folderSearch,
includeSubFolders);
searchResult.addAll(actualSearch);
}
return searchResult;
}
}
return getTrait().search(contextNodeRef,
namePattern,
fileSearch,
folderSearch,
includeSubFolders);
}
@Override
public FileInfo rename(NodeRef sourceNodeRef, String newName) throws FileExistsException, FileNotFoundException
{
return getTrait().rename(virtualStore.materializeIfPossible(sourceNodeRef),
newName);
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.util.Collection;
import org.alfresco.repo.lock.mem.Lifetime;
import org.alfresco.repo.lock.mem.LockState;
import org.alfresco.repo.lock.traitextender.LockServiceExtension;
import org.alfresco.repo.lock.traitextender.LockServiceTrait;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.lock.LockStatus;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.lock.UnableToAquireLockException;
import org.alfresco.service.cmr.lock.UnableToReleaseLockException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualLockServiceExtension extends SpringBeanExtension<LockServiceExtension, LockServiceTrait>
implements LockServiceExtension
{
private VirtualStore virtualStore;
public VirtualLockServiceExtension()
{
super(LockServiceTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
@Override
public void lock(NodeRef nodeRef, LockType lockType) throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRef),
lockType);
}
@Override
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire) throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRef),
lockType,
timeToExpire);
}
@Override
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, Lifetime lifetime)
throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRef),
lockType,
timeToExpire,
lifetime);
}
@Override
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, Lifetime lifetime, String additionalInfo)
throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRef),
lockType,
timeToExpire,
lifetime,
additionalInfo);
}
@Override
public void lock(NodeRef nodeRef, LockType lockType, int timeToExpire, boolean lockChildren)
throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRef),
lockType,
timeToExpire,
lockChildren);
}
@Override
public void lock(Collection<NodeRef> nodeRefs, LockType lockType, int timeToExpire)
throws UnableToAquireLockException
{
getTrait().lock(virtualStore.materializeIfPossible(nodeRefs),
lockType,
timeToExpire);
}
@Override
public void unlock(NodeRef nodeRef) throws UnableToReleaseLockException
{
getTrait().unlock(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public void unlock(NodeRef nodeRef, boolean lockChildren) throws UnableToReleaseLockException
{
getTrait().unlock(virtualStore.materializeIfPossible(nodeRef),
lockChildren);
}
@Override
public void unlock(NodeRef nodeRef, boolean lockChildren, boolean allowCheckedOut)
throws UnableToReleaseLockException
{
getTrait().unlock(virtualStore.materializeIfPossible(nodeRef),
lockChildren,
allowCheckedOut);
}
@Override
public void unlock(Collection<NodeRef> nodeRefs) throws UnableToReleaseLockException
{
getTrait().unlock(virtualStore.materializeIfPossible(nodeRefs));
}
@Override
public LockStatus getLockStatus(NodeRef nodeRef)
{
return getTrait().getLockStatus(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public LockStatus getLockStatus(NodeRef nodeRef, String userName)
{
return getTrait().getLockStatus(virtualStore.materializeIfPossible(nodeRef),
userName);
}
@Override
public LockType getLockType(NodeRef nodeRef)
{
return getTrait().getLockType(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public void checkForLock(NodeRef nodeRef)
{
getTrait().checkForLock(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public void suspendLocks()
{
getTrait().suspendLocks();
}
@Override
public void enableLocks()
{
getTrait().enableLocks();
}
@Override
public String getAdditionalInfo(NodeRef nodeRef)
{
return getTrait().getAdditionalInfo(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public LockState getLockState(NodeRef nodeRef)
{
return getTrait().getLockState(virtualStore.materializeIfPossible(nodeRef));
}
@Override
public void setEphemeralExpiryThreshold(int threshSecs)
{
getTrait().setEphemeralExpiryThreshold(threshSecs);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import org.alfresco.repo.lock.mem.LockState;
import org.alfresco.repo.lock.traitextender.LockableAspectInterceptorExtension;
import org.alfresco.repo.lock.traitextender.LockableAspectInterceptorTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ref.GetActualNodeRefMethod;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualLockableAspectInterceptorExtension extends
SpringBeanExtension<LockableAspectInterceptorExtension, LockableAspectInterceptorTrait> implements
LockableAspectInterceptorExtension
{
private ActualEnvironment environment;
public VirtualLockableAspectInterceptorExtension()
{
super(LockableAspectInterceptorTrait.class);
}
public void setEnvironment(ActualEnvironment environment)
{
this.environment = environment;
}
@Override
public LockState getLockState(NodeRef nodeRef)
{
if(Reference.isReference(nodeRef)){
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef actualNodeRef = reference.execute(new GetActualNodeRefMethod(environment));
return getTrait().traitImplOf_getLockState(actualNodeRef);
}
return getTrait().traitImplOf_getLockState(nodeRef);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,563 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.alfresco.repo.security.permissions.NodePermissionEntry;
import org.alfresco.repo.security.permissions.PermissionEntry;
import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.repo.security.permissions.impl.SimpleNodePermissionEntry;
import org.alfresco.repo.security.permissions.impl.traitextender.PermissionServiceExtension;
import org.alfresco.repo.security.permissions.impl.traitextender.PermissionServiceTrait;
import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionContext;
import org.alfresco.service.namespace.QName;
import org.alfresco.traitextender.SpringBeanExtension;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class VirtualPermissionServiceExtension extends
SpringBeanExtension<PermissionServiceExtension, PermissionServiceTrait> implements
PermissionServiceExtension
{
private static Log logger = LogFactory.getLog(VirtualPermissionServiceExtension.class);
private VirtualStore virtualStore;
public VirtualPermissionServiceExtension()
{
super(PermissionServiceTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
public AccessStatus hasPermission(NodeRef nodeRef, String perm)
{
PermissionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.hasPermission(nodeRef,
perm);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
AccessStatus virtualAccessStatus = virtualStore.hasPermission(reference,
perm);
if (!AccessStatus.UNDETERMINED.equals(virtualAccessStatus))
{
return virtualAccessStatus;
}
else
{
NodeRef nodeToAdhereTo = establishPermisisonAdherence(reference);
if (nodeToAdhereTo == null)
{
return AccessStatus.UNDETERMINED;
}
else
{
return theTrait.hasPermission(nodeToAdhereTo,
perm);
}
}
}
}
public AccessStatus hasPermission(NodeRef nodeRef, PermissionReference perm)
{
PermissionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.hasPermission(nodeRef,
perm);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
AccessStatus virtualAccessStatus = virtualStore.hasPermission(reference,
perm);
if (!AccessStatus.UNDETERMINED.equals(virtualAccessStatus))
{
return virtualAccessStatus;
}
else
{
NodeRef nodeToAdhereTo = establishPermisisonAdherence(reference);
if (nodeToAdhereTo == null)
{
return AccessStatus.UNDETERMINED;
}
else
{
return theTrait.hasPermission(nodeToAdhereTo,
perm);
}
}
}
}
@Override
public PermissionReference getAllPermissionReference()
{
return getTrait().getAllPermissionReference();
}
@Override
public Set<PermissionReference> getSettablePermissionReferences(QName type)
{
return getTrait().getSettablePermissionReferences(type);
}
@Override
public Set<PermissionReference> getSettablePermissionReferences(NodeRef nodeRef)
{
if (!Reference.isReference(nodeRef))
{
return getTrait().getSettablePermissionReferences(nodeRef);
}
else
{
return Collections.emptySet();
}
}
@Override
public NodePermissionEntry getSetPermissions(NodeRef nodeRef)
{
PermissionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.getSetPermissions(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodePermissionEntry virtualSetPermissions = virtualStore.getSetPermissions(reference);
NodeRef nodeToAdhereTo = establishPermisisonAdherence(reference);
List<? extends PermissionEntry> actualPermissionEntries;
boolean inheritPermissions = false;
if (nodeToAdhereTo != null)
{
NodePermissionEntry actualSetPermissions = theTrait.getSetPermissions(nodeToAdhereTo);
actualPermissionEntries = actualSetPermissions.getPermissionEntries();
inheritPermissions = actualSetPermissions.inheritPermissions();
}
else
{
actualPermissionEntries = Collections.emptyList();
inheritPermissions = false;
}
List<PermissionEntry> mergedEntries = new LinkedList<>();
List<? extends PermissionEntry> virtualPermissionEntries = virtualSetPermissions.getPermissionEntries();
Set<QName> overridenPermissions = new HashSet<>();
for (PermissionEntry permissionEntry : virtualPermissionEntries)
{
overridenPermissions.add(permissionEntry.getPermissionReference().getQName());
mergedEntries.add(permissionEntry);
}
for (PermissionEntry permissionEntry : actualPermissionEntries)
{
if (!overridenPermissions.contains(permissionEntry.getPermissionReference().getQName()))
{
mergedEntries.add(permissionEntry);
}
}
return new SimpleNodePermissionEntry(nodeRef,
inheritPermissions,
mergedEntries);
}
}
private NodeRef establishPermisisonAdherence(Reference reference)
{
NodeRef nodeToAdhereTo = virtualStore.adhere(reference,
VirtualStore.FILING_OR_MATERIAL_ADHERENCE);
if (logger.isDebugEnabled())
{
logger.debug("Could not establish permission adherence for " + reference.toString());
}
return nodeToAdhereTo;
}
@Override
public NodePermissionEntry explainPermission(NodeRef nodeRef, PermissionReference perm)
{
return getTrait().explainPermission(virtualStore.materializeIfPossible(nodeRef),
perm);
}
@Override
public void deletePermissions(NodePermissionEntry nodePermissionEntry)
{
if (!Reference.isReference(nodePermissionEntry.getNodeRef()))
{
getTrait().deletePermissions(nodePermissionEntry);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void deletePermission(PermissionEntry permissionEntry)
{
if (!Reference.isReference(permissionEntry.getNodeRef()))
{
getTrait().deletePermission(permissionEntry);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void setPermission(PermissionEntry permissionEntry)
{
if (!Reference.isReference(permissionEntry.getNodeRef()))
{
getTrait().setPermission(permissionEntry);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void setPermission(NodePermissionEntry nodePermissionEntry)
{
if (!Reference.isReference(nodePermissionEntry.getNodeRef()))
{
getTrait().setPermission(nodePermissionEntry);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public PermissionReference getPermissionReference(QName qname, String permissionName)
{
return getTrait().getPermissionReference(permissionName);
}
@Override
public PermissionReference getPermissionReference(String permissionName)
{
return getTrait().getPermissionReference(permissionName);
}
@Override
public String getPermission(PermissionReference permissionReference)
{
return getTrait().getPermission(permissionReference);
}
@Override
public void deletePermissions(String recipient)
{
getTrait().deletePermissions(recipient);
}
@Override
public NodePermissionEntry getSetPermissions(StoreRef storeRef)
{
return getTrait().getSetPermissions(storeRef);
}
@Override
public String getOwnerAuthority()
{
return getTrait().getOwnerAuthority();
}
@Override
public String getAllAuthorities()
{
return getTrait().getAllAuthorities();
}
@Override
public String getAllPermission()
{
return getTrait().getAllPermission();
}
@Override
public Set<AccessPermission> getPermissions(NodeRef nodeRef)
{
PermissionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.getPermissions(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
Set<AccessPermission> virtualSetPermissions = virtualStore.getAllSetPermissions(reference);
NodeRef nodeToAdhereTo = establishPermisisonAdherence(reference);
Set<AccessPermission> mergedEntries = new HashSet<>(virtualSetPermissions);
if (nodeToAdhereTo != null)
{
Set<AccessPermission> actualSetPermissions = theTrait.getPermissions(nodeToAdhereTo);
mergedEntries.addAll(actualSetPermissions);
}
return mergedEntries;
}
}
@Override
public Set<AccessPermission> getAllSetPermissions(NodeRef nodeRef)
{
PermissionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.getAllSetPermissions(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
Set<AccessPermission> virtualSetPermissions = virtualStore.getAllSetPermissions(reference);
NodeRef nodeToAdhereTo = establishPermisisonAdherence(reference);
Set<AccessPermission> actualSetPermissions;
if (nodeToAdhereTo != null)
{
actualSetPermissions = theTrait.getAllSetPermissions(nodeToAdhereTo);
}
else
{
actualSetPermissions = Collections.emptySet();
}
Set<String> overridenPermissions = new HashSet<>();
Set<AccessPermission> mergedEntries = new HashSet<>();
for (AccessPermission permission : virtualSetPermissions)
{
overridenPermissions.add(permission.getPermission());
mergedEntries.add(permission);
}
for (AccessPermission permission : actualSetPermissions)
{
if (!overridenPermissions.contains(permission.getPermission()))
{
mergedEntries.add(permission);
}
}
return mergedEntries;
}
}
@Override
public Set<String> getSettablePermissions(NodeRef nodeRef)
{
if (!Reference.isReference(nodeRef))
{
return getTrait().getSettablePermissions(nodeRef);
}
else
{
return Collections.emptySet();
}
}
@Override
public Set<String> getSettablePermissions(QName type)
{
return getTrait().getSettablePermissions(type);
}
@Override
public AccessStatus hasReadPermission(NodeRef nodeRef)
{
return getTrait().hasReadPermission(nodeRef);
}
@Override
public Set<String> getReaders(Long aclId)
{
return getTrait().getReaders(aclId);
}
@Override
public Set<String> getReadersDenied(Long aclId)
{
return getTrait().getReadersDenied(aclId);
}
@Override
public AccessStatus hasPermission(Long aclID, PermissionContext context, String permission)
{
return getTrait().hasPermission(aclID,
context,
permission);
}
@Override
public void deletePermissions(NodeRef nodeRef)
{
if (!Reference.isReference(nodeRef))
{
getTrait().deletePermissions(nodeRef);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void clearPermission(NodeRef nodeRef, String authority)
{
if (!Reference.isReference(nodeRef))
{
getTrait().clearPermission(nodeRef,
authority);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void deletePermission(NodeRef nodeRef, String authority, String permission)
{
if (!Reference.isReference(nodeRef))
{
getTrait().deletePermission(nodeRef,
authority,
permission);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void setPermission(NodeRef nodeRef, String authority, String permission, boolean allow)
{
if (!Reference.isReference(nodeRef))
{
getTrait().setPermission(nodeRef,
authority,
permission,
allow);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public void setInheritParentPermissions(NodeRef nodeRef, boolean inheritParentPermissions)
{
if (!Reference.isReference(nodeRef))
{
getTrait().setInheritParentPermissions(nodeRef,
inheritParentPermissions);
}
else
{
// no action taken on virtual nodes
}
}
@Override
public boolean getInheritParentPermissions(NodeRef nodeRef)
{
if (!Reference.isReference(nodeRef))
{
return getTrait().getInheritParentPermissions(nodeRef);
}
else
{
return false;
}
}
@Override
public void setPermission(StoreRef storeRef, String authority, String permission, boolean allow)
{
getTrait().setPermission(storeRef,
authority,
permission,
allow);
}
@Override
public void deletePermission(StoreRef storeRef, String authority, String permission)
{
getTrait().deletePermission(storeRef,
authority,
permission);
}
@Override
public void clearPermission(StoreRef storeRef, String authority)
{
getTrait().clearPermission(storeRef,
authority);
}
@Override
public void deletePermissions(StoreRef storeRef)
{
getTrait().deletePermissions(storeRef);
}
@Override
public Set<AccessPermission> getAllSetPermissions(StoreRef storeRef)
{
return getTrait().getAllSetPermissions(storeRef);
}
@Override
public Set<String> getAuthorisations()
{
return getTrait().getAuthorisations();
}
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.preference.traitextender.PreferenceServiceExtension;
import org.alfresco.repo.preference.traitextender.PreferenceServiceTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ref.GetActualNodeRefMethod;
import org.alfresco.repo.virtual.ref.GetParentReferenceMethod;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.preference.PreferenceService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualPreferenceServiceExtension extends
SpringBeanExtension<PreferenceServiceExtension, PreferenceServiceTrait>implements PreferenceServiceExtension
{
private static final String DOCUMENTS_FAVOURITES_KEY = "org.alfresco.share.documents.favourites";
private static final String CREATED_AT = ".createdAt";
private static final String EXT_DOCUMENTS_FAVOURITES = "org.alfresco.ext.documents.favourites.";
private VirtualStore virtualStore;
private ActualEnvironment environment;
private PreferenceService preferenceService;
public VirtualPreferenceServiceExtension()
{
super(PreferenceServiceTrait.class);
}
public ActualEnvironment getEnvironment()
{
return environment;
}
public void setEnvironment(ActualEnvironment environment)
{
this.environment = environment;
}
public PreferenceService getPreferenceService()
{
return preferenceService;
}
public void setPreferenceService(PreferenceService preferenceService)
{
this.preferenceService = preferenceService;
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
private String getExtDocumentPreferenceKey(Map<String, Serializable> preferences)
{
String extKey = null;
if (!preferences.containsKey(DOCUMENTS_FAVOURITES_KEY))
{
return null;
}
Set<Entry<String, Serializable>> entrySet = preferences.entrySet();
if (entrySet == null)
{
return null;
}
Iterator<Entry<String, Serializable>> iterator = entrySet.iterator();
if (!iterator.hasNext())
{
return null;
}
while (iterator.hasNext())
{
Entry<String, Serializable> entry = iterator.next();
String key = entry.getKey();
if (key.startsWith(EXT_DOCUMENTS_FAVOURITES))
{
extKey = key;
break;
}
}
return extKey;
}
@Override
public void setPreferences(String userName, Map<String, Serializable> preferences) throws Throwable
{
final String comma = ",";
String extKey = getExtDocumentPreferenceKey(preferences);
if (extKey != null)
{
String pattern = "^" + EXT_DOCUMENTS_FAVOURITES + "(\\S+)" + CREATED_AT + "$";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(extKey);
if (m.find())
{
String documentNodeRefStr = m.group(1);
String favorites = (String) preferences.get(DOCUMENTS_FAVOURITES_KEY);
if (documentNodeRefStr != null && !documentNodeRefStr.isEmpty())
{
NodeRef documentNodeRef = new NodeRef(documentNodeRefStr);
if (Reference.isReference(documentNodeRef))
{
Reference reference = Reference.fromNodeRef(documentNodeRef);
NodeRef actualNodeRef = reference.execute(new GetActualNodeRefMethod(null));
String actualNodeRefStr = actualNodeRef.toString();
Reference parentVF = reference.execute(new GetParentReferenceMethod());
NodeRef actualFolder = parentVF.execute(new GetActualNodeRefMethod(environment));
Reference virtualizedRoot = virtualStore.virtualize(actualFolder);
String documentName = (String) environment.getProperty(documentNodeRef,
ContentModel.PROP_NAME);
List<Reference> results = virtualStore.search(virtualizedRoot,
documentName,
true,
false,
true);
if (favorites.contains(documentNodeRefStr))
{
for (Reference ref : results)
{
NodeRef nodeRef = ref.toNodeRef();
String nodeRefStr = nodeRef.toString();
if (!favorites.contains(nodeRefStr))
{
if (favorites.isEmpty())
{
favorites = nodeRefStr;
}
else
{
favorites = favorites + comma + nodeRefStr;
}
}
}
if (!favorites.contains(actualNodeRefStr))
{
favorites = favorites + comma + actualNodeRefStr;
}
preferences.put(DOCUMENTS_FAVOURITES_KEY,
favorites);
}
else
{
List<String> elements = new ArrayList<String>(Arrays.asList(favorites.split(comma)));
for (Reference ref : results)
{
NodeRef nodeRef = ref.toNodeRef();
String nodeRefStr = nodeRef.toString();
if (elements.contains(nodeRefStr))
{
elements.remove(nodeRefStr);
String preferenceToClear = EXT_DOCUMENTS_FAVOURITES + nodeRefStr + CREATED_AT;
preferenceService.clearPreferences(userName,
preferenceToClear);
}
}
if (elements.contains(actualNodeRefStr))
{
elements.remove(actualNodeRefStr);
String preferenceToClear = EXT_DOCUMENTS_FAVOURITES + actualNodeRefStr + CREATED_AT;
preferenceService.clearPreferences(userName,
preferenceToClear);
}
favorites = "";
for (String element : elements)
{
if (favorites.isEmpty())
{
favorites = element;
}
else
{
favorites = favorites + comma + element;
}
}
preferences.put(DOCUMENTS_FAVOURITES_KEY,
favorites);
}
}
else
{
ChildAssociationRef parentAssociation = environment.getPrimaryParent(documentNodeRef);
NodeRef parentNodeRef = parentAssociation.getParentRef();
if (virtualStore.canVirtualize(parentNodeRef))
{
Reference virtualizedRoot = virtualStore.virtualize(parentNodeRef);
String documentName = (String) environment.getProperty(documentNodeRef,
ContentModel.PROP_NAME);
List<Reference> results = virtualStore.search(virtualizedRoot,
documentName,
true,
false,
true);
if (preferences.get(extKey) == null)
{
List<String> elements = new ArrayList<String>(Arrays.asList(favorites.split(comma)));
for (Reference ref : results)
{
NodeRef nodeRef = ref.toNodeRef();
String nodeRefStr = nodeRef.toString();
if (elements.contains(nodeRefStr))
{
elements.remove(nodeRefStr);
String preferenceToClear = EXT_DOCUMENTS_FAVOURITES + nodeRefStr + CREATED_AT;
preferenceService.clearPreferences(userName,
preferenceToClear);
}
}
favorites = "";
for (String element : elements)
{
if (favorites.isEmpty())
{
favorites = element;
}
else
{
favorites = favorites + comma + element;
}
}
preferences.put(DOCUMENTS_FAVOURITES_KEY,
favorites);
}
else
{
for (Reference ref : results)
{
NodeRef nodeRef = ref.toNodeRef();
String nodeRefStr = nodeRef.toString();
if (!favorites.contains(nodeRefStr))
{
if (favorites.isEmpty())
{
favorites = nodeRefStr;
}
else
{
favorites = favorites + comma + nodeRefStr;
}
}
}
preferences.put(DOCUMENTS_FAVOURITES_KEY,
favorites);
}
}
}
}
}
}
getTrait().setPreferences(userName,
preferences);
}
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.rating.traitextender.RatingServiceExtension;
import org.alfresco.repo.rating.traitextender.RatingServiceTrait;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.rating.Rating;
import org.alfresco.service.cmr.rating.RatingScheme;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualRatingServiceExtension extends SpringBeanExtension<RatingServiceExtension, RatingServiceTrait>
implements RatingServiceExtension
{
private VirtualStore virtualStore;
public VirtualRatingServiceExtension()
{
super(RatingServiceTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
public void applyRating(NodeRef targetNode, float rating, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
getTrait().applyRating(materialNode,
rating,
ratingSchemeName);
}
public int getRatingsCount(NodeRef targetNode, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getRatingsCount(materialNode,
ratingSchemeName);
}
public float getTotalRating(NodeRef targetNode, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getTotalRating(materialNode,
ratingSchemeName);
}
public float getAverageRating(NodeRef targetNode, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getAverageRating(materialNode,
ratingSchemeName);
}
public Rating getRatingByCurrentUser(NodeRef targetNode, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getRatingByCurrentUser(materialNode,
ratingSchemeName);
}
public List<Rating> getRatingsByCurrentUser(NodeRef targetNode)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getRatingsByCurrentUser(materialNode);
}
public Rating removeRatingByCurrentUser(NodeRef targetNode, String ratingSchemeName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().removeRatingByCurrentUser(materialNode,
ratingSchemeName);
}
public Serializable getRatingRollup(NodeRef targetNode, String ratingSchemeName, String ratingRollupName)
{
NodeRef materialNode = virtualStore.materializeIfPossible(targetNode);
return getTrait().getRatingRollup(materialNode,
ratingSchemeName,
ratingRollupName);
}
@Override
public Map<String, RatingScheme> getRatingSchemes()
{
return getTrait().getRatingSchemes();
}
@Override
public RatingScheme getRatingScheme(String ratingSchemeName)
{
return getTrait().getRatingScheme(ratingSchemeName);
}
}

View File

@@ -0,0 +1,626 @@
/*
* Copyright (C) 2005-2015 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.virtual.bundle;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.repo.version.VersionServicePolicies.CalculateVersionLabelPolicy;
import org.alfresco.repo.version.common.VersionImpl;
import org.alfresco.repo.version.traitextender.VersionServiceExtension;
import org.alfresco.repo.version.traitextender.VersionServiceTrait;
import org.alfresco.repo.virtual.ref.GetParentReferenceMethod;
import org.alfresco.repo.virtual.ref.NodeProtocol;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.service.cmr.repository.AspectMissingException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.ReservedVersionNameException;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.namespace.QName;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualVersionServiceExtension extends SpringBeanExtension<VersionServiceExtension, VersionServiceTrait>
implements VersionServiceExtension
{
private VirtualStore virtualStore;
public class VirtualVersionHistory implements VersionHistory
{
/**
*
*/
private static final long serialVersionUID = 2640439550254763191L;
private Reference versionedReference;
private VersionHistory actualHistory;
public VirtualVersionHistory(Reference versionedReference, VersionHistory actualHistory)
{
super();
this.versionedReference = versionedReference;
this.actualHistory = actualHistory;
}
@Override
public Version getRootVersion()
{
Version actualRootVersion = actualHistory.getRootVersion();
return VirtualVersionServiceExtension.this.virtualizeVersion(versionedReference,
actualRootVersion);
}
@Override
public Version getHeadVersion()
{
Version actualHeadVersion = actualHistory.getRootVersion();
return VirtualVersionServiceExtension.this.virtualizeVersion(versionedReference,
actualHeadVersion);
}
@Override
public Collection<Version> getAllVersions()
{
Collection<Version> allActualVersions = actualHistory.getAllVersions();
return VirtualVersionServiceExtension.this.virtualizeVersions(versionedReference,
allActualVersions);
}
@Override
public Version getPredecessor(Version version)
{
Version actualVersion = VirtualVersionServiceExtension.this.materializeVersionIfReference(version);
Version actualPredecesor = actualHistory.getPredecessor(actualVersion);
return VirtualVersionServiceExtension.this.virtualizeVersion(versionedReference,
actualPredecesor);
}
@Override
public Collection<Version> getSuccessors(Version version)
{
Version actualVersion = VirtualVersionServiceExtension.this.materializeVersionIfReference(version);
Collection<Version> actualSuccessors = actualHistory.getSuccessors(actualVersion);
return VirtualVersionServiceExtension.this.virtualizeVersions(versionedReference,
actualSuccessors);
}
@Override
public Version getVersion(String versionLabel)
{
Version actualVersion = actualHistory.getVersion(versionLabel);
return VirtualVersionServiceExtension.this.virtualizeVersion(versionedReference,
actualVersion);
}
}
public VirtualVersionServiceExtension()
{
super(VersionServiceTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
@Override
public StoreRef getVersionStoreReference()
{
return getTrait().getVersionStoreReference();
}
@Override
public boolean isAVersion(NodeRef nodeRef)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.isAVersion(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
return theTrait.isAVersion(materialNode);
}
}
@Override
public boolean isVersioned(NodeRef nodeRef)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.isVersioned(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
return theTrait.isVersioned(materialNode);
}
}
private Version materializeVersionIfReference(Version virtualVersion)
{
NodeRef frozenStateNodeRef = virtualVersion.getFrozenStateNodeRef();
StoreRef frozenStoreRef = frozenStateNodeRef.getStoreRef();
NodeRef materialFrozenNodeRef = frozenStateNodeRef;
if (Reference.isReference(frozenStateNodeRef))
{
Reference frozenReference = Reference.fromNodeRef(frozenStateNodeRef);
materialFrozenNodeRef = virtualStore.materialize(frozenReference);
}
Map<String, Serializable> virtualProperties = virtualVersion.getVersionProperties();
Map<String, Serializable> actualProperties = new HashMap<>(virtualProperties);
if (frozenStoreRef.getIdentifier().equals(Version2Model.STORE_ID))
{
// V2 version store (eg. workspace://version2Store)
NodeRef propFrozenNode = (NodeRef) virtualProperties.get(Version2Model.PROP_FROZEN_NODE_REF);
NodeRef propActualFrozenNode = propFrozenNode;
if (Reference.isReference(propFrozenNode))
{
Reference propFrozenReference = Reference.fromNodeRef(propFrozenNode);
propActualFrozenNode = virtualStore.materialize(propFrozenReference);
}
actualProperties.put(Version2Model.PROP_FROZEN_NODE_REF,
propActualFrozenNode);
}
else if (frozenStoreRef.getIdentifier().equals(VersionModel.STORE_ID))
{
// Deprecated V1 version store (eg.
// workspace://lightWeightVersionStore)
String frozenNodeStoreProtocol = (String) virtualProperties
.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
String frozenNodeStoreId = (String) virtualProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
String frozenNodeId = (String) virtualProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
NodeRef propFrozenNode = new NodeRef(frozenNodeStoreProtocol,
frozenNodeStoreId,
frozenNodeId);
NodeRef propActualFrozenNode = propFrozenNode;
if (Reference.isReference(propFrozenNode))
{
Reference propFrozenReference = Reference.fromNodeRef(propFrozenNode);
propActualFrozenNode = virtualStore.materialize(propFrozenReference);
}
StoreRef propActualStoreRef = propFrozenNode.getStoreRef();
actualProperties.put(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL,
propActualStoreRef.getProtocol());
actualProperties.put(VersionModel.PROP_FROZEN_NODE_STORE_ID,
propActualStoreRef.getIdentifier());
actualProperties.put(VersionModel.PROP_FROZEN_NODE_ID,
propActualFrozenNode.getId());
}
Version actualVersion = new VersionImpl(actualProperties,
materialFrozenNodeRef);
return actualVersion;
}
private Version virtualizeVersion(Reference versionedReference, Version actualVersion)
{
if (actualVersion == null)
{
return null;
}
NodeRef frozenStateNodeRef = actualVersion.getFrozenStateNodeRef();
StoreRef frozenStoreRef = frozenStateNodeRef.getStoreRef();
Reference parentReference = versionedReference.execute(new GetParentReferenceMethod());
Reference virtualFrozenReference = NodeProtocol.newReference(frozenStateNodeRef,
parentReference);
Map<String, Serializable> properties = actualVersion.getVersionProperties();
Map<String, Serializable> virtualProperties = new HashMap<String, Serializable>(properties);
// Switch VersionStore depending on configured impl
if (frozenStoreRef.getIdentifier().equals(Version2Model.STORE_ID))
{
// V2 version store (eg. workspace://version2Store)
NodeRef propFrozenNodeRef = (NodeRef) virtualProperties.get(Version2Model.PROP_FROZEN_NODE_REF);
Reference virtualPropFrozenReference = NodeProtocol.newReference(propFrozenNodeRef,
parentReference);
virtualProperties.put(Version2Model.PROP_FROZEN_NODE_REF,
virtualPropFrozenReference.toNodeRef(propFrozenNodeRef.getStoreRef()));
}
else if (frozenStoreRef.getIdentifier().equals(VersionModel.STORE_ID))
{
// Deprecated V1 version store (eg.
// workspace://lightWeightVersionStore)
String frozenNodeStoreProtocol = (String) virtualProperties
.get(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL);
String frozenNodeStoreId = (String) virtualProperties.get(VersionModel.PROP_FROZEN_NODE_STORE_ID);
String frozenNodeId = (String) virtualProperties.get(VersionModel.PROP_FROZEN_NODE_ID);
StoreRef propFrozenStoreRef = new StoreRef(frozenNodeStoreProtocol,
frozenNodeStoreId);
NodeRef propFrozenNode = new NodeRef(propFrozenStoreRef,
frozenNodeId);
Reference virtualPropFrozenReference = NodeProtocol.newReference(propFrozenNode,
parentReference);
NodeRef virtualPropFrozenNodeRef = virtualPropFrozenReference.toNodeRef(propFrozenStoreRef);
virtualProperties.put(VersionModel.PROP_FROZEN_NODE_STORE_PROTOCOL,
propFrozenStoreRef.getProtocol());
virtualProperties.put(VersionModel.PROP_FROZEN_NODE_STORE_ID,
propFrozenStoreRef.getIdentifier());
virtualProperties.put(VersionModel.PROP_FROZEN_NODE_ID,
virtualPropFrozenNodeRef.getId());
}
return new VersionImpl(virtualProperties,
virtualFrozenReference.toNodeRef(frozenStateNodeRef.getStoreRef()));
}
private Collection<Version> virtualizeVersions(Reference versionedReference, Collection<Version> actualVersions)
{
Collection<Version> virtualizedVersions = new LinkedList<>();
for (Version actualVersion : actualVersions)
{
Version virtualizedVersion = virtualizeVersion(versionedReference,
actualVersion);
virtualizedVersions.add(virtualizedVersion);
}
return virtualizedVersions;
}
@Override
public Version createVersion(NodeRef nodeRef, Map<String, Serializable> versionProperties)
throws ReservedVersionNameException, AspectMissingException
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.createVersion(nodeRef,
versionProperties);
}
else
{
NodeRef materialNode = virtualStore.materializeIfPossible(nodeRef);
Version actualVersion = theTrait.createVersion(materialNode,
versionProperties);
Reference reference = Reference.fromNodeRef(nodeRef);
return virtualizeVersion(reference,
actualVersion);
}
}
@Override
public Collection<Version> createVersion(NodeRef nodeRef, Map<String, Serializable> versionProperties,
boolean versionChildren) throws ReservedVersionNameException, AspectMissingException
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.createVersion(nodeRef,
versionProperties,
versionChildren);
}
else
{
NodeRef materialNode = virtualStore.materializeIfPossible(nodeRef);
Collection<Version> actualVersions = theTrait.createVersion(materialNode,
versionProperties,
versionChildren);
Reference reference = Reference.fromNodeRef(nodeRef);
return virtualizeVersions(reference,
actualVersions);
}
}
@Override
public Collection<Version> createVersion(Collection<NodeRef> nodeRefs, Map<String, Serializable> versionProperties)
throws ReservedVersionNameException, AspectMissingException
{
VersionServiceTrait theTrait = getTrait();
Collection<NodeRef> materialNodeRefs = new LinkedList<>();
Map<NodeRef, Reference> materializedNodeRefs = new HashMap<>();
for (NodeRef nodeRef : nodeRefs)
{
if (!Reference.isReference(nodeRef))
{
materialNodeRefs.add(nodeRef);
}
else
{
NodeRef materialNode = virtualStore.materializeIfPossible(nodeRef);
materialNodeRefs.add(materialNode);
materializedNodeRefs.put(materialNode,
Reference.fromNodeRef(nodeRef));
}
}
Collection<Version> versions = theTrait.createVersion(materialNodeRefs,
versionProperties);
Collection<Version> virtualizedVersions = new LinkedList<>();
for (Version version : versions)
{
NodeRef versionedNodeRef = version.getVersionedNodeRef();
Reference reference = materializedNodeRefs.get(versionedNodeRef);
if (reference != null)
{
Version virtualizedVersion = virtualizeVersion(reference,
version);
virtualizedVersions.add(virtualizedVersion);
}
else
{
virtualizedVersions.add(version);
}
}
return virtualizedVersions;
}
@Override
public VersionHistory getVersionHistory(NodeRef nodeRef) throws AspectMissingException
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.getVersionHistory(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
VersionHistory actualVersionHistory = theTrait.getVersionHistory(materialNode);
if (actualVersionHistory == null)
{
return null;
}
else
{
Reference versionedReference = Reference.fromNodeRef(nodeRef);
return new VirtualVersionHistory(versionedReference,
actualVersionHistory);
}
}
}
@Override
public Version getCurrentVersion(NodeRef nodeRef)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.getCurrentVersion(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
Reference versionedReference = Reference.fromNodeRef(nodeRef);
Version actualVersion = theTrait.getCurrentVersion(materialNode);
return virtualizeVersion(versionedReference,
actualVersion);
}
}
@Override
public void revert(NodeRef nodeRef)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.revert(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
theTrait.revert(materialNode);
}
}
@Override
public void revert(NodeRef nodeRef, boolean deep)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.revert(nodeRef,
deep);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
theTrait.revert(materialNode,
deep);
}
}
@Override
public void revert(NodeRef nodeRef, Version version)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.revert(nodeRef,
version);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
Version actualVersion = VirtualVersionServiceExtension.this.materializeVersionIfReference(version);
theTrait.revert(materialNode,
actualVersion);
}
}
@Override
public void revert(NodeRef nodeRef, Version version, boolean deep)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.revert(nodeRef,
version,
deep);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
Version actualVersion = VirtualVersionServiceExtension.this.materializeVersionIfReference(version);
theTrait.revert(materialNode,
actualVersion,
deep);
}
}
@Override
public NodeRef restore(NodeRef nodeRef, NodeRef parentNodeRef, QName assocTypeQName, QName assocQName)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.restore(nodeRef,
parentNodeRef,
assocTypeQName,
assocQName);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
return theTrait.restore(materialNode,
parentNodeRef,
assocTypeQName,
assocQName);
}
}
@Override
public NodeRef restore(NodeRef nodeRef, NodeRef parentNodeRef, QName assocTypeQName, QName assocQName, boolean deep)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
return theTrait.restore(nodeRef,
parentNodeRef,
assocTypeQName,
assocQName,
deep);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
return theTrait.restore(materialNode,
parentNodeRef,
assocTypeQName,
assocQName,
deep);
}
}
@Override
public void deleteVersionHistory(NodeRef nodeRef) throws AspectMissingException
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.deleteVersionHistory(nodeRef);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
theTrait.deleteVersionHistory(materialNode);
}
}
@Override
public void deleteVersion(NodeRef nodeRef, Version version)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.deleteVersion(nodeRef,
version);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
Version actualVersion = materializeVersionIfReference(version);
theTrait.deleteVersion(materialNode,
actualVersion);
}
}
@Override
public void ensureVersioningEnabled(NodeRef nodeRef, Map<QName, Serializable> versionProperties)
{
VersionServiceTrait theTrait = getTrait();
if (!Reference.isReference(nodeRef))
{
theTrait.ensureVersioningEnabled(nodeRef,
versionProperties);
}
else
{
Reference reference = Reference.fromNodeRef(nodeRef);
NodeRef materialNode = virtualStore.materialize(reference);
theTrait.ensureVersioningEnabled(materialNode,
versionProperties);
}
}
@Override
public void registerVersionLabelPolicy(QName typeQName, CalculateVersionLabelPolicy policy)
{
getTrait().registerVersionLabelPolicy(typeQName,
policy);
}
}

View File

@@ -0,0 +1,52 @@
package org.alfresco.repo.virtual.bundle;
import java.util.List;
import org.alfresco.repo.virtual.store.VirtualStore;
import org.alfresco.repo.workflow.traitextender.WorkflowPackageExtension;
import org.alfresco.repo.workflow.traitextender.WorkflowPackageTrait;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.traitextender.SpringBeanExtension;
public class VirtualWorkflowPackageExtension extends
SpringBeanExtension<WorkflowPackageExtension, WorkflowPackageTrait> implements WorkflowPackageExtension
{
private VirtualStore virtualStore;
public VirtualWorkflowPackageExtension()
{
super(WorkflowPackageTrait.class);
}
public void setVirtualStore(VirtualStore virtualStore)
{
this.virtualStore = virtualStore;
}
@Override
public NodeRef createPackage(NodeRef container)
{
return getTrait().createPackage(virtualStore.materializeIfPossible(container));
}
@Override
public void deletePackage(NodeRef container)
{
getTrait().deletePackage(virtualStore.materializeIfPossible(container));
}
@Override
public List<String> getWorkflowIdsForContent(NodeRef packageItem)
{
return getTrait().getWorkflowIdsForContent(virtualStore.materializeIfPossible(packageItem));
}
@Override
public boolean setWorkflowForPackage(WorkflowInstance instance)
{
return getTrait().setWorkflowForPackage(instance);
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* A {@link NodeRefContext} that solves a name path relative to the Alfresco
* company home node.
*/
public class CompanyHomeContext implements NodeRefContext
{
public static final String COMPANY_HOME_CONTEXT_NAME = "CompanyHome";
private static final String[] EMPTY_PATH = new String[0];
private String companyHomeQName;
public void setCompanyHomeQName(String companyHomeQName)
{
this.companyHomeQName = companyHomeQName;
}
@Override
public NodeRef resolveNamePath(String[] namePath, NodeRefResolver resolver)
{
String[] companyHomeRealtiveRef = createRelativeNamePath(namePath);
return resolver.resolvePathReference(companyHomeRealtiveRef);
}
private String[] createRelativeNamePath(String[] namePath)
{
if (namePath == null)
{
namePath = EMPTY_PATH;
}
String[] companyHomeRealtiveRef = new String[namePath.length + 3];
companyHomeRealtiveRef[0] = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getProtocol();
companyHomeRealtiveRef[1] = StoreRef.STORE_REF_WORKSPACE_SPACESSTORE.getIdentifier();
companyHomeRealtiveRef[2] = companyHomeQName;
if (namePath.length > 0)
{
System.arraycopy(namePath,
0,
companyHomeRealtiveRef,
3,
namePath.length);
}
return companyHomeRealtiveRef;
}
@Override
public NodeRef resolveQNamePath(String[] qNamePath, NodeRefResolver resolver)
{
String[] companyHomeRealtiveRef = createRelativeQNamePath(qNamePath);
return resolver.resolveQNameReference(companyHomeRealtiveRef);
}
private String[] createRelativeQNamePath(String[] qNamePath)
{
if (qNamePath == null)
{
qNamePath = EMPTY_PATH;
}
String[] companyHomeRealtiveRef = new String[qNamePath.length + 1];
companyHomeRealtiveRef[0] = companyHomeQName;
if (qNamePath.length > 0)
{
System.arraycopy(qNamePath,
0,
companyHomeRealtiveRef,
1,
qNamePath.length);
}
return companyHomeRealtiveRef;
}
@Override
public NodeRef createNamePath(String[] namePath, NodeRefResolver resolver)
{
String[] relativeNamePath = createRelativeNamePath(namePath);
return resolver.createNamePath(relativeNamePath);
}
@Override
public NodeRef createQNamePath(String[] qNamePath, String[] names, NodeRefResolver resolver)
{
String[] relativeQNamePath = createRelativeQNamePath(qNamePath);
return resolver.createQNamePath(relativeQNamePath,
names);
}
@Override
public String getContextName()
{
return COMPANY_HOME_CONTEXT_NAME;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* A repository context in which a {@link NodeRefPathExpression} should resolve
* to a {@link NodeRef} using a relative name or qname path.
*/
public interface NodeRefContext
{
/**
* @param namePath
* @param resolver
* @return the {@link NodeRef} the given name path resolves to using the
* supplied resolver.
*/
NodeRef resolveNamePath(String[] namePath, NodeRefResolver resolver);
/**
* @param qNamePath
* @param resolver
* @return the {@link NodeRef} the given {@link QName} prefixed string path
* resolves to using the supplied resolver.
*/
NodeRef resolveQNamePath(String[] qNamePath, NodeRefResolver resolver);
/**
* @return the name of this context
*/
String getContextName();
NodeRef createNamePath(String[] namePath, NodeRefResolver resolver);
NodeRef createQNamePath(String[] qNamePath, String[] names, NodeRefResolver resolver);
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* An expression that resolves to a {@link NodeRef}.<br>
*/
public interface NodeRefExpression
{
NodeRef resolve();
NodeRef resolve(boolean createIfNotFound);
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A String name or qname path expression that resolves to a {@link NodeRef}.<br>
* The given name or qname path is relative to a {@link NodeRefContext}
* repository location. The default context is set to
* {@link CompanyHomeContext#COMPANY_HOME_CONTEXT_NAME}. Other contexts can be
* set using their name with {@link #setContext(String)}.<br>
* The set path is automatically detected and checked for consistency.
*/
public class NodeRefPathExpression implements NodeRefExpression
{
private static final String NAMESPACE_DELIMITER = ":";
private static final String PATH_DELIMITER = "/";
private Map<String, NodeRefContext> contexts = new HashMap<String, NodeRefContext>();
private NodeRefResolver resolver;
private String context = CompanyHomeContext.COMPANY_HOME_CONTEXT_NAME;
private String[] createNamePath;
private String[] namePath;
private String[] qNamePath;
public NodeRefPathExpression(NodeRefResolver resolver, Map<String, NodeRefContext> contexts)
{
this(resolver,
contexts,
CompanyHomeContext.COMPANY_HOME_CONTEXT_NAME,
null);
}
public NodeRefPathExpression(NodeRefResolver resolver, Map<String, NodeRefContext> contexts, String context,
String path)
{
super();
this.resolver = resolver;
this.contexts = contexts;
this.context = context;
setPath(path);
}
public void setContext(String context)
{
this.context = context;
}
public void setCreatedPathName(String createNamePath)
{
this.createNamePath = createNamePath.split(",");
}
/**
* Path setter.<br>
* The type of path is automatically detected and checked for consistency.
*
* @param path the string path to be resolved later
* @throws AlfrescoRuntimeException if the given path is inconsistent (i.e.
* a combination of qnames and names)
*/
public void setPath(String path) throws AlfrescoRuntimeException
{
String[] pathElements = splitAndNormalizePath(path);
if (isQNamePath(pathElements))
{
this.qNamePath = pathElements;
}
else if (isNamePath(pathElements))
{
this.namePath = pathElements;
}
else
{
throw new AlfrescoRuntimeException("Invalid path format : " + path);
}
}
private boolean isQNamePath(String[] pathElements)
{
for (int i = 0; i < pathElements.length; i++)
{
if (!pathElements[i].contains(NAMESPACE_DELIMITER))
{
return false;
}
}
return true;
}
private boolean isNamePath(String[] pathElements)
{
for (int i = 0; i < pathElements.length; i++)
{
if (pathElements[i].contains(NAMESPACE_DELIMITER))
{
return false;
}
}
return true;
}
public static String[] splitAndNormalizePath(String path)
{
if (path == null || path.trim().length() == 0)
{
return new String[] {};
}
String[] splitPath = path.split(PATH_DELIMITER);
// remove blank entries resulted from misplaced delimiters
int shift = 0;
for (int i = 0; i < splitPath.length; i++)
{
if (splitPath[i] == null || splitPath[i].trim().isEmpty())
{
shift++;
}
else if (shift > 0)
{
splitPath[i - shift] = splitPath[i];
}
}
if (shift > 0)
{
String[] noBlanksSplitPath = new String[splitPath.length - shift];
if (noBlanksSplitPath.length > 0)
{
System.arraycopy(splitPath,
0,
noBlanksSplitPath,
0,
noBlanksSplitPath.length);
}
splitPath = noBlanksSplitPath;
}
return splitPath;
}
@Override
public NodeRef resolve()
{
NodeRefContext theContext = contexts.get(context);
if (this.namePath != null)
{
return theContext.resolveNamePath(this.namePath,
resolver);
}
else
{
return theContext.resolveQNamePath(this.qNamePath,
resolver);
}
}
@Override
public NodeRef resolve(boolean createIfNotFound)
{
NodeRef nodeRef = resolve();
if (nodeRef == null && createIfNotFound)
{
NodeRefContext theContext = contexts.get(context);
if (this.namePath != null)
{
return theContext.createNamePath(this.namePath,
resolver);
}
else
{
return theContext.createQNamePath(this.qNamePath,
this.createNamePath,
resolver);
}
}
return nodeRef;
}
@Override
public String toString()
{
StringBuilder pathString = new StringBuilder();
pathString.append("<");
pathString.append(this.context);
pathString.append(">/");
if (this.namePath != null)
{
pathString.append(Arrays.toString(this.namePath));
}
if (this.qNamePath != null)
{
pathString.append(Arrays.toString(this.qNamePath));
}
return "<null path expression>";
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Spring context {@link NodeRefPathExpression} factory bean.<br>
* It creates {@link NodeRefPathExpression} instances configured with the
* spring context defined {@link NodeRefResolver} and the given set of spring
* configured {@link NodeRefContext}s.
*/
public class NodeRefPathExpressionFactory
{
private Map<String, NodeRefContext> contextsMap = Collections.emptyMap();
private NodeRefResolver resolver;
public void setResolver(NodeRefResolver resolver)
{
this.resolver = resolver;
}
public void setNodeRefContexts(Set<NodeRefContext> nodeRefContexts)
{
this.contextsMap = new HashMap<String, NodeRefContext>();
for (NodeRefContext nodeRefContext : nodeRefContexts)
{
this.contextsMap.put(nodeRefContext.getContextName(),
nodeRefContext);
}
}
public NodeRefPathExpression createInstance()
{
return new NodeRefPathExpression(resolver,
this.contextsMap);
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.model.Repository;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Dependency inversion of the Provision of Repository Context.<br>
*
* @see Repository
*/
public interface NodeRefResolver
{
/**
* Path type reference create if absent. Fail substitute for
* {@link Repository#findNodeRef(String, String[])}.
*
* @param reference path element names array
* @return reference array of reference segments
* @throws AlfrescoRuntimeException if an unimplemented or invalid reference
* type is provided
* @see Repository#findNodeRef(String, String[])
*/
NodeRef createNamePath(String[] reference);
/**
* QName type reference create if absent.Fail safe substitute for
* {@link Repository#findNodeRef(String, String[])}.
*
* @param reference path element qnames array
* @param names names to be used when creating the given path. If less than
* reference elements they will be matched from the end of the
* reference path.
* @return reference array of reference segments
* @throws AlfrescoRuntimeException if an unimplemented or invalid reference
* type is provided
* @see Repository#findNodeRef(String, String[])
*/
NodeRef createQNamePath(String[] reference, String[] names);
/**
* Node type explicit inversion of
* {@link Repository#findNodeRef(String, String[])}.
*
* @return reference array of reference segments
* @throws AlfrescoRuntimeException if an unimplemented or invalid reference
* type is provided
* @see Repository#findNodeRef(String, String[])
*/
NodeRef resolveNodeReference(String[] reference);
/**
* Path type explicit inversion of
* {@link Repository#findNodeRef(String, String[])}.
*
* @return reference array of reference segments
* @throws AlfrescoRuntimeException if an unimplemented or invalid reference
* type is provided
* @see Repository#findNodeRef(String, String[])
*/
NodeRef resolvePathReference(String[] reference);
/**
* QName type explicit inversion of
* {@link Repository#findNodeRef(String, String[])}.<br>
* Unlike {@link Repository} {@link NodeRefResolver} implementors must
* provide an adequate implementation.
*
* @return reference array of reference segments
* @throws AlfrescoRuntimeException if an unimplemented or invalid reference
* type is provided
* @see Repository#findNodeRef(String, String[])
*/
NodeRef resolveQNameReference(String[] reference);
/**
* Gets the Company Home. Note this is tenant-aware if the correct Cache is
* supplied.
*
* @return company home node ref
*/
NodeRef getCompanyHome();
/**
* Gets the root home of the company home store
*
* @return root node ref
*/
NodeRef getRootHome();
/**
* Gets the Shared Home. Note this is tenant-aware if the correct Cache is
* supplied.
*
* @return shared home node ref
*/
NodeRef getSharedHome();
/**
* Gets the user home of the currently authenticated person
*
* @param person person
* @return user home of person
*/
NodeRef getUserHome(NodeRef person);
}

View File

@@ -0,0 +1,299 @@
/*
* Copyright (C) 2005-2015 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.virtual.config;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.model.Repository;
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.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
/**
* {@link Repository} based {@link NodeRefResolver} implementation.<br>
*/
public class RepositoryNodeRefResolver implements NodeRefResolver
{
public static final String PATH_REF_EXPRESSION = "path";
public static final String NODE_REF_EXPRESSION = "node";
public static final String QNAME_REF_EXPRESSION = "qname";
private Repository repository;
private NodeService nodeService;
private NamespacePrefixResolver namespacePrefixResolver;
public RepositoryNodeRefResolver()
{
}
public RepositoryNodeRefResolver(Repository repository)
{
super();
this.repository = repository;
}
@Override
public NodeRef resolveNodeReference(String[] reference)
{
return repository.findNodeRef(NODE_REF_EXPRESSION,
reference);
}
@Override
public NodeRef resolvePathReference(String[] reference)
{
return repository.findNodeRef(PATH_REF_EXPRESSION,
reference);
}
@Override
public NodeRef resolveQNameReference(String[] reference)
{
NodeRef theNodeRef = null;
if (reference.length > 0)
{
theNodeRef = repository.getRootHome();
List<ChildAssociationRef> rootChildren = nodeService
.getChildAssocs(theNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName(reference[0],
namespacePrefixResolver),
false);
if (rootChildren == null || rootChildren.isEmpty())
{
// one more attempt : might be a contains assoc
rootChildren = nodeService.getChildAssocs(theNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(reference[0],
namespacePrefixResolver),
false);
}
if (rootChildren == null || rootChildren.isEmpty())
{
// one more attempt : might be a contains assoc though
return null;
}
else
{
theNodeRef = rootChildren.get(0).getChildRef();
}
for (int i = 1; i < reference.length; i++)
{
List<ChildAssociationRef> children = nodeService
.getChildAssocs(theNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(reference[i],
namespacePrefixResolver),
false);
if (children == null || children.isEmpty())
{
theNodeRef = null;
break;
}
else
{
theNodeRef = children.get(0).getChildRef();
}
}
}
return theNodeRef;
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
public void setRepository(Repository repository)
{
this.repository = repository;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
@Override
public NodeRef getCompanyHome()
{
return repository.getCompanyHome();
}
@Override
public NodeRef getRootHome()
{
return repository.getRootHome();
}
@Override
public NodeRef getSharedHome()
{
return repository.getSharedHome();
}
@Override
public NodeRef getUserHome(NodeRef person)
{
return repository.getUserHome(person);
}
@Override
public NodeRef createNamePath(String[] reference)
{
Stack<String> notFoundStack = new Stack<>();
NodeRef found;
if (reference == null || reference.length == 0)
{
found = getRootHome();
}
else
{
NodeRef parentNodeRef = null;
for (int i = reference.length; i > 0; i--)
{
String[] parent = new String[i];
System.arraycopy(reference,
0,
parent,
0,
i);
parentNodeRef = resolvePathReference(parent);
if (parentNodeRef != null)
{
break;
}
else
{
notFoundStack.push(reference[i - 1]);
}
}
while (!notFoundStack.isEmpty())
{
String toCreate = notFoundStack.pop();
final HashMap<QName, Serializable> newProperties = new HashMap<QName, Serializable>();
newProperties.put(ContentModel.PROP_NAME,
toCreate);
ChildAssociationRef newAssoc = nodeService
.createNode(parentNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName(toCreate)),
ContentModel.TYPE_FOLDER,
newProperties);
parentNodeRef = newAssoc.getChildRef();
}
found = parentNodeRef;
}
return found;
}
@Override
public NodeRef createQNamePath(String[] reference, String[] names)
{
Stack<String> notFoundStack = new Stack<>();
Stack<String> notFoundNameStack = new Stack<>();
NodeRef found;
if (reference == null || reference.length == 0)
{
found = getRootHome();
}
else
{
NodeRef parentNodeRef = null;
for (int i = reference.length; i > 0; i--)
{
String[] parent = new String[i];
System.arraycopy(reference,
0,
parent,
0,
i);
parentNodeRef = resolveQNameReference(parent);
if (parentNodeRef != null)
{
break;
}
else
{
if (names != null)
{
int offset = reference.length - i;
if (offset < names.length)
{
notFoundNameStack.push(names[names.length - 1 - offset]);
}
}
notFoundStack.push(reference[i - 1]);
}
}
while (!notFoundStack.isEmpty())
{
String stringQNameToCreate = notFoundStack.pop();
QName qNameToCreate = QName.createQName(stringQNameToCreate,
namespacePrefixResolver);
String nameToCreate;
if (!notFoundNameStack.isEmpty())
{
nameToCreate = notFoundNameStack.pop();
}
else
{
nameToCreate = qNameToCreate.getLocalName();
}
final HashMap<QName, Serializable> newProperties = new HashMap<QName, Serializable>();
newProperties.put(ContentModel.PROP_NAME,
nameToCreate);
ChildAssociationRef newAssoc = nodeService.createNode(parentNodeRef,
ContentModel.ASSOC_CONTAINS,
qNameToCreate,
ContentModel.TYPE_FOLDER,
newProperties);
parentNodeRef = newAssoc.getChildRef();
}
found = parentNodeRef;
}
return found;
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (C) 2005-2015 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.virtual.model;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.dictionary.constraint.ListOfValuesConstraint;
import org.alfresco.repo.virtual.config.NodeRefExpression;
import org.alfresco.repo.virtual.store.SystemVirtualizationMethod;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.i18n.MessageLookup;
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.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.extensions.surf.util.I18NUtil;
/**
* A system paths string values constraint to be used in conjunction with
* {@link SystemVirtualizationMethod}s to provide available system paths by
* exploring a predefined location in the java classpath ad a predefined
* repository location.
*
* @author Silviu Dinuta
*/
public class SystemTemplateLocationsConstraint extends ListOfValuesConstraint
{
public static final String NULL_SYSTEM_TEMPLATE = "nullSystemTemplate";
public static final String NULL_SYSTEM_TEMPLATE_MESSAGE = "vm_virtualization.nullSystemTemplate.message";
private NodeService nodeService;
private String templatesParentClasspath;
private NodeRefExpression templatesParentRepositoryPath;
private NamespacePrefixResolver namespacePrefixResolver;
private String repositoryTemplateTypeName;
public SystemTemplateLocationsConstraint()
{
super();
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setTemplatesParentClasspath(String templatesParentClasspath)
{
this.templatesParentClasspath = templatesParentClasspath;
}
public String getTemplatesParentClasspath()
{
return this.templatesParentClasspath;
}
public NodeRefExpression getTemplatesParentRepositoryPath()
{
return this.templatesParentRepositoryPath;
}
public void setTemplatesParentRepositoryPath(NodeRefExpression templatesParentRepositoryPath)
{
this.templatesParentRepositoryPath = templatesParentRepositoryPath;
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
public void setRepositoryTemplateTypeName(String repositoryTemplateTypeName)
{
this.repositoryTemplateTypeName = repositoryTemplateTypeName;
}
@Override
public List<String> getRawAllowedValues()
{
List<String> result = null;
try
{
result = loadClasspathTemplates(templatesParentClasspath,
"json");
}
catch (IOException e)
{
throw new ConstraintException("ListTemplateTypesConstraints",
e);
}
List<String> repositoryTemplates = loadRepositoryTemplates(templatesParentRepositoryPath);
result.addAll(repositoryTemplates);
if (result.size() == 0)
{
result.add(NULL_SYSTEM_TEMPLATE);
}
super.setAllowedValues(result);
return result;
}
@Override
public List<String> getAllowedValues()
{
if (sorted == true)
{
List<String> rawValues = getRawAllowedValues();
List<String> values = new ArrayList<String>(rawValues);
Collections.sort(values,
new LabelComparator());
return values;
}
else
{
return super.getAllowedValues();
}
}
@Override
public String getDisplayLabel(String constraintAllowableValue, MessageLookup messageLookup)
{
if (constraintAllowableValue.startsWith("N"))
{
Serializable nameProperty = nodeService.getProperty(new NodeRef(constraintAllowableValue.substring(1)),
ContentModel.PROP_NAME);
return nameProperty.toString();
}
else if (constraintAllowableValue.equals(SystemTemplateLocationsConstraint.NULL_SYSTEM_TEMPLATE))
{
String message = messageLookup.getMessage(SystemTemplateLocationsConstraint.NULL_SYSTEM_TEMPLATE_MESSAGE,
I18NUtil.getLocale());
return message == null ? constraintAllowableValue : message;
}
else
{
return constraintAllowableValue.substring(constraintAllowableValue.lastIndexOf("/") + 1);
}
}
@Override
protected void evaluateSingleValue(Object value)
{
super.setAllowedValues(getAllowedValues());
super.evaluateSingleValue(value);
}
private List<String> loadClasspathTemplates(String templatesParentClasspath, String... extensions)
throws IOException
{
List<String> result = new ArrayList<String>(5);
List<String> files = new ArrayList<String>(5);
ClassLoader cl = this.getClass().getClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
Resource[] resources = resolver.getResources("classpath*:" + templatesParentClasspath + "/*");
for (Resource resource : resources)
{
files.add(resource.getFilename());
}
if (extensions != null && extensions.length > 0)
{
String extensionStr = "";
for (int i = 0; i < extensions.length; i++)
{
if (i == extensions.length - 1)
{
extensionStr += extensions[i];
}
else
{
extensionStr += extensions[i] + "|";
}
}
String fileExtensions = "(?i).*\\.(" + extensionStr + ")$";
Pattern pattern = Pattern.compile(fileExtensions);
for (String file : files)
{
if (pattern.matcher(file).matches())
{
result.add("C" + templatesParentClasspath + "/" + file);
}
}
}
return result;
}
private List<String> loadRepositoryTemplates(NodeRefExpression templatesParentRepositoryPath)
{
List<String> result = new ArrayList<String>();
NodeRef findNodeRef = templatesParentRepositoryPath.resolve();
if (findNodeRef != null)
{
final QName repositoryTemplateTypeQName = QName.createQName(repositoryTemplateTypeName,
namespacePrefixResolver);
Set<QName> searchTypeQNames = new HashSet<QName>();
searchTypeQNames.add(repositoryTemplateTypeQName);
List<ChildAssociationRef> children = nodeService.getChildAssocs(findNodeRef,
searchTypeQNames);
for (ChildAssociationRef childAssociationRef : children)
{
NodeRef childNodeRef = childAssociationRef.getChildRef();
QName childType = nodeService.getType(childNodeRef);
if (searchTypeQNames.contains(childType))
{
result.add("N" + childNodeRef.toString());
}
}
}
return result;
}
private class LabelComparator implements Comparator<String>
{
@Override
public int compare(String o1, String o2)
{
return getDisplayLabel(o1,
null).compareTo(getDisplayLabel(o2,
null));
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2005-2015 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.virtual.page;
public class InvalidPageBounds extends PageCollationException
{
/**
*
*/
private static final long serialVersionUID = -1197373266957787084L;
public InvalidPageBounds()
{
super();
}
public InvalidPageBounds(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public InvalidPageBounds(String message, Throwable cause)
{
super(message,
cause);
}
public InvalidPageBounds(String message)
{
super(message);
}
public InvalidPageBounds(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 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.virtual.page;
public class PageCollationException extends Exception
{
/**
*
*/
private static final long serialVersionUID = -6956517169771939562L;
public PageCollationException()
{
super();
}
public PageCollationException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public PageCollationException(String message, Throwable cause)
{
super(message,
cause);
}
public PageCollationException(String message)
{
super(message);
}
public PageCollationException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright (C) 2005-2015 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.virtual.page;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A generic utility for arranging a {@link List} of objects of type
* <code>R</code> into a <code>R</code> objects page obtained from a
* {@link PagingResultsSource} considering a given {@link PagingRequest} for the
* resulted {@link PagingResults}.
*
* @author Bogdan Horje
* @param <R>
*/
public class PageCollator<R>
{
private static Log logger = LogFactory.getLog(PageCollator.class);
/**
* Implementors are paging request capable objects - i.e. can provide
* data-paged results of type <code>R</code> considering a given
* {@link PagingRequest}.
*
* @param <R>
*/
public interface PagingResultsSource<R>
{
PagingResults<R> retrieve(PagingRequest pr) throws PageCollationException;
}
/**
* @param objects
* @param objectPageSurce
* @param pagingRequest
* @param comparator
* @return a {@link PagingResults} R objects obtained from merging a
* collection of R objects with a paged result obtained from a
* {@link PagingResultsSource} considering the a merged result
* {@link PagingRequest}
* @throws PageCollationException
*/
public PagingResults<R> collate(List<R> objects, PagingResultsSource<R> objectPageSurce,
PagingRequest pagingRequest, Comparator<R> comparator) throws PageCollationException
{
final int skip = pagingRequest.getSkipCount();
final int pageSize = pagingRequest.getMaxItems();
if (skip < 0 || pageSize < 0)
{
throw new InvalidPageBounds("Negative page skip index and/or bounds.");
}
int preemptiveSkip = Math.max(0,
skip - objects.size());
int pageSkip = skip - preemptiveSkip;
int preemptiveSize = pageSize + pageSkip;
PagingResults<R> pageResults = null;
try
{
PagingRequest preemptiveRequest = new PagingRequest(preemptiveSkip,
preemptiveSize,
pagingRequest.getQueryExecutionId());
preemptiveRequest.setRequestTotalCountMax(pagingRequest.getRequestTotalCountMax());
pageResults = objectPageSurce.retrieve(preemptiveRequest);
}
catch (InvalidPageBounds e)
{
if (logger.isDebugEnabled())
{
logger.debug(e);
}
pageResults = new PagingResults<R>()
{
@Override
public List<R> getPage()
{
return Collections.emptyList();
}
@Override
public boolean hasMoreItems()
{
return false;
}
@Override
public Pair<Integer, Integer> getTotalResultCount()
{
return new Pair<Integer, Integer>(null,
null);
}
@Override
public String getQueryExecutionId()
{
return null;
}
};
}
return collate(objects,
pageResults,
pageSkip,
pagingRequest,
comparator);
}
private PagingResults<R> collate(List<R> objects, final PagingResults<R> objectPageSurce, int pageSkip,
final PagingRequest pagingRequest, Comparator<R> comparator)
{
final int pageSize = pagingRequest.getMaxItems();
final List<R> inPageList = objectPageSurce.getPage();
final List<R> collatedPageList = new LinkedList<>();
final boolean endOfCollation = collate(objects,
inPageList,
pageSkip,
pageSize,
comparator,
collatedPageList);
final int resultsSize = objects.size();
final Pair<Integer, Integer> pageTotal = objectPageSurce.getTotalResultCount();
Integer pageTotalFirst = null;
Integer pageTotalSecond = null;
if (pageTotal != null)
{
pageTotalFirst = pageTotal.getFirst();
pageTotalSecond = pageTotal.getSecond();
}
final Pair<Integer, Integer> total = new Pair<>(pageTotalFirst == null ? null : pageTotalFirst + resultsSize,
pageTotalSecond == null ? null : pageTotalSecond + resultsSize);
final boolean hasMoreItems = objectPageSurce.hasMoreItems() || !endOfCollation;
return new PagingResults<R>()
{
@Override
public List<R> getPage()
{
return collatedPageList;
}
@Override
public boolean hasMoreItems()
{
return hasMoreItems;
}
@Override
public Pair<Integer, Integer> getTotalResultCount()
{
return total;
}
@Override
public String getQueryExecutionId()
{
return pagingRequest.getQueryExecutionId();
}
};
}
private boolean collate(List<R> objects, List<R> pageObjects, int pageSkip, int pageSize, Comparator<R> comparator,
List<R> collatedResult)
{
final int resultsSize = objects.size();
final int inPageSize = pageObjects.size();
if (pageSkip >= resultsSize + inPageSize)
{
return true;
}
List<R> collation = new ArrayList<>(objects.size() + pageObjects.size());
collation.addAll(pageObjects);
for (int i = 0; i < resultsSize; i++)
{
final int collationSize = collation.size();
final R result = objects.get(i);
int j = 0;
if (comparator != null)
{
for (; j < collationSize; j++)
{
final R collated = collation.get(j);
if (comparator.compare(result,
collated) <= 0)
{
break;
}
}
}
collation.add(j,
result);
}
final R[] collationArray = (R[]) collation.toArray();
final int zeroPageSize = (pageSize == 0 ? collationArray.length - pageSkip : pageSize);
final int to = Math.min(pageSkip + zeroPageSize,
collationArray.length);
collatedResult.addAll(Arrays.asList(Arrays.copyOfRange(collationArray,
pageSkip,
to)));
return to == collationArray.length;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Handles protocol method dispatch. Not supported: base protocol
* dispatches. The vanilla protocol can be handled by default
* as the virtual protocol.
*
* @param <R>
*/
public abstract class AbstractProtocolMethod<R> implements ProtocolMethod<R>
{
public static final String PATH_SEPARATOR = "/";
@Override
public R execute(VanillaProtocol vanillaProtocol, Reference reference) throws ProtocolMethodException
{
// cast to force virtual protocol execution
return execute((VirtualProtocol) vanillaProtocol,
reference);
}
@Override
public R execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
return throwUnsupportedProtocolException(virtualProtocol);
}
@Override
public R execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
return throwUnsupportedProtocolException(protocol);
}
private R throwUnsupportedProtocolException(Protocol protocol) throws ProtocolMethodException
{
throw new ProtocolMethodException("Unsupported protocol " + protocol);
}
@Override
public R execute(Protocol protocol, Reference reference) throws ProtocolMethodException
{
return throwUnsupportedProtocolException(protocol);
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
/**
* Identifies content from a classpath
*/
public class ClasspathResource implements Resource
{
private String classpath;
public ClasspathResource(String classpath)
{
this.classpath = classpath;
}
public String getClasspath()
{
return classpath;
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyResource(this);
}
@Override
public int hashCode()
{
return classpath != null ? classpath.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(obj instanceof ClasspathResource))
{
return false;
}
ClasspathResource other = (ClasspathResource) obj;
if (classpath == null)
{
return other.classpath == null;
}
else
{
return this.classpath.equals(other.classpath);
}
}
@Override
public <R> R processWith(ResourceProcessor<R> processor) throws ResourceProcessingError
{
return processor.process(this);
}
@Override
public InputStream asStream(ActualEnvironment environment) throws ActualEnvironmentException
{
return environment.openContentStream(classpath);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.Serializable;
/**
* A {@link Reference} {@link String} encoding definition.<br>
*
* @see ReferenceParser
* @see Stringifier
* @author Bogdan Horje
*/
public class Encoding implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* String encoding token - signals the beginning of a reference encoded with
* this encoding in given String.
*/
public final Character token;
/**
* <code>true</code> if {@link Reference}s encoded using this encoding
* can be part of URLs.
*/
public final boolean urlNative;
public final ReferenceParser parser;
public final Stringifier stringifier;
public Encoding(Character token, ReferenceParser parser, Stringifier stringifier, boolean urlNative)
{
super();
this.token = token;
this.parser = parser;
this.stringifier = stringifier;
this.urlNative = urlNative;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.HashMap;
import java.util.Map;
/**
* Common {@link Reference} encodings.
*
* @author Bogdan Horje
*/
public enum Encodings
{
/**
* {@link Reference} string encoding that parses and produces reference
* string representations that conform to the following grammar :
*
* <pre>
* reference := protocol':'resource[':'parameters]
* protocol := 'virtual'|'node'|'template'
* resource := repositoryResource | classpathResource
* repositoryResource := 'repository'':'repositoryLocation
* repositoryLocation := ('path'':'path)|('node'':'nodeRef)
* classpathResource := 'classpath'':'path
* path := string
* parameters := parameter[':'parameters]
* parameter := referenceParameter | integerParameter | stringParameter
* referenceParameter := 'ref'':'reference
* resourceParameter := 'r'':'resource
* integerParameter := 'i'':'integer
* stringParameter := 's'':'string
*
* Examples (syntax is correct, but not the semantic):
*
* virtual:classpath:/org/alfresco/
* virtual:classpath:/org/alfresco/:r:repository:node:workspace:SpacesStore:0029-222-333-444
* virtual:classpath:/org/alfresco/:r:repository:node:workspace:SpacesStore:0029-222-333-444:r:repository:path:/Data Dictionary/Virtual Folders/claim.json
* node:repository:node:workspace:SpacesStore:0029-222-333-444:r:virtual:repository:node:workspace:SpacesStore:0029-122-333-0023
* </pre>
*/
PLAIN(new Encoding('p',
new PlainReferenceParser(),
new PlainStringifier(),
false)),
/**
* A condensed {@link Reference} string representation.
*/
ZERO(new Encoding('0',
new ZeroReferenceParser(),
new ZeroStringifier(),
false)),
/**
* A hash based condensed {@link Reference} string representation.
*/
HASH(new Encoding('H',
new HashReferenceParser(),
new HashStringifier(),
true));
private static volatile Map<Character, Encoding> tokenMap;
public static synchronized Encoding fromToken(Character token)
{
return tokenMap.get(token);
}
private static synchronized void register(Encoding encoding)
{
if (tokenMap == null)
{
tokenMap = new HashMap<>();
}
tokenMap.put(encoding.token,
encoding);
}
public final Encoding encoding;
Encodings(Encoding encoding)
{
this.encoding = encoding;
register(encoding);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Returns the actual {@link NodeRef} of a given reference.<br>
* Actual {@link NodeRef} are node references of content elements found in the
* Alfresco repository that are subjected to a virtualization process.
*
* @author Bogdan Horje
*/
public class GetActualNodeRefMethod extends AbstractProtocolMethod<NodeRef>
{
private ActualEnvironment environment;
public GetActualNodeRefMethod(ActualEnvironment environment)
{
super();
this.environment = environment;
}
@Override
public NodeRef execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
try
{
RepositoryLocation nodeRefLocation = virtualProtocol.getActualNodeLocation(reference);
return nodeRefLocation.asNodeRef(environment);
}
catch (ActualEnvironmentException e)
{
throw new ProtocolMethodException(e);
}
}
@Override
public NodeRef execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
return protocol.getNodeRef(reference);
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.HashSet;
import java.util.Set;
import org.alfresco.repo.node.db.traitextender.NodeServiceTrait;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.repo.virtual.VirtualContentModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
public class GetAspectsMethod extends AbstractProtocolMethod<Set<QName>>
{
private NodeServiceTrait nodeServiceTrait;
private ActualEnvironment environment;
public GetAspectsMethod(NodeServiceTrait nodeServiceTrait, ActualEnvironment environment)
{
super();
this.nodeServiceTrait = nodeServiceTrait;
this.environment = environment;
}
private Set<QName> createVirtualAspects()
{
Set<QName> aspects = new HashSet<QName>();
aspects.add(VirtualContentModel.ASPECT_VIRTUAL);
return aspects;
}
private Set<QName> createVirtualDocumentAspects()
{
Set<QName> aspects = new HashSet<QName>();
aspects.add(VirtualContentModel.ASPECT_VIRTUAL_DOCUMENT);
return aspects;
}
@Override
public Set<QName> execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
NodeRef nodeRef = protocol.getNodeRef(reference);
Set<QName> nodeAspects = nodeServiceTrait.getAspects(nodeRef);
Set<QName> aspects = createVirtualDocumentAspects();
aspects.addAll(nodeAspects);
return aspects;
}
@Override
public Set<QName> execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
try
{
Set<QName> aspects = createVirtualAspects();
String path = virtualProtocol.getTemplatePath(reference);
if (PATH_SEPARATOR.equals(path.trim()))
{
NodeRef nodeRef;
nodeRef = virtualProtocol.getActualNodeLocation(reference).asNodeRef(environment);
Set<QName> nodeAspects = nodeServiceTrait.getAspects(nodeRef);
aspects.addAll(nodeAspects);
}
return aspects;
}
catch (ActualEnvironmentException e)
{
throw new ProtocolMethodException(e);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public class GetChildByIdMethod extends AbstractProtocolMethod<Reference>
{
private String childId;
public GetChildByIdMethod(String childId)
{
super();
this.childId = childId;
}
/**
* Provides a child {@link Reference} obtained from the parent
* {@link Reference} and the childId. The inner template path is obtained
* from the parent {@link Reference} and then the childId String is
* concatenated to it. The child {@link Reference} is created by calling
* Protocol#replaceTemplatePathMethod with the new id String as a parameter.
*
* @param virtualProtocol
* @param reference the parent {@link Reference}
* @return the child {@link Reference}
* @throws ProtocolMethodException
*/
@Override
public Reference execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
String path = reference.execute(new GetTemplatePathMethod()).trim();
StringBuilder pathBuilder = new StringBuilder(path);
if (!path.endsWith(PATH_SEPARATOR))
{
pathBuilder.append(PATH_SEPARATOR);
}
pathBuilder.append(childId);
return virtualProtocol.replaceTemplatePath(reference,
pathBuilder.toString());
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Returns a virtual parent reference upon execution by subtracting the last
* template path element from of the given reference.<br>
* For root template path references a <code>null</code> will be returned upon
* execution.
*
* @see VirtualProtocol#replaceTemplatePath(Reference, String)
* @author Bogdan Horje
*/
public class GetParentReferenceMethod extends AbstractProtocolMethod<Reference>
{
@Override
public Reference execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
String path = virtualProtocol.getTemplatePath(reference);
if (path.trim().endsWith(PATH_SEPARATOR))
{
int trailingPathIndex = path.lastIndexOf(PATH_SEPARATOR);
if (trailingPathIndex == 0)
{
return null;
}
else
{
path = path.substring(0,
trailingPathIndex);
}
}
int index = path.lastIndexOf(PATH_SEPARATOR);
if (index < 0)
{
return null;
}
else
{
String parentPath = path.substring(0,
index);
if (parentPath.isEmpty())
{
if (path.length() > 1)
{
parentPath = PATH_SEPARATOR;
}
else
{
return null;
}
}
return virtualProtocol.replaceTemplatePath(reference,
parentPath);
}
}
@Override
public Reference execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
return ((ReferenceParameter) reference.getParameters().get(0)).getValue();
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* Returns actual {@link QName} Type of a given reference <br>
* indicated by the given protocol reference.
*/
public class GetReferenceType extends AbstractProtocolMethod<QName>
{
private ActualEnvironment environment;
public GetReferenceType(ActualEnvironment environment)
{
super();
this.environment = environment;
}
@Override
public QName execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
NodeRef nodeRef = protocol.getNodeRef(reference);
return environment.getType(nodeRef);
}
@Override
public QName execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
return ContentModel.TYPE_FOLDER;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Returns the virtual folder template inner path for a virtualized entity
* reference.
*
* @author Bogdan Horje
*/
public class GetTemplatePathMethod extends AbstractProtocolMethod<String>
{
@Override
public String execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
String path = virtualProtocol.getTemplatePath(reference);
return path;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
/**
* It returns an {@link InputStream} for the vanilla-virtual folder template resource
* indicated by the given vanilla protocol reference.
*
* @author Bogdan Horje
*/
public class GetVanillaScriptInputStreamMethod extends AbstractProtocolMethod<InputStream>
{
private ActualEnvironment environment;
public GetVanillaScriptInputStreamMethod(ActualEnvironment environment)
{
super();
this.environment = environment;
}
@Override
public InputStream execute(VanillaProtocol vanillaProtocol, Reference reference) throws ProtocolMethodException
{
Resource resource = vanillaProtocol.getVanillaTemplateResource(reference);
try
{
return resource.asStream(environment);
}
catch (ActualEnvironmentException e)
{
throw new ProtocolMethodException(e);
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Hash encoding constants interface.
*/
public interface HashEncodingArtefact
{
static final String VANILLA_PROTOCOL_CODE = "1";
static final String VIRTUAL_PROTOCOL_CODE = "2";
static final String NODE_PROTOCOL_CODE = "3";
static final String REPOSITORY_NODEREF_RESOURCE_CODE = "1";
static final String REPOSITORY_PATH_CODE = "2";
static final String HASHED_REPOSITORY_PATH_CODE = "3";
static final String MIXED_REPOSITORY_PATH_CODE = "4";
static final String CLASSPATH_RESOUCE_CODE = "5";
static final String HASHED_CLASSPATH_RESOUCE_CODE = "6";
static final String MIXED_CLASSPATH_RESOUCE_CODE = "7";
static final String NUMERIC_ROOT_PATH_CODE = "1";
static final String NUMERIC_PATH_CODE = "2";
static final String HASHED_NUMERIC_PATH_CODE = "3";
static final String MIXED_NUMERIC_PATH_CODE = "4";
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Hash encoded reference string parser.<br>
* Delegates to {@link VirtualHashReferenceParser},
* {@link VanillaHashReferenceParser} or {@link NodeHashReferenceParser} for
* custom protocol parsing.
*/
public class HashReferenceParser implements ReferenceParser, HashEncodingArtefact
{
/**
*
*/
private static final long serialVersionUID = -2569625423953183530L;
private NodeHashReferenceParser nodeReferenceParser;
private VirtualHashReferenceParser virtualReferenceParser;
private VanillaHashReferenceParser vanillaReferenceParser;
public HashReferenceParser()
{
HashStore cpStore = HashStoreConfiguration.getInstance().getClasspathHashStore();
nodeReferenceParser = new NodeHashReferenceParser(cpStore,
this);
virtualReferenceParser = new VirtualHashReferenceParser(cpStore);
vanillaReferenceParser = new VanillaHashReferenceParser(cpStore);
}
@Override
public Reference parse(String referenceString) throws ReferenceParseException
{
String[] tokens = referenceString.split("-");
Cursor c = new Cursor(tokens,
0);
return parse(c);
}
public Reference parse(Cursor c)
{
if (NODE_PROTOCOL_CODE.equals(c.currentToken()))
{
return nodeReferenceParser.parse(c);
}
else if (VANILLA_PROTOCOL_CODE.equals(c.currentToken()))
{
return vanillaReferenceParser.parse(c);
}
else if (VIRTUAL_PROTOCOL_CODE.equals(c.currentToken()))
{
return virtualReferenceParser.parse(c);
}
else
{
throw new ReferenceEncodingException("Unknown reference code " + c.currentToken());
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A synchronized string hash code mapping store.<br>
* Associates a string with a given string-hash.
*/
public class HashStore
{
private HashMap<String, String> hashStore = new HashMap<>();
private HashMap<String, String> lookupStore = new HashMap<>();
private ReentrantReadWriteLock configurationLock = new ReentrantReadWriteLock();
public void put(String string, String hash)
{
configurationLock.writeLock().lock();
try
{
hashStore.put(string,
hash);
lookupStore.put(hash,
string);
}
finally
{
configurationLock.writeLock().unlock();
}
}
public String hash(String string)
{
configurationLock.readLock().lock();
try
{
return hashStore.get(string);
}
finally
{
configurationLock.readLock().unlock();
}
}
public String lookup(String hash)
{
configurationLock.readLock().lock();
try
{
return lookupStore.get(hash);
}
finally
{
configurationLock.readLock().unlock();
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.version.VersionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Global hash store configuration.<br>
* Used for custom global {@link HashStore}s required for {@link Reference}
* string encoding.
*/
public class HashStoreConfiguration
{
private static Log logger = LogFactory.getLog(HashStoreConfiguration.class);
public static class HashStoreConfigurationBean
{
public void setClasspathsHashes(String classpathsHashes)
{
String[] hashes = classpathsHashes.split(",");
for (int i = 0; i < hashes.length; i++)
{
String[] pathHash = hashes[i].split("->");
if (pathHash.length != 2)
{
logger.error("Invalid classpath hash configuration " + hashes[i]);
}
else
{
HashStoreConfiguration.getInstance().getClasspathHashStore().put(pathHash[0],
pathHash[1]);
if (logger.isDebugEnabled())
{
logger.debug("Configured classpath hash " + pathHash[0] + " -> " + pathHash[1]);
}
}
}
}
}
private static HashStoreConfiguration instance = null;
public static synchronized HashStoreConfiguration getInstance()
{
if (instance == null)
{
instance = new HashStoreConfiguration();
}
return instance;
}
private final HashStore classpathStore;
private HashStore storeProtocolStore;
private HashStore storeIdStore;
private HashStoreConfiguration()
{
classpathStore = new HashStore();
storeProtocolStore = new HashStore();
storeIdStore = new HashStore();
storeProtocolStore.put(StoreRef.PROTOCOL_WORKSPACE,
"1");
storeProtocolStore.put(StoreRef.PROTOCOL_ARCHIVE,
"2");
storeProtocolStore.put(StoreRef.PROTOCOL_AVM,
"3");
storeProtocolStore.put(StoreRef.PROTOCOL_DELETED,
"4");
storeProtocolStore.put(StoreRef.PROTOCOL_TEST,
"5");
storeProtocolStore.put(VersionService.VERSION_STORE_PROTOCOL,
"6");
storeIdStore.put("SpacesStore",
"1");
storeIdStore.put(VersionModel.STORE_ID,
"2");
storeIdStore.put(Version2Model.STORE_ID,
"3");
}
public HashStore getClasspathHashStore()
{
return classpathStore;
}
public HashStore getStoreIdStore()
{
return this.storeIdStore;
}
public HashStore getStoreProtocolStore()
{
return this.storeProtocolStore;
}
}

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.List;
/**
* Hash encoded reference stringifier.<br>
* Delegates to {@link VanillaHashStringifier},
* {@link VirtualHashStringifier} or {@link NodeHashStringifier} for
* custom protocol parsing.
*/
public class HashStringifier implements Stringifier
{
/**
*
*/
private static final long serialVersionUID = 2213824445193662644L;
private NodeHashStringifier nodeStringifier;
private VirtualHashStringifier virtualStringifier;
private VanillaHashStringifier vanillaStringifier;
public HashStringifier()
{
HashStore cpStore = HashStoreConfiguration.getInstance().getClasspathHashStore();
nodeStringifier = new NodeHashStringifier(cpStore,
this);
virtualStringifier = new VirtualHashStringifier(cpStore,
this);
vanillaStringifier = new VanillaHashStringifier(cpStore,
this);
}
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
final Protocol protocol = reference.getProtocol();
if (Protocols.NODE.protocol.equals(protocol))
{
return nodeStringifier.stringify(reference);
}
else if (Protocols.VIRTUAL.protocol.equals(protocol))
{
return virtualStringifier.stringify(reference);
}
else if (Protocols.VANILLA.protocol.equals(protocol))
{
return vanillaStringifier.stringify(reference);
}
else
{
return stringifyUnknown(reference);
}
}
private String stringifyUnknown(Reference reference) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Could not stringify unknown protocol reference s"
+ reference.encode(Encodings.PLAIN.encoding));
}
@Override
public String stringify(Resource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyResource(Resource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyResource(RepositoryResource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyResource(ClasspathResource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringify(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyRepositoryLocation(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyRepositoryLocation(RepositoryNodeRef repositoryNodeRef) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyRepositoryLocation(RepositoryPath repositoryPath) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringify(List<Parameter> parameters) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringify(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyParameter(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyParameter(ResourceParameter resourceParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyParameter(StringParameter stringParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
@Override
public String stringifyParameter(ReferenceParameter referenceParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown hash protocol.");
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.codec.binary.Base64;
/**
* Creates and looks up hashes of '/' paths defining strings.<br>
* Paths are hashed using {@link HashStore} defined hashes. <br>
* Store defined hashes are matched for the longest possible sub-path of a given
* path. The remaining path is encoded using a Base64 encoder. The two resulted
* strings.
*/
public abstract class HierarchicalPathHasher implements PathHasher
{
private static String normalizePath(String classpath)
{
String normalizedClasspath = classpath.trim();
if (!normalizedClasspath.startsWith("/"))
{
normalizedClasspath = "/" + normalizedClasspath;
}
if (normalizedClasspath.endsWith("/"))
{
normalizedClasspath = normalizedClasspath.substring(0,
normalizedClasspath.length() - 1);
}
return normalizedClasspath;
}
protected abstract String hashSubpath(String subpath);
protected abstract String lookupSubpathHash(String hash);
@Override
public Pair<String, String> hash(String path)
{
ParameterCheck.mandatoryString("path",
path);
String normalClasspath = normalizePath(path);
String searchedClasspath = normalClasspath;
String notFoundPath = null;
String hash = hashSubpath(searchedClasspath);
while (hash == null)
{
int lastSeparator = searchedClasspath.lastIndexOf('/');
if (lastSeparator < 0)
{
String code = new String(Base64.encodeBase64(normalClasspath.getBytes(),
false));
return new Pair<String, String>(null,
code);
}
if (notFoundPath != null)
{
notFoundPath = searchedClasspath.substring(lastSeparator + 1) + "/" + notFoundPath;
}
else
{
notFoundPath = searchedClasspath.substring(lastSeparator + 1);
}
searchedClasspath = searchedClasspath.substring(0,
lastSeparator);
hash = hashSubpath(searchedClasspath);
if (hash != null)
{
String notFoundClasspathBase64 = new String(Base64.encodeBase64(notFoundPath.getBytes(),
false));
return new Pair<String, String>(hash,
notFoundClasspathBase64);
}
}
return new Pair<String, String>(hash,
null);
}
@Override
public String lookup(Pair<String, String> hash)
{
if (hash.getSecond() == null)
{
return lookupSubpathHash(hash.getFirst());
}
else if (hash.getFirst() == null)
{
return lookupSubpathCode(hash.getSecond());
}
else
{
String lHash = lookupSubpathHash(hash.getFirst());
String lCode = lookupSubpathCode(hash.getSecond());
return lHash + "/" + lCode;
}
}
private String lookupSubpathCode(String code)
{
if (code.isEmpty())
{
return "/";
}
byte[] decodedBytes = Base64.decodeBase64(code.getBytes());
return new String(decodedBytes);
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.service.cmr.repository.NodeRef;
public class NewVirtualReferenceMethod extends AbstractProtocolMethod<Reference>
{
private String templateSysPath = null;
private NodeRef templateRef = null;
private String templatePath = null;
private NodeRef actualNodeRef = null;
/**
* classpath to the javascript processor of vanilla JSON templates used to construct virtual folders
*/
private String vanillaProcessorClasspath = null;
/**
* @param templateSysPath
* @param templatePath
* @param actualNodeRef
* @param vanillaProcessorClasspath
* @deprecated In future system paths will be replaced with actual resources
* or string encoded references
*/
public NewVirtualReferenceMethod(String templateSysPath, String templatePath, NodeRef actualNodeRef,
String vanillaProcessorClasspath)
{
super();
this.templateSysPath = templateSysPath;
this.templatePath = templatePath;
this.actualNodeRef = actualNodeRef;
this.vanillaProcessorClasspath = vanillaProcessorClasspath;
}
public NewVirtualReferenceMethod(NodeRef templateRef, String templatePath, NodeRef actualNodeRef,
String vanillaProcessorClasspath)
{
super();
this.templateRef = templateRef;
this.templatePath = templatePath;
this.actualNodeRef = actualNodeRef;
this.vanillaProcessorClasspath = vanillaProcessorClasspath;
}
@Override
public Reference execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException
{
if (templateRef != null)
{
return virtualProtocol.newReference(templateRef,
templatePath,
actualNodeRef);
}
else
{
return virtualProtocol.newReference(templateSysPath,
templatePath,
actualNodeRef);
}
}
@Override
public Reference execute(VanillaProtocol vanillaProtocol, Reference reference) throws ProtocolMethodException
{
if (templateRef != null)
{
return vanillaProtocol.newReference(vanillaProcessorClasspath,
templatePath,
actualNodeRef,
templateRef);
}
else
{
return vanillaProtocol.newReference(vanillaProcessorClasspath,
templatePath,
actualNodeRef,
templateSysPath);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.ref.ReferenceParser.Cursor;
/**
* Custom parser for hash encoded strings of {@link Reference}s having the
* protocol set to {@link NodeProtocol}.
*/
public class NodeHashReferenceParser extends ProtocolHashParser
{
private HashReferenceParser referenceParser;
public NodeHashReferenceParser(HashStore classpathHashStore, HashReferenceParser referenceParser)
{
super(classpathHashStore);
this.referenceParser = referenceParser;
}
@Override
public Reference parse(Cursor cursor) throws ReferenceParseException
{
if (!NODE_PROTOCOL_CODE.equals(cursor.currentToken()))
{
throw new ReferenceParseException("Node token \"" + NODE_PROTOCOL_CODE + "\" expected instead of \""
+ cursor.currentToken() + "\"");
}
cursor.i++;
Resource resource = parseResource(cursor);
Reference parentReference = referenceParser.parse(cursor);
return NodeProtocol.newReference(Encodings.HASH.encoding,
resource,
parentReference);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.List;
/**
* Custom stringifier for hash encoded strings of {@link Reference}s having the
* protocol set to {@link NodeProtocol}.
*/
public class NodeHashStringifier extends ProtocolHashStringifier
{
/**
*
*/
private static final long serialVersionUID = 1L;
public NodeHashStringifier(HashStore classpathHashStore, Stringifier referenceDispatcher)
{
super(classpathHashStore,
referenceDispatcher);
}
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
final Protocol protocol = reference.getProtocol();
if (!Protocols.NODE.protocol.equals(protocol))
{
throw new ReferenceEncodingException("Unsupported protocol " + protocol);
}
Resource resource = reference.getResource();
String resourceString = stringify(resource);
List<Parameter> parameters = reference.getParameters();
ReferenceParameter referenceParameter = (ReferenceParameter) parameters.get(0);
Reference parentReference = referenceParameter.getValue();
String parametersString = dispatchStringifyReference(parentReference);
return NODE_PROTOCOL_CODE + "-" + resourceString + "-" + parametersString;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.Arrays;
import org.alfresco.repo.version.Version2Model;
import org.alfresco.repo.version.VersionBaseModel;
import org.alfresco.repo.version.VersionModel;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
public class NodeProtocol extends Protocol
{
/**
*
*/
private static final long serialVersionUID = -6120481299842983600L;
public static Reference newReference(NodeRef nodeRef, Reference parentReference)
{
return new Reference(DEFAULT_ENCODING,
Protocols.NODE.protocol,
new RepositoryResource(new RepositoryNodeRef(nodeRef)),
Arrays.asList(new ReferenceParameter(parentReference)));
}
public static Reference newReference(Encoding encoding, Resource actualNodeResource, Reference parentReference)
{
return new Reference(DEFAULT_ENCODING,
Protocols.NODE.protocol,
actualNodeResource,
Arrays.asList(new ReferenceParameter(parentReference)));
}
public NodeProtocol()
{
super("node");
}
public NodeRef getNodeRef(Reference reference)
{
// TODO: use a resource processor for node ref extraction
RepositoryResource repositoryResource = (RepositoryResource) reference.getResource();
RepositoryNodeRef reposioryNodeRef = (RepositoryNodeRef) repositoryResource.getLocation();
return reposioryNodeRef.getNodeRef();
}
public Reference getVirtualParentReference(Reference reference)
{
return ((ReferenceParameter) reference.getParameters().get(0)).getValue();
}
@Override
public <R> R dispatch(ProtocolMethod<R> method, Reference reference) throws ProtocolMethodException
{
return method.execute(this,
reference);
}
@Override
public Reference propagateNodeRefMutations(NodeRef mutatedNodeRef, Reference reference)
{
StoreRef storeRef = mutatedNodeRef.getStoreRef();
String storeId = storeRef.getIdentifier();
String protocol = storeRef.getProtocol();
if (Version2Model.STORE_ID.equals(storeId) || VersionModel.STORE_ID.equals(storeId)
|| VersionBaseModel.STORE_PROTOCOL.equals(protocol))
{
Resource resource = reference.getResource();
if (resource instanceof RepositoryResource)
{
RepositoryResource repositoryResource = (RepositoryResource) resource;
RepositoryLocation location = repositoryResource.getLocation();
if (location instanceof RepositoryNodeRef)
{
RepositoryNodeRef repositoryNodeRef = (RepositoryNodeRef) location;
NodeRef nodeRef = repositoryNodeRef.getNodeRef();
NodeRef nodeRefPropagation = new NodeRef(mutatedNodeRef.getStoreRef(),
nodeRef.getId());
Resource resourcePropagation = new RepositoryResource(new RepositoryNodeRef(nodeRefPropagation));
return new Reference(reference.getEncoding(),
reference.getProtocol(),
resourcePropagation,
reference.getParameters());
}
}
}
// default branch
return reference;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/**
* Creates and looks up string-pair hash codes of {@link NodeRef}s.<br>
*/
public interface NodeRefHasher
{
NodeRef lookup(Pair<String, String> hash);
Pair<String, String> hash(NodeRef nodeRef);
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.math.BigInteger;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.util.Pair;
import org.apache.commons.lang.StringUtils;
import com.sun.star.uno.RuntimeException;
/**
* Creates string-pair hashes of {@link NodeRef}s where the first string is a
* stored hash combination for {@link NodeRef} store elements (protocol and id)
* and the second is a radix 36 encoded {@link NodeRef} id.
*/
public class NodeRefRadixHasher implements NodeRefHasher
{
public static final NodeRefRadixHasher RADIX_36_HASHER = new NodeRefRadixHasher(36);
private HashStore storeProtocolStore;
private HashStore storeIdStore;
private int radix;
public NodeRefRadixHasher()
{
this(16);
}
public NodeRefRadixHasher(int radix)
{
super();
this.radix = radix;
this.storeProtocolStore = HashStoreConfiguration.getInstance().getStoreProtocolStore();
this.storeIdStore = HashStoreConfiguration.getInstance().getStoreIdStore();
}
@Override
public Pair<String, String> hash(NodeRef nodeRef)
{
String uuid = nodeRef.getId();
if (uuid.length() != 36)
{
throw new RuntimeException("Invalid noderf id length " + uuid);
}
String bigInt16String = uuid.replaceAll("-",
"");
if (bigInt16String.length() != 32)
{
throw new RuntimeException("Invalid noderf id format " + uuid);
}
BigInteger bigIntId = new BigInteger(bigInt16String,
16);
StoreRef storeRef = nodeRef.getStoreRef();
String storeProtocolHash = storeProtocolStore.hash(storeRef.getProtocol());
String storeIdHash = storeIdStore.hash(storeRef.getIdentifier());
if (storeProtocolHash == null || storeIdHash == null)
{
throw new RuntimeException("Missing hash for " + storeRef);
}
String storeHash = storeProtocolHash + storeIdHash;
return new Pair<String, String>(storeHash,
bigIntId.toString(radix));
}
@Override
public NodeRef lookup(Pair<String, String> hash)
{
String storeHash = hash.getFirst();
String storeProtocolHash = storeHash.substring(0,
1);
String storeIdHash = storeHash.substring(1,
2);
String storeProtocol = storeProtocolStore.lookup(storeProtocolHash);
String storeId = storeIdStore.lookup(storeIdHash);
if (storeProtocol == null || storeId == null)
{
throw new RuntimeException("Lookup found no protocol or id for " + storeHash);
}
BigInteger nodeId = new BigInteger(hash.getSecond(),
radix);
String nodeIdHexa = nodeId.toString(16);
nodeIdHexa = StringUtils.leftPad(nodeIdHexa,
32,
"0");
int leadZeros = 32 - nodeIdHexa.length();
if (leadZeros > 0)
{
}
String groups[] = new String[5];
groups[0] = nodeIdHexa.substring(0,
8);
groups[1] = nodeIdHexa.substring(8,
12);
groups[2] = nodeIdHexa.substring(12,
16);
groups[3] = nodeIdHexa.substring(16,
20);
groups[4] = nodeIdHexa.substring(20,
32);
StringBuilder idBuilder = new StringBuilder(groups[0]);
for (int i = 1; i < groups.length; i++)
{
idBuilder.append("-");
idBuilder.append(groups[i]);
}
return new NodeRef(storeProtocol,
storeId,
idBuilder.toString());
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.apache.commons.lang.StringUtils;
/**
* Creates string-pair hashes of single digit element numeric paths.<br>
* @see HierarchicalPathHasher
*/
public class NumericPathHasher extends HierarchicalPathHasher
{
@Override
protected String hashSubpath(String subpath)
{
try
{
if (subpath.trim().isEmpty())
{
return null;
}
String[] numericPathElements = subpath.split("/");
if (numericPathElements == null || numericPathElements.length == 0)
{
return "0";
}
long lHash = 0;
for (int i = numericPathElements[0].isEmpty() ? 1 : 0; i < numericPathElements.length; i++)
{
if (numericPathElements[i].length() == 1)
{
long intPathElement = Long.parseLong(numericPathElements[i]);
if (intPathElement > 0)
{
lHash = lHash * 10 + intPathElement;
if (lHash < 0)
{
return null;
}
else
{
continue;
}
}
else
{
return null;
}
}
else
{
return null;
}
}
return "" + lHash;
}
catch (NumberFormatException e)
{
return null;
}
}
@Override
protected String lookupSubpathHash(String hash)
{
String[] digits = hash.split("(?<=.)");
return "/" + StringUtils.join(digits,
'/');
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public interface Parameter
{
/**
* Converts the value attribute into a string representation according to
* {@link Encodings} definition, using provided {@link Stringifier}
* parameter.
*
* @param stringifier
* @return the string representation of this parameter as provided by the
* given {@link Stringifier}
* @throws ReferenceEncodingException
*/
String stringify(Stringifier stringifier) throws ReferenceEncodingException;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.util.Pair;
public interface PathHasher
{
Pair<String,String> hash(String path);
String lookup(Pair<String,String> hash);
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public interface PlainEncoding
{
static final String DELIMITER = ":";
static final String REFERENCE_DELIMITER = "*";
static final String REPOSITORY = "repository";
static final String CLASSPATH = "classpath";
static final String PATH = "path";
static final String NODE = "node";
static final String INT_PARAMETER = "i";
static final String STRING_PARAMETER = "s";
static final String RESOURCE_PARAMETER = "r";
static final String REFERENCE_PARAMETER = "ref";
}

View File

@@ -0,0 +1,289 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Parses string references into {@link Reference} objects based on Plain
* encodings grammar.
* <p>
* For grammar examples see {@link Encodings#PLAIN} encoding definition.
*/
public class PlainReferenceParser implements ReferenceParser, PlainEncoding
{
/**
*
*/
private static final long serialVersionUID = -7053644289373735564L;
@Override
public Reference parse(String referenceString) throws ReferenceParseException
{
String[] referenceTokens = referenceString.split(DELIMITER);
final Cursor cursor = new Cursor(referenceTokens,
0);
if (referenceTokens.length < 2)
{
throw new ReferenceParseException("Invalid reference " + referenceString);
}
return this.parseReference(cursor);
}
private Reference parseReference(Cursor cursor) throws ReferenceParseException
{
try
{
final String protocolString = cursor.tokens[cursor.i];
final Protocol protocol = Protocols.fromName(protocolString);
if (protocol == null)
{
throw new ReferenceParseException("Unknown protocol " + protocolString);
}
cursor.i++;
final Resource resource = parseResource(cursor);
final List<Parameter> parameters = parseParameters(cursor);
return new Reference(Encodings.PLAIN.encoding,
protocol,
resource,
parameters);
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new ReferenceParseException("Invalid reference",
e);
}
}
/**
* Obtains a list of {@link Parameter} from the cursor parameter
*
* @param cursor
* @return a list of {@link Parameter} from the cursor parameter
* @throws ReferenceParseException
*/
private List<Parameter> parseParameters(Cursor cursor) throws ReferenceParseException
{
List<Parameter> parameters = new ArrayList<>();
while (cursor.i < cursor.tokens.length)
{
if (RESOURCE_PARAMETER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseResourceParameter(cursor));
}
else if (STRING_PARAMETER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseStringParameter(cursor));
}
else if (REFERENCE_PARAMETER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseReferenceParameter(cursor));
}
else if (REFERENCE_DELIMITER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
break;
}
else
{
throw new ReferenceParseException("Invalid parameter " + cursor.tokens[cursor.i]);
}
}
return parameters;
}
/**
* Obtains a {@link Parameter} reference that is instance of
* {@link StringParameter} from the cursor parameter
*
* @param cursor
* @return a {@link Parameter} reference that is instance of
* {@link StringParameter} from the cursor parameter
*/
private Parameter parseStringParameter(Cursor cursor)
{
StringParameter paramenter = new StringParameter(cursor.tokens[cursor.i]);
cursor.i++;
return paramenter;
}
/**
* Obtains a {@link Parameter} reference that is instance of
* {@link ResourceParameter} from the cursor parameter
*
* @param cursor
* @return a {@link Parameter} reference that is instance of
* {@link ResourceParameter} from the cursor parameter
* @throws ReferenceParseException
*/
private Parameter parseResourceParameter(Cursor cursor) throws ReferenceParseException
{
Resource resource = parseResource(cursor);
return new ResourceParameter(resource);
}
/**
* Obtains {@link Resource} reference witch is an instance of
* {@link RepositoryResource} if current token is
* {@link PlainEncoding#REPOSITORY} or an instance of
* {@link ClasspathResource} if current token is
* {@link PlainEncoding#CLASSPATH}
*
* @param cursor
* @return {@link Resource} reference witch an instance of
* {@link RepositoryResource} if current token is
* {@link PlainEncoding#REPOSITORY} or an instance of
* {@link ClasspathResource} if current token is
* {@link PlainEncoding#CLASSPATH}
* @throws ReferenceParseException
*/
private Resource parseResource(Cursor cursor) throws ReferenceParseException
{
if (REPOSITORY.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
return parseRepositoryResource(cursor);
}
else if (CLASSPATH.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
return parseClasspathResource(cursor);
}
else
{
throw new ReferenceParseException("Invalid resource " + cursor.tokens[cursor.i]);
}
}
/**
* Obtains {@link RepositoryResource} reference from the cursor parameter
*
* @param cursor
* @return A {@link RepositoryResource} reference from the cursor parameter
* @throws ReferenceParseException
*/
private RepositoryResource parseRepositoryResource(Cursor cursor) throws ReferenceParseException
{
return new RepositoryResource(parseRepositoryLocation(cursor));
}
/**
* Obtains {@link RepositoryLocation} reference witch is an instance of
* {@link RepositoryPath} if current token is {@link PlainEncoding#PATH} or
* an instance of {@link RepositoryNodeRef} if current token is
* {@link PlainEncoding#NODE}
*
* @param cursor
* @return A {@link RepositoryLocation} reference witch an instance of
* {@link RepositoryPath} if current token is
* {@link PlainEncoding#PATH} or an instance of
* {@link RepositoryNodeRef} if current token is
* {@link PlainEncoding#NODE}
* @throws ReferenceParseException
*/
private RepositoryLocation parseRepositoryLocation(Cursor cursor) throws ReferenceParseException
{
if (PATH.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
return parseRepositoryPath(cursor);
}
else if (NODE.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
return parseRepositoryNode(cursor);
}
else
{
throw new ReferenceParseException("Invalid location " + cursor.tokens[cursor.i]);
}
}
/**
* Obtains {@link RepositoryPath} reference from current token of the cursor
* parameter
*
* @param cursor
* @return A {@link RepositoryPath} reference from current token of the
* cursor parameter
*/
private RepositoryPath parseRepositoryPath(Cursor cursor)
{
String path = cursor.tokens[cursor.i];
cursor.i++;
return new RepositoryPath(path);
}
/**
* Obtains {@link RepositoryNodeRef} reference from store protocol, store
* identifier and node id obtained from cursor's tokens starting with
* current token of the cursor.
*
* @param cursor
* @return A {@link RepositoryNodeRef} reference from store protocol, store
* identifier and node id obtained from cursor's tokens starting
* with current token of the cursor.
*/
private RepositoryNodeRef parseRepositoryNode(Cursor cursor)
{
String storeProtocol = cursor.tokens[cursor.i];
String storeIdentifier = cursor.tokens[cursor.i + 1];
String id = cursor.tokens[cursor.i + 2];
cursor.i += 3;
return new RepositoryNodeRef(new NodeRef(storeProtocol,
storeIdentifier,
id));
}
/**
* Obtains {@link ClasspathResource} reference from current token of the
* cursor parameter
*
* @param cursor
* @return A {@link ClasspathResource} reference from current token of the
* cursor parameter
*/
private ClasspathResource parseClasspathResource(Cursor cursor)
{
String classpath = cursor.tokens[cursor.i];
cursor.i++;
return new ClasspathResource(classpath);
}
private ReferenceParameter parseReferenceParameter(Cursor cursor) throws ReferenceParseException
{
Reference reference = parseReference(cursor);
ReferenceParameter parameter = new ReferenceParameter(reference);
return parameter;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Converts the object to a string representation according to
* {@link Encodings#PLAIN} encoding definition.
*/
public class PlainStringifier implements Stringifier, PlainEncoding
{
/**
*
*/
private static final long serialVersionUID = -8169416257716384803L;
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
return reference.getProtocol() + DELIMITER + stringify(reference.getResource())
+ stringify(reference.getParameters());
}
@Override
public String stringify(Resource resource) throws ReferenceEncodingException
{
return resource.stringify(this);
}
@Override
public String stringifyResource(Resource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid reference " + resource.getClass());
}
@Override
public String stringifyResource(RepositoryResource resource) throws ReferenceEncodingException
{
return REPOSITORY + DELIMITER + stringify(resource.getLocation());
}
@Override
public String stringifyResource(ClasspathResource resource)
{
return CLASSPATH + DELIMITER + resource.getClasspath();
}
@Override
public String stringify(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
return repositoryLocation.stringify(this);
}
@Override
public String stringifyRepositoryLocation(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid location " + repositoryLocation.getClass());
}
@Override
public String stringifyRepositoryLocation(RepositoryNodeRef repositoryNodeRef) throws ReferenceEncodingException
{
NodeRef nodeRef = repositoryNodeRef.getNodeRef();
StoreRef storeRef = nodeRef.getStoreRef();
return NODE + DELIMITER + storeRef.getProtocol() + DELIMITER + storeRef.getIdentifier() + DELIMITER
+ nodeRef.getId();
}
@Override
public String stringifyRepositoryLocation(RepositoryPath repositoryPath) throws ReferenceEncodingException
{
return PATH + DELIMITER + repositoryPath.getPath();
}
@Override
public String stringify(List<Parameter> parameters) throws ReferenceEncodingException
{
StringBuilder parametersBuilder = new StringBuilder();
for (Parameter parameter : parameters)
{
parametersBuilder.append(DELIMITER);
parametersBuilder.append(stringify(parameter));
}
return parametersBuilder.toString();
}
@Override
public String stringify(Parameter parameter) throws ReferenceEncodingException
{
return parameter.stringify(this);
}
@Override
public String stringifyParameter(ResourceParameter resourceParameter) throws ReferenceEncodingException
{
return RESOURCE_PARAMETER + DELIMITER + stringify(resourceParameter.getValue());
}
@Override
public String stringifyParameter(StringParameter stringParameter) throws ReferenceEncodingException
{
return STRING_PARAMETER + DELIMITER + stringParameter.getValue();
}
@Override
public String stringifyParameter(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid parameter " + parameter.getClass());
}
@Override
public String stringifyParameter(ReferenceParameter parameter) throws ReferenceEncodingException
{
return REFERENCE_PARAMETER + DELIMITER + stringify(parameter.getValue()) + DELIMITER + REFERENCE_DELIMITER;
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.Serializable;
import java.util.ArrayList;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A {@link Reference} model element that defines the type of the referred
* artefact and the virtualization process that was applied when creating a
* reference.<br>
* Protocols define the semantics of all elements of a reference. Protocol
* implementations add syntactic processing methods.<br>
* The high level semantic functionality of a protocol is implemented with
* {@link ProtocolMethod}s.
*
* @author Bogdan Horje
*/
public class Protocol implements Serializable
{
/**
*
*/
private static final long serialVersionUID = -6969613804420028905L;
public final String name;
protected static final Encoding DEFAULT_ENCODING = Encodings.HASH.encoding;
public Protocol(String name)
{
super();
this.name = name;
}
public Parameter getParameter(Reference reference, int index)
{
return reference.getParameters().get(index);
}
public Reference replaceParameter(Reference reference, int index, String stringParameter)
{
return replaceParameter(reference,
index,
new StringParameter(stringParameter));
}
public Reference replaceParameter(Reference reference, int index, Parameter parameter)
{
ArrayList<Parameter> parameters = new ArrayList<Parameter>(reference.getParameters());
parameters.set(index,
parameter);
return new Reference(reference.getEncoding(),
reference.getProtocol(),
reference.getResource(),
parameters);
}
public Reference addParameter(Reference reference, Resource resource)
{
return addParameter(reference,
new ResourceParameter(resource));
}
public Reference addParameter(Reference reference, Parameter parameter)
{
ArrayList<Parameter> parameters = new ArrayList<Parameter>(reference.getParameters());
parameters.add(parameter);
return new Reference(reference.getEncoding(),
reference.getProtocol(),
reference.getResource(),
parameters);
}
/**
* {@link ProtocolMethod} double-dispatch/visitor protocol type selector.
* Subclasses should override this method to select the appropriate type
* bound method.<br>
* This particular implementation calls the default
* {@link ProtocolMethod#execute(Protocol, Reference)} default method
* implementation.
*
* @param method
* @param reference
* @return the value returned by the type bond method
* @throws ProtocolMethodException
*/
public <R> R dispatch(ProtocolMethod<R> method, Reference reference) throws ProtocolMethodException
{
return method.execute(this,
reference);
}
@Override
public String toString()
{
return name;
}
/**
* {@link Protocol} delegate of
* {@link Reference#propagateNodeRefMutations(NodeRef)}
*
* @param mutatedNodeRef
* @param reference
* @return a mutated version of the given {@link Reference} corresponding to
* the given mutated node or the given {@link Reference} if no
* mutations are detected
*/
public Reference propagateNodeRefMutations(NodeRef mutatedNodeRef, Reference reference)
{
// nothing to propagate by default
return reference;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.ref.ReferenceParser.Cursor;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/**
* Base class for custom protocol hash encoded {@link ReferenceParser}s.
*/
public abstract class ProtocolHashParser implements HashEncodingArtefact
{
protected abstract Reference parse(Cursor cursor) throws ReferenceParseException;
private NodeRefHasher nodeRefHasher = NodeRefRadixHasher.RADIX_36_HASHER;
private PathHasher classpathHasher;
private PathHasher repositoryPathHasher;
public ProtocolHashParser(HashStore classpathHashStore)
{
this.classpathHasher = new StoredPathHasher(classpathHashStore);
this.repositoryPathHasher = new StoredPathHasher(classpathHashStore);
}
protected Resource parseResource(Cursor cursor) throws ReferenceParseException
{
String token = cursor.nextToken();
if (REPOSITORY_NODEREF_RESOURCE_CODE.equals(token))
{
String nodeRefHash = cursor.nextToken();
String storeHash = nodeRefHash.substring(0,
2);
String nodeIdHash = nodeRefHash.substring(2);
NodeRef nodeRef = nodeRefHasher.lookup(new Pair<String, String>(storeHash,
nodeIdHash));
return new RepositoryResource(new RepositoryNodeRef(nodeRef));
}
else if (HASHED_CLASSPATH_RESOUCE_CODE.equals(token))
{
String cp = classpathHasher.lookup(new Pair<String, String>(cursor.nextToken(),
null));
return new ClasspathResource(cp);
}
else if (MIXED_CLASSPATH_RESOUCE_CODE.equals(token))
{
String cp = classpathHasher.lookup(new Pair<String, String>(cursor.nextToken(),
cursor.nextToken()));
return new ClasspathResource(cp);
}
else if (CLASSPATH_RESOUCE_CODE.equals(token))
{
String cp = classpathHasher.lookup(new Pair<String, String>(null,
cursor.nextToken()));
return new ClasspathResource(cp);
}
else if (HASHED_REPOSITORY_PATH_CODE.equals(token))
{
String path = repositoryPathHasher.lookup(new Pair<String, String>(cursor.nextToken(),
null));
return new RepositoryResource(new RepositoryPath(path));
}
else if (MIXED_REPOSITORY_PATH_CODE.equals(token))
{
String path = repositoryPathHasher.lookup(new Pair<String, String>(cursor.nextToken(),
cursor.nextToken()));
return new RepositoryResource(new RepositoryPath(path));
}
else if (REPOSITORY_PATH_CODE.equals(token))
{
String path = repositoryPathHasher.lookup(new Pair<String, String>(null,
cursor.nextToken()));
return new RepositoryResource(new RepositoryPath(path));
}
else
{
throw new ReferenceParseException("Unknown resource token " + token + " at " + (cursor.i--));
}
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/**
* Base class for custom protocol hash encoded {@link Stringifier}s.
*/
public abstract class ProtocolHashStringifier implements HashEncodingArtefact, Stringifier
{
/**
*
*/
private static final long serialVersionUID = 6471653470842760043L;
private NodeRefHasher nodeRefHasher = NodeRefRadixHasher.RADIX_36_HASHER;
private PathHasher classpathHasher;
private PathHasher repositoryPathHasher;
private Stringifier referenceDispatcher;
public ProtocolHashStringifier(HashStore classpathHashStore, Stringifier referenceDispatcher)
{
this.classpathHasher = new StoredPathHasher(classpathHashStore);
this.repositoryPathHasher=new StoredPathHasher(classpathHashStore);
this.referenceDispatcher = referenceDispatcher;
}
protected String dispatchStringifyReference(Reference reference)
{
return referenceDispatcher.stringify(reference);
}
@Override
public String stringify(Resource resource) throws ReferenceEncodingException
{
return resource.stringify(this);
}
@Override
public String stringifyResource(Resource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown resource type " + resource);
}
@Override
public String stringifyResource(RepositoryResource resource) throws ReferenceEncodingException
{
RepositoryLocation location = resource.getLocation();
return location.stringify(this);
}
@Override
public String stringifyResource(ClasspathResource resource) throws ReferenceEncodingException
{
String cp = resource.getClasspath();
Pair<String, String> hash = classpathHasher.hash(cp);
final String hashed = hash.getFirst();
final String nonHashed = hash.getSecond();
if (nonHashed == null)
{
return HASHED_CLASSPATH_RESOUCE_CODE + "-" + hashed;
}
else if (hashed == null)
{
return CLASSPATH_RESOUCE_CODE + "-" + nonHashed;
}
else
{
return MIXED_CLASSPATH_RESOUCE_CODE + "-" + hashed + "-" + nonHashed;
}
}
@Override
public String stringify(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
return repositoryLocation.stringify(this);
}
@Override
public String stringifyRepositoryLocation(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Unknown repository location " + repositoryLocation);
}
@Override
public String stringifyRepositoryLocation(RepositoryNodeRef repositoryNodeRef) throws ReferenceEncodingException
{
NodeRef nodeRef = repositoryNodeRef.getNodeRef();
Pair<String, String> hash = nodeRefHasher.hash(nodeRef);
return REPOSITORY_NODEREF_RESOURCE_CODE + "-" + hash.getFirst() + hash.getSecond();
}
@Override
public String stringifyRepositoryLocation(RepositoryPath repositoryPath) throws ReferenceEncodingException
{
String cp = repositoryPath.getPath();
Pair<String, String> hash = repositoryPathHasher.hash(cp);
final String hashed = hash.getFirst();
final String nonHashed = hash.getSecond();
if (nonHashed == null)
{
return HASHED_REPOSITORY_PATH_CODE + "-" + hashed;
}
else if (hashed == null)
{
return REPOSITORY_PATH_CODE + "-" + nonHashed;
}
else
{
return MIXED_REPOSITORY_PATH_CODE + "-" + hashed + "-" + nonHashed;
}
}
// parameters
@Override
public String stringify(List<Parameter> parameters) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + parameters);
}
@Override
public String stringify(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + parameter);
}
@Override
public String stringifyParameter(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + parameter);
}
@Override
public String stringifyParameter(ResourceParameter resourceParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + resourceParameter);
}
@Override
public String stringifyParameter(StringParameter stringParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + stringParameter);
}
@Override
public String stringifyParameter(ReferenceParameter referenceParameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid stringifier cotext " + referenceParameter);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* A double-dispatched method abstraction.<br>
* The method execution is dispatched based on concrete protocol type.<br>
* Implementor encapsulate high-level reference protocol based semantic
* functionality.
*
* @param <R> method return type
* @see Reference#execute(ProtocolMethod)
* @author Bogdan Horje
*/
public interface ProtocolMethod<R>
{
R execute(VanillaProtocol vanillaProtocol, Reference reference) throws ProtocolMethodException;
R execute(VirtualProtocol virtualProtocol, Reference reference) throws ProtocolMethodException;
R execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException;
R execute(Protocol protocol, Reference reference) throws ProtocolMethodException;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.VirtualizationException;
public class ProtocolMethodException extends VirtualizationException
{
private static final long serialVersionUID = -7476127763746116107L;
public ProtocolMethodException()
{
super();
}
public ProtocolMethodException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public ProtocolMethodException(String message, Throwable cause)
{
super(message,
cause);
}
public ProtocolMethodException(String message)
{
super(message);
}
public ProtocolMethodException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.HashMap;
import java.util.Map;
/**
* Common {@link Reference} protocols.
*/
public enum Protocols
{
NODE(new NodeProtocol()), VIRTUAL(new VirtualProtocol()), VANILLA(new VanillaProtocol());
private static volatile Map<String, Protocol> protocolsMap;
public static synchronized Protocol fromName(String name)
{
return protocolsMap.get(name);
}
private synchronized static void register(Protocol protocol)
{
if (protocolsMap == null)
{
protocolsMap = new HashMap<>();
}
protocolsMap.put(protocol.name,
protocol);
}
public final Protocol protocol;
Protocols(Protocol protocol)
{
this.protocol = protocol;
register(protocol);
}
}

View File

@@ -0,0 +1,389 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.repo.version.common.VersionUtil;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A generic, immutable virtualized artefact reference.<br>
* Refers virtualized artefacts through :<br>
* <ul>
* <li>a {@link Protocol} - defines what kind of virtualzied artefact is
* referred by this reference as well as what virtualization process was applied
* </li>
* <li>a {@link Resource} - identifies the main resource used in the
* virtualization (egg. a classpath location or repository node reference)</li>
* <li>a list of {@link ResourceParameter}s - used in customizing the
* virtualization process (egg. a resource pointing to the actual node of a
* semi-virtual folder reference)</li>
* </ul>
*
* @author Bogdan Horje
*/
public class Reference
{
private static Log logger = LogFactory.getLog(Reference.class);
private static final Character VIRTUAL_TOKEN = 'v';
/**
* Quick Reference compliance check of a {@link NodeRef}.<br>
* NodeRef Reference representations validated by this method should produce
* valid Reference objects based on the given {@link NodeRef} when passed to
* the {@link #fromNodeRef(NodeRef)} method.
*
* @param nodeRef
* @return <code>true</code> if the given {@link NodeRef} is a valid
* Reference representation<br>
* <code>false</code> otherwise
*/
public static final boolean isReference(NodeRef nodeRef)
{
if (nodeRef != null)
{
String id = nodeRef.getId();
if (id != null)
{
char zeroChar = id.charAt(0);
return VIRTUAL_TOKEN.equals(zeroChar);
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("NodeRef with null ID.");
}
}
}
return false;
}
/**
* {@link NodeRef} {@link Reference} representation decoder/converter
* method.<br>
* Creates a {@link Reference} representation based on the ID of the given
* {@link NodeRef}.<br>
* It expects a {@link #VIRTUAL_TOKEN} prefixed encoded string. The encoded
* string must start with a valid {@link Encoding} token. The Reference
* representation structure is (no delimiters between the 3 elements):
* VIRTUAL_TOKEN ENCODING_TOKEN referenceString Given that a valid encoding
* was detected {@link Encoding#urlNative} information is used to obtain a
* reference string. The reference string is parsed using the encoding
* configured parser.
*
* @param nodeRef
* @return the {@link Reference} object corresponding to the given
* {@link NodeRef}
* @throws ReferenceParseException if an error occurs during the reference
* string parsing
* @throws ReferenceEncodingException if the {@link NodeRef} ID has an
* invalid virtual token prefix or it uses an invalid encoding
* token
*/
public static final Reference fromNodeRef(NodeRef nodeRef) throws ReferenceParseException,
ReferenceEncodingException
{
String id = nodeRef.getId();
if (id.startsWith("" + VIRTUAL_TOKEN))
{
char token = id.charAt(1);
Encoding encoding = Encodings.fromToken(token);
if (encoding == null)
{
throw new ReferenceEncodingException("Invalid encoding token " + token + " in " + id);
}
else
{
String referenceString = id.substring(2);
if (!encoding.urlNative)
{
referenceString = new String(org.apache.commons.codec.binary.Base64.decodeBase64(referenceString));
}
Reference reference = encoding.parser.parse(referenceString);
return reference.propagateNodeRefMutations(nodeRef);
}
}
else
{
throw new ReferenceEncodingException("Invalid node ID format " + id);
}
}
// Average reference length DEBUG trace
private static long _debug_refLength = 0;
private static long _debug_refCount = 0;
private static final long _debug_refBatchSize = 256;
private static synchronized void debug_avg_ref_length(long refLength)
{
_debug_refLength += refLength;
_debug_refCount++;
if (_debug_refBatchSize > 0 && _debug_refCount % _debug_refBatchSize == 0)
{
logger.debug("Average reference encoding size : " + (_debug_refLength / _debug_refCount));
_debug_refCount = 0;
_debug_refLength = 0;
}
}
private Encoding encoding;
private Protocol protocol;
private Resource resource;
private List<Parameter> parameters;
/**
* Constructor
*
* @param encoding the default {@link Encoding} of the new resource - to be
* used where an encoding is required and none is specified
* @param protocol
* @param resource
* @param parameters resource parameters - a copy of the provided list will
* be stored by this reference
*/
public Reference(Encoding encoding, Protocol protocol, Resource resource, List<? extends Parameter> parameters)
{
this.encoding = encoding;
this.protocol = protocol;
this.resource = resource;
this.parameters = new LinkedList<>(parameters);
}
public Reference(Encoding encoding, Protocol protocol, Resource resource)
{
this(encoding,
protocol,
resource,
Collections.<Parameter> emptyList());
}
/**
* @return a {@link String} representation of this reference using its
* default {@link Encoding}
* @throws ReferenceEncodingException
*/
public String encode() throws ReferenceEncodingException
{
return encode(this.encoding);
}
/**
* @param anEncoding
* @return a {@link String} representation of this reference using the given
* {@link Encoding}
* @throws ReferenceEncodingException
*/
public String encode(Encoding anEncoding) throws ReferenceEncodingException
{
return anEncoding.stringifier.stringify(this);
}
/**
* @return the default {@link Encoding} of this reference
*/
public Encoding getEncoding()
{
return this.encoding;
}
public Protocol getProtocol()
{
return this.protocol;
}
public Resource getResource()
{
return this.resource;
}
public List<Parameter> getParameters()
{
return parameters;
}
/**
* @return a {@link NodeRef} representation of this resource using the
* {@link StoreRef#STORE_REF_WORKSPACE_SPACESSTORE} and the default
* encoding of this resource
* @throws ReferenceEncodingException
*/
public NodeRef toNodeRef() throws ReferenceEncodingException
{
return toNodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
}
/**
* @param storeRef
* @return a {@link NodeRef} representation of this resource using the given
* {@link StoreRef} and the default encoding of this resource
* @throws ReferenceEncodingException
*/
public NodeRef toNodeRef(StoreRef storeRef) throws ReferenceEncodingException
{
return toNodeRef(storeRef,
this.encoding);
}
/**
* @param storeRef
* @param encoding
* @return a {@link NodeRef} representation of this resource using the given
* {@link StoreRef} and {@link Encoding}
* @throws ReferenceEncodingException
*/
public NodeRef toNodeRef(StoreRef storeRef, Encoding encoding) throws ReferenceEncodingException
{
String id = encode(encoding);
// TODO: move non-native encoding to encoding object itself
if (!encoding.urlNative)
{
id = new String(org.apache.commons.codec.binary.Base64.encodeBase64(id.getBytes(),
false));
}
StringBuilder idBuilder = new StringBuilder();
idBuilder.append(VIRTUAL_TOKEN);
idBuilder.append(encoding.token);
idBuilder.append(id);
NodeRef theNode = new NodeRef(storeRef,
idBuilder.toString());
if (logger.isDebugEnabled())
{
debug_avg_ref_length(theNode.toString().length());
}
return theNode;
}
/**
* Double-dispatches {@link ProtocolMethod}s.<br>
* Uses {@link Protocol#dispatch(ProtocolMethod, Reference)} to trigger
* concrete protocol based double dispatch
* <code>ProtocolMethod::execute</code> invocation on the given method
* object.
*
* @param method
* @return the dispatched method execution result
* @throws ProtocolMethodException
*/
public <R> R execute(ProtocolMethod<R> method) throws ProtocolMethodException
{
return this.protocol.dispatch(method,
this);
}
/**
* Despite claimed {@link NodeRef} opacity Alfresco sometimes alters
* NodeRefs representation to achieve functionality. For example see
* {@link VersionUtil#convertNodeRef(NodeRef)}.<br>
* We say that altered {@link NodeRef}s have suffered mutations and we try
* to detect those mutations and create a correspondent reference.
*
* @param mutatedNodeRef
* @return a mutated version of this {@link Reference} corresponding to the
* given mutated node or
* <code>this<code> Reference if no mutations are detected
*/
public Reference propagateNodeRefMutations(NodeRef mutatedNodeRef)
{
return protocol.propagateNodeRefMutations(mutatedNodeRef,
this);
}
@Override
public String toString()
{
try
{
return encode();
}
catch (ReferenceEncodingException e)
{
logger.error("Invalid reference",
e);
return super.toString();
}
}
@Override
public int hashCode()
{
return resource != null ? resource.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(obj instanceof Reference))
{
return false;
}
Reference other = (Reference) obj;
if (resource == null)
{
return other.resource == null;
}
else
{
if (!this.resource.equals(other.resource))
{
return false;
}
else
{
if (parameters == null)
{
return other.parameters == null;
}
else
{
return parameters.equals(other.parameters);
}
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.VirtualizationException;
public class ReferenceEncodingException extends VirtualizationException
{
private static final long serialVersionUID = 8952014414253439106L;
public ReferenceEncodingException()
{
super();
}
public ReferenceEncodingException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public ReferenceEncodingException(String message, Throwable cause)
{
super(message,
cause);
}
public ReferenceEncodingException(String message)
{
super(message);
}
public ReferenceEncodingException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public class ReferenceParameter extends ValueParameter<Reference>
{
public ReferenceParameter(Reference reference)
{
super(reference);
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyParameter(this);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import org.alfresco.repo.virtual.VirtualizationException;
public class ReferenceParseException extends VirtualizationException
{
private static final long serialVersionUID = 7234372861104307635L;
public ReferenceParseException()
{
super();
}
public ReferenceParseException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public ReferenceParseException(String message, Throwable cause)
{
super(message,
cause);
}
public ReferenceParseException(String message)
{
super(message);
}
public ReferenceParseException(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.Serializable;
public interface ReferenceParser extends Serializable
{
/**
* Helper class used in parsing string reference.
*/
class Cursor
{
/**
* Tokens obtained by splitting the reference string using
* {@link PlainEncoding#DELIMITER}
*/
String[] tokens;
/**
* Current processed Token
*/
int i;
Cursor(String[] tokens, int i)
{
super();
this.tokens = tokens;
this.i = i;
}
String currentToken()
{
return tokens[i];
}
String nextToken()
{
String c = tokens[i];
i++;
return c;
}
boolean hasNext()
{
return i < tokens.length;
}
}
/**
* Parses a string reference into a {@link Reference} object
*
* @param referenceString
* @return A reference of {@link Reference}
* @throws ReferenceParseException
*/
Reference parse(String referenceString) throws ReferenceParseException;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* An Alfresco repository content abstraction.
*
* @author Bogdan Horje
*/
public interface RepositoryLocation
{
String stringify(Stringifier stringifier) throws ReferenceEncodingException;
InputStream openContentStream(ActualEnvironment environment) throws ActualEnvironmentException;
NodeRef asNodeRef(ActualEnvironment environment) throws ActualEnvironmentException;
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.service.cmr.repository.NodeRef;
public class RepositoryNodeRef implements RepositoryLocation
{
private NodeRef nodeRef;
public RepositoryNodeRef(NodeRef aNodeRef)
{
this.nodeRef = aNodeRef;
}
public NodeRef getNodeRef()
{
return nodeRef;
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyRepositoryLocation(this);
}
@Override
public int hashCode()
{
return nodeRef != null ? nodeRef.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(obj instanceof RepositoryNodeRef))
{
return false;
}
RepositoryNodeRef other = (RepositoryNodeRef) obj;
if (nodeRef == null)
{
return other.nodeRef == null;
}
else
{
return this.nodeRef.equals(other.nodeRef);
}
}
@Override
public InputStream openContentStream(ActualEnvironment environment) throws ActualEnvironmentException
{
return environment.openContentStream(nodeRef);
}
@Override
public NodeRef asNodeRef(ActualEnvironment environment) throws ActualEnvironmentException
{
return getNodeRef();
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.service.cmr.repository.NodeRef;
public class RepositoryPath implements RepositoryLocation
{
private String path;
public RepositoryPath(String aPath)
{
this.path = aPath;
}
public String getPath()
{
return path;
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyRepositoryLocation(this);
}
@Override
public int hashCode()
{
return this.path != null ? this.path.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(obj instanceof RepositoryPath))
{
return false;
}
RepositoryPath other = (RepositoryPath) obj;
if (path == null)
{
return other.path == null;
}
else
{
return this.path.equals(other.path);
}
}
@Override
public InputStream openContentStream(ActualEnvironment environment) throws ActualEnvironmentException
{
throw new ActualEnvironmentException("Not implemented!");
}
@Override
public NodeRef asNodeRef(ActualEnvironment environment) throws ActualEnvironmentException
{
throw new RuntimeException("Not implemented!");
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
/**
* Identifies content from {@link RepositoryLocation}
*/
public class RepositoryResource implements Resource
{
private RepositoryLocation location;
public RepositoryResource(RepositoryLocation aLocation)
{
this.location = aLocation;
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyResource(this);
}
public RepositoryLocation getLocation()
{
return location;
}
@Override
public int hashCode()
{
return location != null ? location.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(obj instanceof RepositoryResource))
{
return false;
}
RepositoryResource other = (RepositoryResource) obj;
if (location == null)
{
return other.location == null;
}
else
{
return this.location.equals(other.location);
}
}
@Override
public <R> R processWith(ResourceProcessor<R> processor) throws ResourceProcessingError
{
return processor.process(this);
}
@Override
public InputStream asStream(ActualEnvironment environment) throws ActualEnvironmentException
{
return location.openContentStream(environment);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.InputStream;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
/**
* A {@link Reference} element that identifies the main or a parameter content
* location. <br>
* The semantics of the resource is given by {@link Reference} protocol.
*
* @author Bogdan Horje
*/
public interface Resource
{
/**
* Returns the String representation of the resource.
*
* @param stringifier
* @return
* @throws ReferenceEncodingException
*/
String stringify(Stringifier stringifier) throws ReferenceEncodingException;
/**
* Processes the Resource with a {@link ResourceProcessor}. This method has
* the role of the accept method in the Visitor pattern, in this case the
* Visitor being the {@link ResourceProcessor} and the Element - the
* Resource.
*
* @param processor
* @return
* @throws ResourceProcessingError
*/
<R> R processWith(ResourceProcessor<R> processor) throws ResourceProcessingError;
InputStream asStream(ActualEnvironment environment) throws ActualEnvironmentException;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Helper class that has one {@link Resource} as a value attribute, value that
* can be retrieved and used in virtualization process.
* <p>
* It also provides the possibility of converting the value attribute into a
* string representation according to {@link Encodings} definition, using
* provided {@link Stringifier} objects.
*/
public class ResourceParameter extends ValueParameter<Resource>
{
public ResourceParameter(Resource resource)
{
super(resource);
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyParameter(this);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public class ResourceProcessingError extends Exception
{
private static final long serialVersionUID = 191847639145802931L;
public ResourceProcessingError()
{
super();
}
public ResourceProcessingError(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace)
{
super(message,
cause,
enableSuppression,
writableStackTrace);
}
public ResourceProcessingError(String message, Throwable cause)
{
super(message,
cause);
}
public ResourceProcessingError(String message)
{
super(message);
}
public ResourceProcessingError(Throwable cause)
{
super(cause);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Generic {@link Resource} visitor. It ensures the processing of different
* types of resources. <br>
*
* @author Bogdan Horje
* @param <R>
*/
public interface ResourceProcessor<R>
{
/**
* Processes a resource of type {@link Resource}.
*
* @param resource a {@link Resource} to be processed.
* @return generic parameter R that implementors are parameterised with.
* @throws ResourceProcessingError
*/
R process(Resource resource) throws ResourceProcessingError;
/**
* Processes a resource of type {@link ClasspathResource}.
*
* @param classpath the {@link ClasspathResource} to be processed.
* @return generic parameter R that implementors are parameterised with.
* @throws ResourceProcessingError
*/
R process(ClasspathResource classpath) throws ResourceProcessingError;
/**
* Processes a resource of type {@link RepositoryResource}.
*
* @param repository a {@link RepositoryResource} to be processed.
* @return generic parameter R that implementors are parameterised with.
* @throws ResourceProcessingError
*/
R process(RepositoryResource repository) throws ResourceProcessingError;
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Creates string-pair hashes based on stored path hashes.<br>
* @see HierarchicalPathHasher
*/
public class StoredPathHasher extends HierarchicalPathHasher
{
private HashStore pathHashStore;
public StoredPathHasher(HashStore pathHashStore)
{
super();
this.pathHashStore = pathHashStore;
}
@Override
protected String hashSubpath(String subpath)
{
return pathHashStore.hash(subpath);
}
@Override
protected String lookupSubpathHash(String hash)
{
return pathHashStore.lookup(hash);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Helper class that has one {@link String} as a value attribute, value that can
* be retrieved and used in virtualization process.
* <p>
* It also provides the possibility of converting the value attribute into a
* string representation according to {@link Encodings} definition, using
* provided {@link Stringifier} objects.
*/
public class StringParameter extends ValueParameter<String>
{
public StringParameter(String value)
{
super(value);
}
@Override
public String stringify(Stringifier stringifier) throws ReferenceEncodingException
{
return stringifier.stringifyParameter(this);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.io.Serializable;
import java.util.List;
/**
* A {@link Reference} abstract tree visitor designed to produce custom string
* representations.
*
* @author Bogdan Horje
*/
public interface Stringifier extends Serializable
{
String stringify(Reference reference) throws ReferenceEncodingException;
String stringify(Resource resource) throws ReferenceEncodingException;
String stringifyResource(Resource resource) throws ReferenceEncodingException;
String stringifyResource(RepositoryResource resource) throws ReferenceEncodingException;
String stringifyResource(ClasspathResource resource) throws ReferenceEncodingException;
String stringify(RepositoryLocation repositoryLocation) throws ReferenceEncodingException;
String stringifyRepositoryLocation(RepositoryLocation repositoryLocation) throws ReferenceEncodingException;
String stringifyRepositoryLocation(RepositoryNodeRef repositoryNodeRef) throws ReferenceEncodingException;
String stringifyRepositoryLocation(RepositoryPath repositoryPath) throws ReferenceEncodingException;
String stringify(List<Parameter> parameters) throws ReferenceEncodingException;
String stringify(Parameter parameter) throws ReferenceEncodingException;
String stringifyParameter(Parameter parameter) throws ReferenceEncodingException;
String stringifyParameter(ResourceParameter resourceParameter) throws ReferenceEncodingException;
String stringifyParameter(StringParameter stringParameter) throws ReferenceEncodingException;
String stringifyParameter(ReferenceParameter referenceParameter) throws ReferenceEncodingException;
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Generic value of type <code>V</code> holder parameter.
*
* @param <V>
*/
public abstract class ValueParameter<V> implements Parameter
{
private V value;
public ValueParameter(V value)
{
super();
this.value = value;
}
public V getValue()
{
return value;
}
@Override
public int hashCode()
{
return this.value != null ? this.value.hashCode() : 0;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj == null)
{
return false;
}
else if (!(getClass().equals(obj.getClass())))
{
return false;
}
if (obj instanceof ValueParameter<?>)
{
ValueParameter<?> other = (ValueParameter<?>) obj;
if (value == null)
{
return other.value == null;
}
else
{
return this.value.equals(other.value);
}
}
else
{
return false;
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.virtual.ref.ReferenceParser.Cursor;
/**
* Custom parser for hash encoded strings of {@link Reference}s having the
* protocol set to {@link VanillaProtocol}.
*/
public class VanillaHashReferenceParser extends VirtualHashReferenceParser
{
public VanillaHashReferenceParser(HashStore classpathHashStore)
{
super(classpathHashStore,
VANILLA_PROTOCOL_CODE);
}
@Override
protected Reference parseVirtualExtension(Cursor c, Resource templateResource, String templatePath,
Resource actualNodeResource)
{
Resource vanillaTemplateResource = parseResource(c);
// TODO :parse vanilla template
List<Parameter> extraParameters = Collections.<Parameter> emptyList();
return ((VanillaProtocol) Protocols.VANILLA.protocol).newReference(Encodings.HASH.encoding,
templateResource,
templatePath,
actualNodeResource,
vanillaTemplateResource,
extraParameters);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
/**
* Custom stringifier for hash encoded strings of {@link Reference}s having the
* protocol set to {@link VanillaProtocol}.
*/
public class VanillaHashStringifier extends VirtualHashStringifier
{
private static final long serialVersionUID = -2087786593789426927L;
public VanillaHashStringifier(HashStore classpathHashStore, Stringifier referenceDispatcher)
{
super(classpathHashStore,
referenceDispatcher);
}
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
final Protocol protocol = reference.getProtocol();
if (!Protocols.VANILLA.protocol.equals(protocol))
{
throw new ReferenceEncodingException("Unsupported protocol " + protocol + "."
+ Protocols.VIRTUAL.protocol.name + " exoected ");
}
String virtualString = stringifyVirtualReference(reference);
ResourceParameter vanillaTemplateParam = (ResourceParameter) reference
.getParameters()
.get(VanillaProtocol.VANILLA_TEMPLATE_PARAM_INDEX);
String vanillaString = stringify(vanillaTemplateParam.getValue());
return VANILLA_PROTOCOL_CODE + "-" + virtualString + "-" + vanillaString;
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* A {@link VirtualProtocol} extension that uses a scripted processor virtual
* template in order to process a so-called vanilla JSON static template
* definition on template execution.<br>
* Vanilla references store have an extra {@link ResourceParameter} for the
* vanilla-JSON template.
*
* @author Bogdan Horje
*/
public class VanillaProtocol extends VirtualProtocol
{
/**
*
*/
private static final long serialVersionUID = -7192024582935232081L;
public static final int VANILLA_TEMPLATE_PARAM_INDEX = 2;
public VanillaProtocol()
{
super("vanilla");
}
@Override
public <R> R dispatch(ProtocolMethod<R> method, Reference reference) throws ProtocolMethodException
{
return method.execute(this,
reference);
}
public Reference newReference(String vanillaProcessorClasspath, String templatePath, NodeRef actualNodeRef,
NodeRef templateRef)
{
return this
.newReference(new ClasspathResource(vanillaProcessorClasspath),
templatePath,
actualNodeRef,
Arrays
.<Parameter> asList(new ResourceParameter(new RepositoryResource(new RepositoryNodeRef(templateRef)))));
}
public Reference newReference(Encoding encoding, Resource virtualTemplateResource, String templatePath,
Resource actualResource, Resource vanillTemplateResource, List<Parameter> extraParameters)
{
List<Parameter> parameters = new ArrayList<>(2);
parameters.add(new ResourceParameter(vanillTemplateResource));
parameters.addAll(extraParameters);
return this.newReference(encoding,
virtualTemplateResource,
templatePath,
actualResource,
parameters);
}
public Resource getVanillaTemplateResource(Reference reference)
{
ResourceParameter vanillaTemplateParamter = (ResourceParameter) reference
.getParameters()
.get(VANILLA_TEMPLATE_PARAM_INDEX);
Resource resource = vanillaTemplateParamter.getValue();
return resource;
}
public Reference newReference(String vanillaProcessorClasspath, String templatePath, NodeRef actualNodeRef,
String templateSysPath) throws ProtocolMethodException
{
Resource templateResource = createSystemPathResource(templateSysPath);
if (templateResource != null)
{
return this.newReference(new ClasspathResource(vanillaProcessorClasspath),
templatePath,
actualNodeRef,
Arrays.<Parameter> asList(new ResourceParameter(templateResource)));
}
else
{
throw new ProtocolMethodException("Invalid template system path : " + templatePath);
}
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.Collections;
import java.util.List;
/*
* Copyright (C) 2005-2015 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/.
*/
import org.alfresco.repo.virtual.ref.ReferenceParser.Cursor;
import org.alfresco.util.Pair;
/**
* Custom parser for hash encoded strings of {@link Reference}s having the
* protocol set to {@link VirtualProtocol}.
*/
public class VirtualHashReferenceParser extends ProtocolHashParser
{
private String protocolCode;
private NumericPathHasher numericPathHasher = new NumericPathHasher();
public VirtualHashReferenceParser(HashStore classpathHashStore)
{
this(classpathHashStore,
VIRTUAL_PROTOCOL_CODE);
}
public VirtualHashReferenceParser(HashStore classpathHashStore, String protocolCode)
{
super(classpathHashStore);
this.protocolCode = protocolCode;
}
@Override
public Reference parse(Cursor cursor) throws ReferenceParseException
{
if (!protocolCode.equals(cursor.currentToken()))
{
throw new ReferenceParseException("Node token \"" + protocolCode + "\" expected instead of \""
+ cursor.currentToken() + "\"");
}
cursor.i++;
Resource templateResource = parseResource(cursor);
Resource actualNodeResource = parseResource(cursor);
String pathToken = cursor.nextToken();
String pathCode = pathToken.substring(0,
1);
String templatePath;
if (HASHED_NUMERIC_PATH_CODE.equals(pathCode))
{
String pathHash = pathToken.substring(1);
templatePath = numericPathHasher.lookup(new Pair<String, String>(pathHash,
null));
}
else if (NUMERIC_ROOT_PATH_CODE.equals(pathCode))
{
templatePath = "/";
}
else if (NUMERIC_PATH_CODE.equals(pathCode))
{
String pathNonHashed = pathToken.substring(1);
templatePath = numericPathHasher.lookup(new Pair<String, String>(null,
pathNonHashed));
}
else if (MIXED_NUMERIC_PATH_CODE.equals(pathCode))
{
String pathHash = pathToken.substring(1);
String pathNonHashed = cursor.nextToken();
templatePath = numericPathHasher.lookup(new Pair<String, String>(pathHash,
pathNonHashed));
}
else
{
throw new ReferenceParseException("Pnvalid path token code " + pathCode);
}
return parseVirtualExtension(cursor,
templateResource,
templatePath,
actualNodeResource);
}
protected Reference parseVirtualExtension(Cursor c, Resource templateResource, String templatePath,
Resource actualNodeResource)
{
List<Parameter> extraParameters = Collections.<Parameter> emptyList();
return ((VirtualProtocol) Protocols.VIRTUAL.protocol).newReference(Encodings.HASH.encoding,
templateResource,
templatePath,
actualNodeResource,
extraParameters);
}
}

View File

@@ -0,0 +1,103 @@
package org.alfresco.repo.virtual.ref;
import java.util.List;
import org.alfresco.util.Pair;
/**
* Custom stringifier for hash encoded strings of {@link Reference}s having the
* protocol set to {@link VirtualProtocol}.
*/
public class VirtualHashStringifier extends ProtocolHashStringifier
{
private static final long serialVersionUID = -252596166306653635L;
private NumericPathHasher numericPathHasher = new NumericPathHasher();
public VirtualHashStringifier(HashStore classpathHashStore, Stringifier referenceDispatcher)
{
super(classpathHashStore,
referenceDispatcher);
}
/**
*
*/
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
final Protocol protocol = reference.getProtocol();
if (!Protocols.VIRTUAL.protocol.equals(protocol))
{
throw new ReferenceEncodingException("Unsupported protocol " + protocol + "."
+ Protocols.VIRTUAL.protocol.name + " exoected ");
}
return VIRTUAL_PROTOCOL_CODE + "-" + stringifyVirtualReference(reference);
}
protected String stringifyVirtualReference(Reference reference)
{
Resource resource = reference.getResource();
String resourceString = resource.stringify(this);
List<Parameter> parameters = reference.getParameters();
ResourceParameter actualNodeParameter = (ResourceParameter) parameters
.get(VirtualProtocol.ACTUAL_NODE_LOCATION_PARAM_INDEX);
Resource actualNodeResource = actualNodeParameter.getValue();
String actualNodeResourceString = actualNodeResource.stringify(this);
StringParameter templatePathParameter;
templatePathParameter = (StringParameter) parameters.get(VirtualProtocol.TEMPLATE_PATH_PARAM_INDEX);
String pathString = templatePathParameter.getValue();
Pair<String, String> pathHash = numericPathHasher.hash(pathString);
StringBuilder stringifiedPath = new StringBuilder();
String hashed = pathHash.getFirst();
String nonHashed = pathHash.getSecond();
if (nonHashed == null)
{
stringifiedPath.append(HASHED_NUMERIC_PATH_CODE);
stringifiedPath.append(hashed);
}
else if (hashed == null)
{
if (nonHashed.isEmpty())
{
stringifiedPath.append(NUMERIC_ROOT_PATH_CODE);
}
else
{
stringifiedPath.append(NUMERIC_PATH_CODE);
stringifiedPath.append(nonHashed);
}
}
else
{
stringifiedPath.append(MIXED_NUMERIC_PATH_CODE);
stringifiedPath.append(hashed);
stringifiedPath.append("-");
stringifiedPath.append(nonHashed);
}
// String delimitedPathString;
// if ("/".equals(pathString.trim()))
// {
// delimitedPathString = "";
// }
// else
// {
// delimitedPathString = pathString.replace('/',
// '-');
// }
String parametersString = actualNodeResourceString +"-"+ stringifiedPath.toString();
return resourceString + "-" + parametersString;
}
}

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.ParameterCheck;
import org.springframework.core.io.ClassPathResource;
/**
* A protocol for encoding virtual artefacts.<br>
* Virtual artefacts are generated using a <b>virtual folder
* template</b>indicated by the main {@link Reference} resource.<br>
* The virtual folder template defines a hierarchical structure of virtual
* nodes. <br>
* The <b>template path</b> (see {@link #getTemplatePath(Reference)}) indicates
* a path in this structure.<br>
* Virtual folders templates can be applied on <b>actual repository nodes</b>
* (see {@link #getActualNodeLocation(Reference)}) which should be passed as
* parameters to the virtual folder template.<br>
* The protocol implementation also handles virtual protocol {@link Reference}
* creation and template path navigation.
*/
public class VirtualProtocol extends Protocol
{
/**
*
*/
private static final long serialVersionUID = -520071882362365522L;
/**
* Actual node {@link Parameter} index.
*/
public static final int ACTUAL_NODE_LOCATION_PARAM_INDEX = 1;
/**
* Template path {@link Parameter} index.
*/
public static final int TEMPLATE_PATH_PARAM_INDEX = 0;
/**
* Repository node path system path token.
*/
public static final Character NODE_TEMPLATE_PATH_TOKEN = 'N';
/**
* Classpath system path token.
*/
public static final Character CLASS_TEMPLATE_PATH_TOKEN = 'C';
public VirtualProtocol()
{
this("virtual");
}
public VirtualProtocol(String name)
{
super(name);
}
@Override
public <R> R dispatch(ProtocolMethod<R> method, Reference reference) throws ProtocolMethodException
{
return method.execute(this,
reference);
}
/**
* @param reference
* @return the inner template path referenced by the given {@link Reference}
* @see VirtualProtocol#TEMPLATE_PATH_PARAM_INDEX
*/
public String getTemplatePath(Reference reference)
{
StringParameter parameter = (StringParameter) getParameter(reference,
TEMPLATE_PATH_PARAM_INDEX);
return parameter.getValue();
}
/**
* @param reference
* @param path
* @return a {@link Reference} copy of the given reference parameter with
* the template path set to the given path parameter value
* @see VirtualProtocol#TEMPLATE_PATH_PARAM_INDEX
*/
public Reference replaceTemplatePath(Reference reference, String path)
{
return replaceParameter(reference,
TEMPLATE_PATH_PARAM_INDEX,
path);
}
/**
* @param reference
* @return the repository location of the actual node that the virtual
* template should be applied on
* @see VirtualProtocol#ACTUAL_NODE_LOCATION_PARAM_INDEX
*/
public RepositoryLocation getActualNodeLocation(Reference reference)
{
ResourceParameter parameter = (ResourceParameter) getParameter(reference,
ACTUAL_NODE_LOCATION_PARAM_INDEX);
RepositoryResource repoResource = (RepositoryResource) parameter.getValue();
return repoResource.getLocation();
}
/**
* @param templateNodeRef {@link NodeRef} of the template content holding
* repository node
* @param templatePath
* @param actualNodeRef
* @return a new virtual protocol {@link Reference} with the given virtual
* protocol reference elements
*/
public Reference newReference(NodeRef templateNodeRef, String templatePath, NodeRef actualNodeRef)
{
ParameterCheck.mandatoryString("templatePath", templatePath);
return this.newReference(new RepositoryResource(new RepositoryNodeRef(templateNodeRef)),
templatePath,
actualNodeRef,
Collections.<Parameter> emptyList());
}
/**
* @param templateResource template content holding resource
* @param templatePath
* @param actualNodeRef
* @return a new virtual protocol {@link Reference} with the given virtual
* protocol reference elements
*/
public Reference newReference(Resource templateResource, String templatePath, NodeRef actualNodeRef,
List<Parameter> extraParameters)
{
ParameterCheck.mandatoryString("templatePath", templatePath);
ArrayList<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new StringParameter(templatePath));
parameters.add(new ResourceParameter(new RepositoryResource(new RepositoryNodeRef(actualNodeRef))));
parameters.addAll(extraParameters);
return new Reference(DEFAULT_ENCODING,
this,
templateResource,
parameters);
}
public Reference newReference(Encoding encoding, Resource templateResource, String templatePath,
Resource actualNodeResource, List<Parameter> extraParameters)
{
ParameterCheck.mandatoryString("templatePath", templatePath);
ArrayList<Parameter> parameters = new ArrayList<Parameter>(3);
parameters.add(new StringParameter(templatePath));
parameters.add(new ResourceParameter(actualNodeResource));
parameters.addAll(extraParameters);
return new Reference(encoding,
this,
templateResource,
parameters);
}
/**
* Creates a resource based on the given template system-path that is used
* in creating a new virtual protocol reference.
*
* @param templateSysPath a template-system-path for the template holding
* content<br>
* Template-system-paths are classpaths paths or repository paths
* prefixed with
* {@link VirtualProtocol#CLASS_TEMPLATE_PATH_TOKEN} or
* {@link VirtualProtocol#NODE_TEMPLATE_PATH_TOKEN} respectively.
* @param templatePath
* @param actualNodeRef
* @return a new virtual protocol {@link Reference} with the given virtual
* protocol reference elements
* @throws ProtocolMethodException
* @deprecated In future system paths will be replaced with actual resources
* or string encoded references
*/
public Reference newReference(String templateSysPath, String templatePath, NodeRef actualNodeRef)
throws ProtocolMethodException
{
Resource templateResource = createSystemPathResource(templateSysPath);
if (templateResource != null)
{
return this.newReference(templateResource,
templatePath,
actualNodeRef,
Collections.<Parameter> emptyList());
}
else
{
throw new ProtocolMethodException("Invalid template system path : " + templatePath);
}
}
/**
* System path resource factory method.
*
* @param templateSysPath a classpath or a repository path prefixed with
* {@link VirtualProtocol#CLASS_TEMPLATE_PATH_TOKEN} or
* {@link VirtualProtocol#NODE_TEMPLATE_PATH_TOKEN} respectively.
* @return a {@link ClassPathResource} or a {@link RepositoryResource} for
* the given system path
* @deprecated In future system paths will be replaced with actual resources
* or string encoded references
*/
protected Resource createSystemPathResource(String templateSysPath)
{
final char systemToken = templateSysPath.charAt(0);
Resource templateResource = null;
if (systemToken == NODE_TEMPLATE_PATH_TOKEN)
{
templateResource = new RepositoryResource(new RepositoryPath(templateSysPath.substring(1)));
}
else if (systemToken == CLASS_TEMPLATE_PATH_TOKEN)
{
templateResource = new ClasspathResource(templateSysPath.substring(1));
}
return templateResource;
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
public interface ZeroEncoding
{
static final String DELIMITER = ":";
static final String REFERENCE_DELIMITER = "*";
static final String STRING_PARAMETER = "s";
/** depending on the resource type */
static final String RESOURCE_PARAMETER[] = { "0", "1", "2" };
static final String REFERENCE_PARAMETER = "r";
public static final int VANILLA_PROTOCOL_CODE = 0;
public static final int VIRTUAL_PROTOCOL_CODE = 3;
public static final int NODE_PROTOCOL_CODE = 6;
public static final int REPOSITORY_RESOURCE_CODE = 0;
public static final int PATH_CODE = 0;
public static final int NODE_CODE = 1;
public static final int CLASSPATH_RESOURCE_CODE = 2;
}

View File

@@ -0,0 +1,297 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
public class ZeroReferenceParser implements ReferenceParser, ZeroEncoding
{
/**
*
*/
private static final long serialVersionUID = 795566334039858555L;
/**
* Parses a String representation of a {@link Reference} and returns the
* corresponding {@link Reference}. Parsing is done with the help of the
* {@link Cursor} class, which keeps track of the String elements that make
* up the {@link Reference} String representation. This method instantiates
* and initiates the cursor and checks the validity of the referenceString
* and relies upon the {@link ZeroReferenceParser#parseReference} for the
* actual parsing.
*
* @param referenceString the String representation of a {@link Reference}.
* @return the newly created {@link Reference}
* @throws ReferenceParseException
*/
@Override
public Reference parse(String referenceString) throws ReferenceParseException
{
String[] referenceTokens = referenceString.split(DELIMITER);
final Cursor cursor = new Cursor(referenceTokens,
0);
if (referenceTokens.length < 2)
{
throw new ReferenceParseException("Invalid reference " + referenceString);
}
return this.parseReference(cursor);
}
/**
* Parses a String representation of a {@link Reference} and returns the
* corresponding {@link Reference}. Parsing is done with the help of the
* {@link Cursor} class, which keeps track of the String elements that make
* up the {@link Reference} String representation.
*
* @param cursor
* @return A {@link Reference} instance.
* @throws ReferenceParseException
*/
private Reference parseReference(Cursor cursor) throws ReferenceParseException
{
try
{
Protocol protocol = null;
int protocolResourceEncoding = Integer.parseInt(cursor.tokens[cursor.i]);
if (protocolResourceEncoding < VIRTUAL_PROTOCOL_CODE)
{
protocol = Protocols.fromName("vanilla");
}
else if (protocolResourceEncoding < NODE_PROTOCOL_CODE)
{
protocol = Protocols.fromName("virtual");
protocolResourceEncoding -= VIRTUAL_PROTOCOL_CODE;
}
else if ((protocolResourceEncoding - NODE_PROTOCOL_CODE) < VIRTUAL_PROTOCOL_CODE)
{
protocol = Protocols.fromName("node");
protocolResourceEncoding -= NODE_PROTOCOL_CODE;
}
if (protocol == null)
{
throw new ReferenceParseException("Unknown protocol " + protocol);
}
cursor.i++;
final Resource resource = parseResource(protocolResourceEncoding,
cursor);
final List<Parameter> parameters = parseParameters(cursor);
Reference reference = new Reference(Encodings.ZERO.encoding,
protocol,
resource,
parameters);
return reference;
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new ReferenceParseException("Invalid reference",
e);
}
}
/**
* Parses a {@link Resource} which is an instance of
* {@link RepositoryResource} or {@link ClasspathResource} if the current
* token is contained in the array {@link ZeroEncoding#RESOURCE_PARAMETER}.
*
* @param resourceEncoding
* @param cursor
* @return an instance of {@link RepositoryResource} or
* {@link ClasspathResource}
* @throws ReferenceParseException
*/
private Resource parseResource(int resourceEncoding, Cursor cursor) throws ReferenceParseException
{
Resource resource = null;
if (resourceEncoding == PATH_CODE)
{
resource = new RepositoryResource(parseRepositoryPath(cursor));
}
else if (resourceEncoding == NODE_CODE)
{
resource = new RepositoryResource(parseRepositoryNode(cursor));
}
else if (resourceEncoding == CLASSPATH_RESOURCE_CODE)
{
resource = parseClasspathResource(cursor);
}
if (resource == null)
{
throw new ReferenceParseException("Unknown resource encoding " + resourceEncoding);
}
return resource;
}
/**
* Parses a {@link Resource} reference which is an instance of
* {@link RepositoryResource} or {@link ClasspathResource}, depending on the
* {@link ZeroEncoding#RESOURCE_PARAMETER}
*
* @param cursor
* @return A {@link Resource} reference.
* @throws ReferenceParseException
*/
private Resource parseResource(Cursor cursor) throws ReferenceParseException
{
return this.parseResource(Byte.parseByte(cursor.tokens[cursor.i - 1]),
cursor);
}
/**
* Creates a list of {@link Parameter}s by parsing the individual parameters
* given by the cursor's tokens. Stops parsing parameters upon encountering
* {@link ZeroEncoding#REFERENCE_DELIMITER}, which signals the end of a
* {@link ReferenceParameter}
*
* @param cursor
* @return a list of {@link Parameter}s
* @throws ReferenceParseException
*/
private List<Parameter> parseParameters(Cursor cursor) throws ReferenceParseException
{
List<Parameter> parameters = new ArrayList<>();
while (cursor.i < cursor.tokens.length)
{
if (Arrays.asList(RESOURCE_PARAMETER).contains(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseResourceParameter(cursor));
}
else if (STRING_PARAMETER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseStringParameter(cursor));
}
else if (REFERENCE_PARAMETER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
parameters.add(parseReferenceParameter(cursor));
}
else if (REFERENCE_DELIMITER.equals(cursor.tokens[cursor.i]))
{
cursor.i++;
break;
}
else
{
throw new ReferenceParseException("Invalid parameter " + cursor.tokens[cursor.i]);
}
}
return parameters;
}
/**
* Creates a {@link Parameter} reference that is an instance of
* {@link StringParameter} by parsing the resource given by the cursor's
* current token.
*
* @param cursor
* @return a {@link Parameter} reference that is instance of
* {@link StringParameter} from the cursor parameter
*/
private Parameter parseStringParameter(Cursor cursor)
{
StringParameter paramenter = new StringParameter(cursor.tokens[cursor.i]);
cursor.i++;
return paramenter;
}
/**
* Creates a {@link Parameter} reference that is an instance of
* {@link ResourceParameter} by parsing the resource given by the cursor's
* current token.
*
* @param cursor
* @return a {@link Parameter} reference that is instance of
* {@link ResourceParameter} from the cursor parameter
* @throws ReferenceParseException
*/
private Parameter parseResourceParameter(Cursor cursor) throws ReferenceParseException
{
Resource resource = parseResource(cursor);
return new ResourceParameter(resource);
}
/**
* Creates a {@link RepositoryPath} reference from current token of the cursor.
*
* @param cursor
* @return A {@link RepositoryPath} reference.
*/
private RepositoryPath parseRepositoryPath(Cursor cursor)
{
String path = cursor.tokens[cursor.i];
cursor.i++;
return new RepositoryPath(path);
}
/**
* Creates a {@link RepositoryNodeRef} reference from the default
* {@link StoreRef}, SpacesStore and from the node id given by the cursor's
* current token.
*
* @param cursor
* @return A {@link RepositoryNodeRef} reference.
*/
private RepositoryNodeRef parseRepositoryNode(Cursor cursor)
{
String id = cursor.tokens[cursor.i];
cursor.i++;
return new RepositoryNodeRef(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
id));
}
/**
* Creates a {@link ClasspathResource} reference from the current token of the
* cursor parameter.
*
* @param cursor
* @return A {@link ClasspathResource} reference.
*/
private ClasspathResource parseClasspathResource(Cursor cursor)
{
String classpath = cursor.tokens[cursor.i];
cursor.i++;
return new ClasspathResource(classpath);
}
/**
* Creates a {@link ReferenceParameter} reference from the cursor's tokens up
* to the * token which signifies the end of the current
* {@link ReferenceParameter}.
*
* @param cursor
* @return A {@link ReferenceParameter} reference.
*/
private ReferenceParameter parseReferenceParameter(Cursor cursor) throws ReferenceParseException
{
Reference reference = parseReference(cursor);
ReferenceParameter parameter = new ReferenceParameter(reference);
return parameter;
}
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (C) 2005-2015 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.virtual.ref;
import java.util.List;
import org.alfresco.service.cmr.repository.NodeRef;
public class ZeroStringifier implements Stringifier, ZeroEncoding
{
private static final long serialVersionUID = 6777894566062875199L;
private int getProtocolEncoding(Protocol protocol) throws ReferenceEncodingException
{
String protocolStr = protocol.toString();
if (protocolStr.equals("vanilla"))
{
return VANILLA_PROTOCOL_CODE;
}
else if (protocolStr.equals("virtual"))
{
return VIRTUAL_PROTOCOL_CODE;
}
else if (protocolStr.equals("node"))
{
return NODE_PROTOCOL_CODE;
}
else
{
throw new ReferenceEncodingException("Invalid protocol: " + protocolStr);
}
}
@Override
public String stringify(Reference reference) throws ReferenceEncodingException
{
String resource = stringify(reference.getResource());
int protocolResourceEncoding = this.getProtocolEncoding(reference.getProtocol());
protocolResourceEncoding += Integer.parseInt(resource.substring(0,
1));
return protocolResourceEncoding + DELIMITER + resource.substring(2) + stringify(reference.getParameters());
}
@Override
public String stringify(Resource resource) throws ReferenceEncodingException
{
return resource.stringify(this);
}
@Override
public String stringifyResource(Resource resource) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid reference " + resource.getClass());
}
@Override
public String stringifyResource(RepositoryResource resource) throws ReferenceEncodingException
{
String resourceLocation = stringify(resource.getLocation());
int locationCode = Integer.parseInt(resourceLocation.substring(0,
1));
locationCode += REPOSITORY_RESOURCE_CODE;
return locationCode + DELIMITER + resourceLocation.substring(2);
}
@Override
public String stringifyResource(ClasspathResource resource)
{
return CLASSPATH_RESOURCE_CODE + DELIMITER + resource.getClasspath();
}
@Override
public String stringify(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
return repositoryLocation.stringify(this);
}
@Override
public String stringifyRepositoryLocation(RepositoryLocation repositoryLocation) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid location: " + repositoryLocation.getClass());
}
@Override
public String stringifyRepositoryLocation(RepositoryNodeRef repositoryNodeRef) throws ReferenceEncodingException
{
NodeRef nodeRef = repositoryNodeRef.getNodeRef();
return NODE_CODE + DELIMITER + nodeRef.getId();
}
@Override
public String stringifyRepositoryLocation(RepositoryPath repositoryPath) throws ReferenceEncodingException
{
return PATH_CODE + DELIMITER + repositoryPath.getPath();
}
@Override
public String stringify(List<Parameter> parameters) throws ReferenceEncodingException
{
StringBuilder parametersBuilder = new StringBuilder();
for (Parameter parameter : parameters)
{
parametersBuilder.append(DELIMITER);
parametersBuilder.append(stringify(parameter));
}
return parametersBuilder.toString();
}
@Override
public String stringify(Parameter parameter) throws ReferenceEncodingException
{
return parameter.stringify(this);
}
@Override
public String stringifyParameter(ResourceParameter resourceParameter) throws ReferenceEncodingException
{
return stringify(resourceParameter.getValue());
}
@Override
public String stringifyParameter(StringParameter stringParameter) throws ReferenceEncodingException
{
return STRING_PARAMETER + DELIMITER + stringParameter.getValue();
}
@Override
public String stringifyParameter(Parameter parameter) throws ReferenceEncodingException
{
throw new ReferenceEncodingException("Invalid parameter: " + parameter.getClass());
}
@Override
public String stringifyParameter(ReferenceParameter parameter) throws ReferenceEncodingException
{
return REFERENCE_PARAMETER + DELIMITER + stringify(parameter.getValue()) + DELIMITER + REFERENCE_DELIMITER;
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2005-2015 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.virtual.store;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
/**
* A template virtualization rule implementation that uses Alfresco-aspect
* defined meta-data for locating templates.<br>
* Stores the aspect {@link QName} to be used in resolving templates by querying
* aspect defined meta data from the virtualized {@link NodeRef}.
*
* @author Bogdan Horje
*/
public abstract class AspectVirtualizationMethod extends TemplateVirtualizationMethod
{
private QName aspectQName;
private String aspectName;
protected NamespacePrefixResolver namespacePrefixResolver;
public AspectVirtualizationMethod()
{
}
public AspectVirtualizationMethod(QName aspectName)
{
super();
this.aspectQName = aspectName;
}
public void init()
{
if (aspectName != null)
{
aspectQName = QName.createQName(aspectName,
namespacePrefixResolver);
}
}
/**
* Determines if a given {@link NodeRef} can be virtualized by this
* virtualization method by checking the presence of the of the configured
* aspect (i.e. {@link #aspectQName}) on the given {@link NodeRef}.
*
* @param env the environment in which the virtualization should take place
* @param nodeRef the {@link NodeRef} that should be virtualized
* @return <code>true</code> if the given {@link NodeRef} can be virtualized
* by this virtualization method (i.e. the configurend aspect is set
* on the given {@link NodeRef}) <code>false</code> otherwise
* @throws VirtualizationException
*/
@Override
public boolean canVirtualize(ActualEnvironment env, NodeRef nodeRef) throws ActualEnvironmentException
{
return env.hasAspect(nodeRef,
getAspectQName());
}
protected QName getAspectQName()
{
return aspectQName;
}
public void setAspectName(String aspectName)
{
this.aspectName = aspectName;
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2005-2015 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.virtual.store;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.ActualEnvironmentException;
import org.alfresco.repo.virtual.VirtualizationException;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
/**
* An {@link AspectVirtualizationMethod} that uses an aspect defined repository
* association to a node that holds the template contents.
*
* @author Bogdan Horje
*/
public class CustomVirtualizationMethod extends AspectVirtualizationMethod
{
/** Template association {@link QName} */
private QName associationQName;
/**
* String representation of the template association. Will be converted into
* a {@link QName} during {@link #init()}
*/
private String associationName;
public CustomVirtualizationMethod()
{
}
/**
* Bean initialization.
*/
@Override
public void init()
{
super.init();
if (associationName != null)
{
associationQName = QName.createQName(associationName,
namespacePrefixResolver);
}
}
public void setAssociationName(String associationName)
{
this.associationName = associationName;
}
@Override
public Reference virtualize(ActualEnvironment env, NodeRef nodeRef) throws VirtualizationException
{
NodeRef templateNode = env.getTargetAssocs(nodeRef,
associationQName);
if (templateNode != null)
{
return newVirtualReference(env,
nodeRef,
templateNode);
}
else
{
// default branch - invalid virtual node
throw new VirtualizationException("Invalid virtualization : missing template association.");
}
}
@Override
public boolean canVirtualize(ActualEnvironment env, NodeRef nodeRef) throws ActualEnvironmentException
{
boolean canVirtualize = super.canVirtualize(env,
nodeRef);
if (canVirtualize)
{
// TODO: optimize - should not need another repository meta data access !!!
NodeRef templateNode = env.getTargetAssocs(nodeRef,
associationQName);
canVirtualize = templateNode != null;
}
return canVirtualize;
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2005-2015 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.virtual.store;
import java.util.HashSet;
import java.util.Set;
import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl;
import org.alfresco.repo.virtual.ref.AbstractProtocolMethod;
import org.alfresco.repo.virtual.ref.NodeProtocol;
import org.alfresco.repo.virtual.ref.ProtocolMethodException;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.VirtualProtocol;
import org.alfresco.repo.virtual.template.FilingParameters;
import org.alfresco.repo.virtual.template.FilingRule;
import org.alfresco.repo.virtual.template.VirtualFolderDefinition;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
public class GetAllSetPermissionsMethod extends AbstractProtocolMethod<Set<AccessPermission>>
{
private VirtualUserPermissions userPermissions;
private String authority;
private VirtualFolderDefinitionResolver resolver;
public GetAllSetPermissionsMethod(VirtualFolderDefinitionResolver resolver, VirtualUserPermissions userPermissions,
String authority)
{
super();
this.userPermissions = userPermissions;
this.authority = authority;
this.resolver = resolver;
}
@Override
public Set<AccessPermission> execute(VirtualProtocol virtualProtocol, Reference reference)
throws ProtocolMethodException
{
Set<String> toAllow = userPermissions.getAllowVirtualNodes();
Set<String> toDeny = userPermissions.getDenyVirtualNodes();
VirtualFolderDefinition definition = resolver.resolveVirtualFolderDefinition(reference);
FilingRule filingRule = definition.getFilingRule();
boolean readonly = filingRule.isNullFilingRule()
|| filingRule.filingNodeRefFor(new FilingParameters(reference)) == null;
if (readonly)
{
Set<String> deniedPermissions = userPermissions.getDenyReadonlyVirtualNodes();
toDeny = new HashSet<>(toDeny);
toDeny.addAll(deniedPermissions);
}
else
{
}
return execute(reference,
toAllow,
toDeny);
}
private Set<AccessPermission> execute(Reference reference, Set<String> toAllow, Set<String> toDeny)
{
Set<AccessPermission> permissions = new HashSet<>();
for (String permission : toAllow)
{
permissions.add(new AccessPermissionImpl(permission,
AccessStatus.ALLOWED,
authority,
0));
}
for (String permission : toDeny)
{
permissions.add(new AccessPermissionImpl(permission,
AccessStatus.DENIED,
authority,
0));
}
return permissions;
}
@Override
public Set<AccessPermission> execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
Set<String> toAllow = userPermissions.getAllowQueryNodes();
Set<String> toDeny = userPermissions.getDenyQueryNodes();
return execute(reference,
toAllow,
toDeny);
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2005-2015 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.virtual.store;
import java.io.Serializable;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.virtual.ActualEnvironment;
import org.alfresco.repo.virtual.VirtualContentModel;
import org.alfresco.repo.virtual.ref.AbstractProtocolMethod;
import org.alfresco.repo.virtual.ref.GetActualNodeRefMethod;
import org.alfresco.repo.virtual.ref.NodeProtocol;
import org.alfresco.repo.virtual.ref.ProtocolMethodException;
import org.alfresco.repo.virtual.ref.Reference;
import org.alfresco.repo.virtual.ref.VirtualProtocol;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.QNamePattern;
public class GetChildAssocsMethod extends AbstractProtocolMethod<List<ChildAssociationRef>>
{
private VirtualStore virtualStore;
private ActualEnvironment environment;
private boolean preload;
private int maxResults;
private QNamePattern qnamePattern;
private QNamePattern typeQNamePattern;
public GetChildAssocsMethod(VirtualStore virtualStore, ActualEnvironment environment, boolean preload,
int maxResults, QNamePattern qnamePattern, QNamePattern typeQNamePattern)
{
super();
this.virtualStore = virtualStore;
this.environment = environment;
this.preload = preload;
this.maxResults = maxResults;
this.qnamePattern = qnamePattern;
this.typeQNamePattern = typeQNamePattern;
}
@Override
public List<ChildAssociationRef> execute(VirtualProtocol virtualProtocol, Reference reference)
throws ProtocolMethodException
{
if (typeQNamePattern.isMatch(ContentModel.ASSOC_CONTAINS))
{
List<ChildAssociationRef> childAssocs = new LinkedList<>();
List<Reference> children = virtualStore.list(reference);
NodeRef nodeRefReference = reference.toNodeRef();
int count = 0;
for (Reference child : children)
{
if (count >= maxResults)
{
break;
}
NodeRef childNodeRef = child.toNodeRef();
Serializable childName = environment.getProperty(childNodeRef,
ContentModel.PROP_NAME);
QName childAssocQName = QName
.createQNameWithValidLocalName(VirtualContentModel.VIRTUAL_CONTENT_MODEL_1_0_URI,
childName.toString());
if (qnamePattern.isMatch(childAssocQName))
{
ChildAssociationRef childAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS,
nodeRefReference,
childAssocQName,
childNodeRef,
true,
-1);
childAssocs.add(childAssoc);
count++;
}
}
return childAssocs;
}
else
{
return Collections.emptyList();
}
}
@Override
public List<ChildAssociationRef> execute(NodeProtocol protocol, Reference reference) throws ProtocolMethodException
{
NodeRef actualNodeRef = reference.execute(new GetActualNodeRefMethod(null));
NodeRef nodeRefReference = reference.toNodeRef();
List<ChildAssociationRef> referenceAssociations = new LinkedList<>();
if (!environment.isSubClass(environment.getType(nodeRefReference), ContentModel.TYPE_FOLDER))
{
List<ChildAssociationRef> actualAssociations = environment.getChildAssocs(actualNodeRef,
typeQNamePattern,
qnamePattern,
maxResults,
preload);
for (ChildAssociationRef actualAssoc : actualAssociations)
{
ChildAssociationRef referenceChildAssocRef = new ChildAssociationRef(actualAssoc.getTypeQName(),
nodeRefReference,
actualAssoc.getQName(),
actualAssoc.getChildRef(),
actualAssoc.isPrimary(),
actualAssoc.getNthSibling());
referenceAssociations.add(referenceChildAssocRef);
}
}
return referenceAssociations;
}
}

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