Moving to root below branch label

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

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the GNU Lesser General Public License as
* published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
/**
* Abstract base class for all web service implementations, provides support for common
* service injection
*
* @author gavinc
*/
public abstract class AbstractWebService
{
protected NodeService nodeService;
protected ContentService contentService;
protected SearchService searchService;
protected NamespaceService namespaceService;
/**
* Sets the instance of the NodeService to be used
*
* @param nodeService The NodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Sets the ContentService instance to use
*
* @param contentSvc The ContentService
*/
public void setContentService(ContentService contentSvc)
{
this.contentService = contentSvc;
}
/**
* Sets the instance of the SearchService to be used
*
* @param searchService The SearchService
*/
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
/**
* Sets the instance of the NamespaceService to be used
*
* @param namespaceService The NamespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
}

View File

@@ -0,0 +1,569 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.repository.UpdateResult;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.CMLAddAspect;
import org.alfresco.repo.webservice.types.CMLAddChild;
import org.alfresco.repo.webservice.types.CMLCopy;
import org.alfresco.repo.webservice.types.CMLCreate;
import org.alfresco.repo.webservice.types.CMLCreateAssociation;
import org.alfresco.repo.webservice.types.CMLDelete;
import org.alfresco.repo.webservice.types.CMLMove;
import org.alfresco.repo.webservice.types.CMLRemoveAspect;
import org.alfresco.repo.webservice.types.CMLRemoveAssociation;
import org.alfresco.repo.webservice.types.CMLRemoveChild;
import org.alfresco.repo.webservice.types.CMLUpdate;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.service.cmr.repository.CopyService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
/**
* @author Roy Wetherall
*/
public class CMLUtil
{
private static final String CREATE = "create";
private static final String ADD_ASPECT = "addAspect";
private static final String REMOVE_ASPECT = "removeAspect";
private static final String UPDATE = "update";
private static final String DELETE = "delete";
private static final String MOVE = "move";
private static final String COPY = "copy";
private static final String ADD_CHILD = "addChild";
private static final String REMOVE_CHILD = "removeChild";
private static final String CREATE_ASSOCIATION = "createAssociation";
private static final String REMOVE_ASSOCIATION = "removeAssociation";
private NodeService nodeService;
private SearchService searchService;
private NamespaceService namespaceService;
private CopyService copyService;
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setCopyService(CopyService copyService)
{
this.copyService = copyService;
}
/**
* Execute a cml update query.
*
* @param cml the cml objects
* @return the update result
*/
public UpdateResult[] executeCML(CML cml)
{
ExecutionContext context = new ExecutionContext();
List<UpdateResult> results = new ArrayList<UpdateResult>();
// Execute creates
CMLCreate[] creates = cml.getCreate();
if (creates != null)
{
for (CMLCreate create : creates)
{
executeCMLCreate(create, context, results);
}
}
// Exceute add aspect
CMLAddAspect[] addAspects = cml.getAddAspect();
if (addAspects != null)
{
for (CMLAddAspect addAspect : addAspects)
{
executeCMLAddAspect(addAspect, context, results);
}
}
// Execeute remove aspect
CMLRemoveAspect[] removeAspects = cml.getRemoveAspect();
if (removeAspects != null)
{
for (CMLRemoveAspect removeAspect : removeAspects)
{
executeCMLRemoveAspect(removeAspect, context, results);
}
}
// Execute update
CMLUpdate[] updates = cml.getUpdate();
if (updates != null)
{
for (CMLUpdate update : updates)
{
executeCMLUpdate(update, context, results);
}
}
// Execute delete
CMLDelete[] deletes = cml.getDelete();
if (deletes != null)
{
for (CMLDelete delete : deletes)
{
executeCMLDelete(delete, context, results);
}
}
// Execute move
CMLMove[] moves = cml.getMove();
if (moves != null)
{
for (CMLMove move : moves)
{
executeCMLMove(move, context, results);
}
}
// Execute copy
CMLCopy[] copies = cml.getCopy();
if (copies != null)
{
for (CMLCopy copy : copies)
{
executeCMLCopy(copy, context, results);
}
}
// Execute addChild
CMLAddChild[] addChildren = cml.getAddChild();
if (addChildren != null)
{
for (CMLAddChild addChild : addChildren)
{
executeCMLAddChild(addChild, context, results);
}
}
// Execute removeChild
CMLRemoveChild[] removeChildren = cml.getRemoveChild();
if (removeChildren != null)
{
for (CMLRemoveChild removeChild : removeChildren)
{
executeCMLRemoveChild(removeChild, context, results);
}
}
// Execute createAssociation
CMLCreateAssociation[] createAssocs = cml.getCreateAssociation();
if (createAssocs != null)
{
for (CMLCreateAssociation createAssoc : createAssocs)
{
executeCMLCreateAssociation(createAssoc, context, results);
}
}
// Execute removeAssociation
CMLRemoveAssociation[] removeAssocs = cml.getRemoveAssociation();
if (removeAssocs != null)
{
for (CMLRemoveAssociation removeAssoc : removeAssocs)
{
executeCMLRemoveAssociation(removeAssoc, context, results);
}
}
return results.toArray(new UpdateResult[results.size()]);
}
/**
*
* @param create
* @param result
*/
private void executeCMLCreate(CMLCreate create, ExecutionContext context, List<UpdateResult> results)
{
// Get the detail of the parent
ParentReference parentReference = create.getParent();
NodeRef parentNodeRef = Utils.convertToNodeRef(
parentReference,
this.nodeService,
this.searchService,
this.namespaceService);
QName assocTypeQName = QName.createQName(parentReference.getAssociationType());
QName assocQName = QName.createQName(parentReference.getChildName());
// Get the type of the node to create
QName nodeTypeQName = QName.createQName(create.getType());
// Get the properties
PropertyMap properties = getPropertyMap(create.getProperty());
// Create the new node
NodeRef nodeRef = this.nodeService.createNode(parentNodeRef, assocTypeQName, assocQName, nodeTypeQName, properties).getChildRef();
// Store the node ref in the execution context (if appropraite)
String id = create.getId();
if (id != null && id.length() != 0)
{
context.addId(id, nodeRef);
}
results.add(createResult(CREATE, null, nodeRef));
}
private PropertyMap getPropertyMap(NamedValue[] namedValues)
{
PropertyMap properties = new PropertyMap();
if (namedValues != null)
{
for (NamedValue value : namedValues)
{
QName qname = QName.createQName(value.getName());
properties.put(qname, value.getValue());
}
}
return properties;
}
private UpdateResult createResult(String cmd, NodeRef sourceNodeRef, NodeRef destinationNodeRef)
{
UpdateResult result = new UpdateResult();
result.setStatement(cmd);
if (sourceNodeRef != null)
{
result.setSource(Utils.convertToReference(sourceNodeRef));
}
if (destinationNodeRef != null)
{
result.setDestination(Utils.convertToReference(destinationNodeRef));
}
// Sort out the count ???
return result;
}
/**
*
* @param addAspect
* @param result
*/
private void executeCMLAddAspect(CMLAddAspect addAspect, ExecutionContext context, List<UpdateResult> results)
{
// Get the node refs
List<NodeRef> nodeRefs = getNodeRefList(addAspect.getWhere_id(), addAspect.getWhere(), context);
// Get the aspect name and the properties
QName aspectQName = QName.createQName(addAspect.getAspect());
PropertyMap properties = getPropertyMap(addAspect.getProperty());
for (NodeRef nodeRef : nodeRefs)
{
// Add the aspect
this.nodeService.addAspect(nodeRef, aspectQName, properties);
// Create the result
results.add(createResult(ADD_ASPECT, nodeRef, nodeRef));
}
}
private void executeCMLRemoveAspect(CMLRemoveAspect removeAspect, ExecutionContext context, List<UpdateResult> results)
{
// Get the node refs
List<NodeRef> nodeRefs = getNodeRefList(removeAspect.getWhere_id(), removeAspect.getWhere(), context);
// Get the aspect name
QName aspectQName = QName.createQName(removeAspect.getAspect());
for (NodeRef nodeRef : nodeRefs)
{
// Add the aspect
this.nodeService.removeAspect(nodeRef, aspectQName);
// Create the result
results.add(createResult(REMOVE_ASPECT, nodeRef, nodeRef));
}
}
private List<NodeRef> getNodeRefList(String id, Predicate predicate, ExecutionContext context)
{
List<NodeRef> nodeRefs = new ArrayList<NodeRef>();
if (id != null && id.length() != 0)
{
NodeRef localNodeRef = context.getNodeRef(id);
if (localNodeRef != null)
{
nodeRefs.add(localNodeRef);
}
}
else
{
nodeRefs = Utils.resolvePredicate(predicate, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRefs;
}
private void executeCMLUpdate(CMLUpdate update, ExecutionContext context, List<UpdateResult> results)
{
// Get the nodes and properties
List<NodeRef> nodeRefs = getNodeRefList(update.getWhere_id(), update.getWhere(), context);
PropertyMap props = getPropertyMap(update.getProperty());
for (NodeRef nodeRef : nodeRefs)
{
// Update the property values
Map<QName, Serializable> currentProps = this.nodeService.getProperties(nodeRef);
currentProps.putAll(props);
this.nodeService.setProperties(nodeRef, currentProps);
// Get the result
results.add(createResult(UPDATE, nodeRef, nodeRef));
}
}
private void executeCMLDelete(CMLDelete delete, ExecutionContext context, List<UpdateResult> results)
{
List<NodeRef> nodeRefs = Utils.resolvePredicate(delete.getWhere(), this.nodeService, this.searchService, this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
// Delete the node
this.nodeService.deleteNode(nodeRef);
// Create the result
results.add(createResult(DELETE, nodeRef, null));
}
}
private void executeCMLMove(CMLMove move, ExecutionContext context, List<UpdateResult> results)
{
NodeRef destinationNodeRef = getNodeRef(move.getTo_id(), move.getTo(), context);
if (destinationNodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (move.getTo_id() != null)
{
assocType = QName.createQName(move.getAssociationType());
assocName = QName.createQName(move.getChildName());
}
else
{
assocType = QName.createQName(move.getTo().getAssociationType());
assocName = QName.createQName(move.getTo().getChildName());
}
List<NodeRef> nodesToMove = getNodeRefList(move.getWhere_id(), move.getWhere(), context);
for (NodeRef nodeToMove : nodesToMove)
{
NodeRef newNodeRef = this.nodeService.moveNode(nodeToMove, destinationNodeRef, assocType, assocName).getChildRef();
// Create the result
results.add(createResult(MOVE, nodeToMove, newNodeRef));
}
}
}
private NodeRef getNodeRef(String id, ParentReference parentReference, ExecutionContext context)
{
NodeRef nodeRef = null;
if (id != null && id.length() != 0)
{
nodeRef = context.getNodeRef(id);
}
else
{
nodeRef = Utils.convertToNodeRef(parentReference, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRef;
}
private NodeRef getNodeRef(String id, Reference reference, ExecutionContext context)
{
NodeRef nodeRef = null;
if (id != null && id.length() != 0)
{
nodeRef = context.getNodeRef(id);
}
else
{
nodeRef = Utils.convertToNodeRef(reference, this.nodeService, this.searchService, this.namespaceService);
}
return nodeRef;
}
private void executeCMLCopy(CMLCopy copy, ExecutionContext context, List<UpdateResult> results)
{
NodeRef destinationNodeRef = getNodeRef(copy.getTo_id(), copy.getTo(), context);
if (destinationNodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (copy.getTo_id() != null)
{
assocType = QName.createQName(copy.getAssociationType());
assocName = QName.createQName(copy.getChildName());
}
else
{
assocType = QName.createQName(copy.getTo().getAssociationType());
assocName = QName.createQName(copy.getTo().getChildName());
}
boolean copyChildren = false;
Boolean value = copy.getChildren();
if (value != null)
{
copyChildren = value.booleanValue();
}
List<NodeRef> nodesToCopy = getNodeRefList(copy.getWhere_id(), copy.getWhere(), context);
for (NodeRef nodeToCopy : nodesToCopy)
{
NodeRef newNodeRef = this.copyService.copy(nodeToCopy, destinationNodeRef, assocType, assocName, copyChildren);
// Create the result
results.add(createResult(COPY, nodeToCopy, newNodeRef));
}
}
}
private void executeCMLAddChild(CMLAddChild addChild, ExecutionContext context, List<UpdateResult> results)
{
NodeRef nodeRef = getNodeRef(addChild.getTo_id(), addChild.getTo(), context);
if (nodeRef != null)
{
QName assocType = null;
QName assocName = null;
if (addChild.getTo_id() != null)
{
assocType = QName.createQName(addChild.getAssociationType());
assocName = QName.createQName(addChild.getChildName());
}
else
{
assocType = QName.createQName(addChild.getTo().getAssociationType());
assocName = QName.createQName(addChild.getTo().getChildName());
}
List<NodeRef> whereNodeRefs = getNodeRefList(addChild.getWhere_id(), addChild.getWhere(), context);
for (NodeRef whereNodeRef : whereNodeRefs)
{
this.nodeService.addChild(nodeRef, whereNodeRef, assocType, assocName);
// Create the result
results.add(createResult(ADD_CHILD, nodeRef, whereNodeRef));
}
}
}
private void executeCMLRemoveChild(CMLRemoveChild removeChild, ExecutionContext context, List<UpdateResult> results)
{
NodeRef parentNodeRef = getNodeRef(removeChild.getFrom_id(), removeChild.getFrom(), context);
if (parentNodeRef != null)
{
List<NodeRef> childNodeRefs = getNodeRefList(removeChild.getWhere_id(), removeChild.getWhere(), context);
for (NodeRef childNodeRef : childNodeRefs)
{
this.nodeService.removeChild(parentNodeRef, childNodeRef);
// Create the result
results.add(createResult(REMOVE_CHILD, parentNodeRef, null));
}
}
}
private void executeCMLCreateAssociation(CMLCreateAssociation createAssoc, ExecutionContext context, List<UpdateResult> results)
{
QName assocType = QName.createQName(createAssoc.getAssociation());
if (assocType != null)
{
List<NodeRef> fromNodeRefs = getNodeRefList(createAssoc.getFrom_id(), createAssoc.getFrom(), context);
List<NodeRef> toNodeRefs = getNodeRefList(createAssoc.getTo_id(), createAssoc.getTo(), context);
for (NodeRef fromNodeRef : fromNodeRefs)
{
for (NodeRef toNodeRef : toNodeRefs)
{
this.nodeService.createAssociation(fromNodeRef, toNodeRef, assocType);
// Create the result
results.add(createResult(CREATE_ASSOCIATION, fromNodeRef, toNodeRef));
}
}
}
}
private void executeCMLRemoveAssociation(CMLRemoveAssociation removeAssoc, ExecutionContext context, List<UpdateResult> results)
{
QName assocType = QName.createQName(removeAssoc.getAssociation());
if (assocType != null)
{
List<NodeRef> fromNodeRefs = getNodeRefList(removeAssoc.getFrom_id(), removeAssoc.getFrom(), context);
List<NodeRef> toNodeRefs = getNodeRefList(removeAssoc.getTo_id(), removeAssoc.getTo(), context);
for (NodeRef fromNodeRef : fromNodeRefs)
{
for (NodeRef toNodeRef : toNodeRefs)
{
this.nodeService.removeAssociation(fromNodeRef, toNodeRef, assocType);
// Create the result
results.add(createResult(REMOVE_ASSOCIATION, fromNodeRef, toNodeRef));
}
}
}
}
private class ExecutionContext
{
private Map<String, NodeRef> idMap = new HashMap<String, NodeRef>();
public void addId(String id, NodeRef nodeRef)
{
this.idMap.put(id, nodeRef);
}
public NodeRef getNodeRef(String id)
{
return this.idMap.get(id);
}
}
}

View File

@@ -0,0 +1,448 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.util.List;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.webservice.repository.UpdateResult;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.CMLAddAspect;
import org.alfresco.repo.webservice.types.CMLAddChild;
import org.alfresco.repo.webservice.types.CMLCopy;
import org.alfresco.repo.webservice.types.CMLCreate;
import org.alfresco.repo.webservice.types.CMLCreateAssociation;
import org.alfresco.repo.webservice.types.CMLDelete;
import org.alfresco.repo.webservice.types.CMLMove;
import org.alfresco.repo.webservice.types.CMLRemoveAspect;
import org.alfresco.repo.webservice.types.CMLRemoveAssociation;
import org.alfresco.repo.webservice.types.CMLRemoveChild;
import org.alfresco.repo.webservice.types.CMLUpdate;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.PropertyMap;
/**
* @author Roy Wetherall
*/
public class CMLUtilTest extends BaseSpringTest
{
private static final ContentData CONTENT_DATA_TEXT_UTF8 = new ContentData(null, MimetypeMap.MIMETYPE_TEXT_PLAIN, 0L, "UTF-8");
private static final ContentData CONTENT_DATA_HTML_UTF16 = new ContentData(null, MimetypeMap.MIMETYPE_HTML, 0L, "UTF-16");
private CMLUtil cmlUtil;
private NodeService nodeService;
private StoreRef testStoreRef;
private NodeRef rootNodeRef;
private NodeRef nodeRef;
private NamespaceService namespaceService;
private SearchService searchService;
private NodeRef folderNodeRef;
private AuthenticationComponent authenticationComponent;
@Override
protected String[] getConfigLocations()
{
return new String[]{"classpath:org/alfresco/repo/webservice/cml-test.xml"};
}
@Override
protected void onSetUpInTransaction() throws Exception
{
this.cmlUtil = (CMLUtil)this.applicationContext.getBean("CMLUtil");
this.nodeService = (NodeService)this.applicationContext.getBean("nodeService");
this.searchService = (SearchService)this.applicationContext.getBean("searchService");
this.namespaceService = (NamespaceService)this.applicationContext.getBean("namespaceService");
this.authenticationComponent = (AuthenticationComponent) this.applicationContext.getBean("authenticationComponent");
this.authenticationComponent.setSystemUserAsCurrentUser();
// Create the store and get the root node
this.testStoreRef = this.nodeService.createStore(
StoreRef.PROTOCOL_WORKSPACE, "Test_"
+ System.currentTimeMillis());
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
// Create the node used for tests
PropertyMap contentProps = new PropertyMap();
contentProps.put(ContentModel.PROP_CONTENT, CONTENT_DATA_TEXT_UTF8);
this.nodeRef = this.nodeService.createNode(
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_CONTENT,
contentProps).getChildRef();
this.folderNodeRef = this.nodeService.createNode(
this.rootNodeRef,
ContentModel.ASSOC_CHILDREN,
ContentModel.ASSOC_CHILDREN,
ContentModel.TYPE_FOLDER).getChildRef();
}
@Override
protected void onTearDownInTransaction()
{
authenticationComponent.clearCurrentSecurityContext();
super.onTearDownInTransaction();
}
public void testMoreThanOneStatement()
{
}
public void testCreate()
{
CMLCreate[] creates = new CMLCreate[]{createCMLCreate(ContentModel.TYPE_CONTENT, "id1")};
CML cml = new CML();
cml.setCreate(creates);
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("create", updateResult.getStatement());
assertNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
NodeRef createdNodeRef = Utils.convertToNodeRef(updateResult.getDestination(), this.nodeService, this.searchService, this.namespaceService);
assertNotNull(createdNodeRef);
assertEquals(ContentModel.TYPE_CONTENT, this.nodeService.getType(createdNodeRef));
assertEquals("name", this.nodeService.getProperty(createdNodeRef, ContentModel.PROP_NAME));
//System.out.println(NodeStoreInspector.dumpNodeStore(this.nodeService, this.testStoreRef));
}
public void testAddRemoveAspect()
{
CMLAddAspect addAspect = new CMLAddAspect();
addAspect.setAspect(ContentModel.ASPECT_VERSIONABLE.toString());
addAspect.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setAddAspect(new CMLAddAspect[]{addAspect});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("addAspect", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
assertTrue(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
// TODO should test with properties set as well
CMLRemoveAspect removeAspect = new CMLRemoveAspect();
removeAspect.setAspect(ContentModel.ASPECT_VERSIONABLE.toString());
removeAspect.setWhere(createPredicate(this.nodeRef));
CML cml2 = new CML();
cml2.setRemoveAspect(new CMLRemoveAspect[]{removeAspect});
UpdateResult[] results2 = this.cmlUtil.executeCML(cml2);
assertNotNull(results2);
assertEquals(1, results2.length);
UpdateResult result2 = results2[0];
assertEquals("removeAspect", result2.getStatement());
assertNotNull(result2.getDestination());
assertNotNull(result2.getSource());
assertFalse(this.nodeService.hasAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE));
}
public void testUpdate()
{
CMLUpdate update = new CMLUpdate();
update.setWhere(createPredicate(this.nodeRef));
update.setProperty(new NamedValue[]
{
new NamedValue(ContentModel.PROP_NAME.toString(), "updatedName"),
new NamedValue(ContentModel.PROP_CONTENT.toString(), CONTENT_DATA_HTML_UTF16.toString())
});
CML cml = new CML();
cml.setUpdate(new CMLUpdate[]{update});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("update", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
assertEquals("updatedName", this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_NAME));
assertEquals(CONTENT_DATA_HTML_UTF16, this.nodeService.getProperty(this.nodeRef, ContentModel.PROP_CONTENT));
}
public void testDelete()
{
CMLDelete delete = new CMLDelete();
delete.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setDelete(new CMLDelete[]{delete});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("delete", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNull(updateResult.getDestination());
// Check that the node no longer exists
assertFalse(this.nodeService.exists(this.nodeRef));
}
public void testMove()
{
CMLMove move = new CMLMove();
move.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
move.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setMove(new CMLMove[]{move});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("move", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testCopy()
{
CMLCopy copy = new CMLCopy();
copy.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
copy.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setCopy(new CMLCopy[]{copy});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("copy", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testAddChild()
{
CMLAddChild addChild = new CMLAddChild();
addChild.setTo(createParentReference(this.folderNodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS));
addChild.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setAddChild(new CMLAddChild[]{addChild});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("addChild", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertNotNull(assocs);
assertEquals(1, assocs.size());
ChildAssociationRef assoc = assocs.get(0);
assertEquals(assoc.getChildRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testRemoveChild()
{
// Add the node as a child of the folder
this.nodeService.addChild(this.folderNodeRef, this.nodeRef, ContentModel.ASSOC_CONTAINS, ContentModel.ASSOC_CONTAINS);
CMLRemoveChild removeChild = new CMLRemoveChild();
removeChild.setFrom(Utils.convertToReference(this.folderNodeRef));
removeChild.setWhere(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setRemoveChild(new CMLRemoveChild[]{removeChild});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("removeChild", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNull(updateResult.getDestination());
List<ChildAssociationRef> assocs = this.nodeService.getChildAssocs(this.folderNodeRef);
assertEquals(0, assocs.size());
}
public void testCreateAssociation()
{
CMLCreateAssociation createAssoc = new CMLCreateAssociation();
createAssoc.setAssociation(ContentModel.ASSOC_CONTAINS.toString());
createAssoc.setFrom(createPredicate(this.folderNodeRef));
createAssoc.setTo(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setCreateAssociation(new CMLCreateAssociation[]{createAssoc});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("createAssociation", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<AssociationRef> assocs = this.nodeService.getTargetAssocs(this.folderNodeRef, ContentModel.ASSOC_CONTAINS);
assertNotNull(assocs);
assertEquals(1, assocs.size());
AssociationRef assoc = assocs.get(0);
assertEquals(assoc.getTargetRef(), Utils.convertToNodeRef(
updateResult.getDestination(),
this.nodeService,
this.searchService,
this.namespaceService));
}
public void testRemoveAssociation()
{
this.nodeService.createAssociation(this.folderNodeRef, this.nodeRef, ContentModel.ASSOC_CONTAINS);
CMLRemoveAssociation removeAssociation = new CMLRemoveAssociation();
removeAssociation.setAssociation(ContentModel.ASSOC_CONTAINS.toString());
removeAssociation.setFrom(createPredicate(this.folderNodeRef));
removeAssociation.setTo(createPredicate(this.nodeRef));
CML cml = new CML();
cml.setRemoveAssociation(new CMLRemoveAssociation[]{removeAssociation});
UpdateResult[] result = this.cmlUtil.executeCML(cml);
assertNotNull(result);
assertEquals(1, result.length);
UpdateResult updateResult = result[0];
assertEquals("removeAssociation", updateResult.getStatement());
assertNotNull(updateResult.getSource());
assertNotNull(updateResult.getDestination());
List<AssociationRef> assocs = this.nodeService.getTargetAssocs(this.folderNodeRef, ContentModel.ASSOC_CONTAINS);
assertNotNull(assocs);
assertEquals(0, assocs.size());
}
private ParentReference createParentReference(NodeRef nodeRef, QName assocType, QName assocName)
{
ParentReference parentReference = new ParentReference();
parentReference.setAssociationType(assocType.toString());
parentReference.setChildName(assocName.toString());
parentReference.setStore(Utils.convertToStore(nodeRef.getStoreRef()));
parentReference.setUuid(nodeRef.getId());
return parentReference;
}
private Predicate createPredicate(NodeRef nodeRef)
{
Predicate predicate = new Predicate();
predicate.setStore(Utils.convertToStore(nodeRef.getStoreRef()));
predicate.setNodes(new Reference[]{Utils.convertToReference(nodeRef)});
return predicate;
}
private CMLCreate createCMLCreate(QName type, String id)
{
CMLCreate create = new CMLCreate();
create.setId("id1");
create.setType(ContentModel.TYPE_CONTENT.toString());
ParentReference parentReference = new ParentReference();
parentReference.setAssociationType(ContentModel.ASSOC_CHILDREN.toString());
parentReference.setChildName(ContentModel.ASSOC_CHILDREN.toString());
parentReference.setStore(Utils.convertToStore(this.testStoreRef));
parentReference.setUuid(this.rootNodeRef.getId());
create.setParent(parentReference);
create.setProperty(getContentNamedValues());
return create;
}
private NamedValue[] getContentNamedValues()
{
return new NamedValue[]
{
new NamedValue(ContentModel.PROP_NAME.toString(), "name"),
new NamedValue(ContentModel.PROP_CONTENT.toString(), CONTENT_DATA_TEXT_UTF8.toString())
};
}
}

View File

@@ -0,0 +1,600 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.UserTransaction;
import org.alfresco.repo.webservice.axis.QueryConfigHandler;
import org.alfresco.repo.webservice.types.AssociationDefinition;
import org.alfresco.repo.webservice.types.Cardinality;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.PropertyDefinition;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.QueryLanguageEnum;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.RoleDefinition;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.repo.webservice.types.StoreEnum;
import org.alfresco.repo.webservice.types.Version;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.axis.MessageContext;
import org.apache.axis.transport.http.HTTPConstants;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Helper class used by the web services
*
* @author gavinc
*/
public class Utils
{
public static final String REPOSITORY_SERVICE_NAMESPACE = "http://www.alfresco.org/ws/service/repository/1.0";
private Utils()
{
// don't allow construction
}
/**
* Converts the web service Store type to a StoreRef used by the repository
*
* @param store
* The Store to convert
* @return The converted StoreRef
*/
public static StoreRef convertToStoreRef(Store store)
{
return new StoreRef(store.getScheme().getValue(), store.getAddress());
}
/**
* Converts a store reference ot a Store type
*
* @param ref
* the store reference
* @return the store
*/
public static Store convertToStore(StoreRef ref)
{
return new Store(StoreEnum.fromValue(ref.getProtocol()), ref
.getIdentifier());
}
/**
* Converts the given Reference web service type into a repository NodeRef
*
* @param ref
* The Reference to convert
* @return The NodeRef representation of the Reference
*/
public static NodeRef convertToNodeRef(Reference ref,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
return resolveToNodeRef(ref.getStore(), ref.getUuid(), ref.getPath(),
nodeService, searchService, namespaceService);
}
/**
* Converts the given ParentReference web service type into a repository
* NodeRef
*
* @param parentRef
* The ParentReference to convert
* @return The NodeRef representation of the ParentReference
*/
public static NodeRef convertToNodeRef(ParentReference parentRef,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
// TODO: Also take into account any association information passed in
// the ParentReference
return resolveToNodeRef(parentRef.getStore(), parentRef.getUuid(),
parentRef.getPath(), nodeService, searchService,
namespaceService);
}
/**
* Converts the given repository NodeRef object into a web service Reference
* type
*
* @param node
* The node to create a Reference for
* @return The Reference
*/
public static Reference convertToReference(NodeRef node)
{
Reference ref = new Reference();
Store store = new Store(StoreEnum.fromValue(node.getStoreRef()
.getProtocol()), node.getStoreRef().getIdentifier());
ref.setStore(store);
ref.setUuid(node.getId());
return ref;
}
/**
* Resolves the given parameters to a repository NodeRef
*
* @param store
* The Store to search within
* @param uuid
* The id of the node, or the id of the starting node if a path
* is also present
* @param path
* The path to the required node, if a uuid is given the search
* starts from that node otherwise the search will start from the
* root node
* @param nodeService
* NodeService to use
* @param searchService
* SearchService to use
* @param namespaceService
* NamespaceService to use
* @return A repository NodeRef
*/
public static NodeRef resolveToNodeRef(Store store, String uuid,
String path, NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
if (store == null)
{
throw new IllegalArgumentException(
"A Store must be supplied to resolve to a NodeRef");
}
NodeRef nodeRef = null;
// find out where we are starting from, either the root or the node
// represented by the uuid
NodeRef rootNodeRef = null;
if (uuid == null)
{
rootNodeRef = nodeService.getRootNode(convertToStoreRef(store));
} else
{
rootNodeRef = new NodeRef(convertToStoreRef(store), uuid);
}
// see if we have a path to further define the node being requested
if (path != null)
{
List<NodeRef> nodes = searchService.selectNodes(rootNodeRef, path,
null, namespaceService, false);
// make sure we only have one result
if (nodes.size() != 1)
{
StringBuilder builder = new StringBuilder(
"Failed to resolve to a single NodeRef with parameters (store=");
builder.append(store.getScheme().getValue()).append(":")
.append(store.getAddress());
builder.append(" uuid=").append(uuid);
builder.append(" path=").append(path).append("), found ");
builder.append(nodes.size()).append(" nodes.");
throw new IllegalStateException(builder.toString());
}
nodeRef = nodes.get(0);
} else
{
// if there is no path just use whatever the rootNodeRef currently
// is
nodeRef = rootNodeRef;
}
return nodeRef;
}
/**
* Resolves the given predicate into a list of NodeRefs that can be acted
* upon
*
* @param predicate
* The predicate passed from the client
* @param nodeService
* NodeService to use
* @param searchService
* SearchService to use
* @param namespaceService
* NamespaceService to use
* @return A List of NodeRef objects
*/
public static List<NodeRef> resolvePredicate(Predicate predicate,
NodeService nodeService, SearchService searchService,
NamespaceService namespaceService)
{
List<NodeRef> nodeRefs = null;
if (predicate.getNodes() != null)
{
Reference[] nodes = predicate.getNodes();
nodeRefs = new ArrayList<NodeRef>(nodes.length);
for (int x = 0; x < nodes.length; x++)
{
nodeRefs.add(convertToNodeRef(nodes[x], nodeService,
searchService, namespaceService));
}
}
else if (predicate.getQuery() != null)
{
// make sure a query is present
Query query = predicate.getQuery();
if (query == null)
{
throw new IllegalStateException(
"Either a set of nodes or a query must be supplied in a Predicate.");
}
// make sure a Store has been supplied too
if (predicate.getStore() == null)
{
throw new IllegalStateException(
"A Store has to be supplied to in order to execute a query.");
}
QueryLanguageEnum langEnum = query.getLanguage();
if (langEnum.equals(QueryLanguageEnum.cql)
|| langEnum.equals(QueryLanguageEnum.xpath))
{
throw new IllegalArgumentException("Only '"
+ QueryLanguageEnum.lucene.getValue()
+ "' queries are currently supported!");
}
// execute the query
ResultSet searchResults = null;
try
{
searchResults = searchService.query(Utils
.convertToStoreRef(predicate.getStore()), langEnum
.getValue(), query.getStatement());
// get hold of all the NodeRef's from the results
nodeRefs = searchResults.getNodeRefs();
}
finally
{
if (searchResults != null)
{
searchResults.close();
}
}
}
else if (predicate.getStore() != null)
{
// Since only the store was supplied interpret this to mean the predicate should be resolved to the
// stores root node
Store store = predicate.getStore();
NodeRef rootNode = nodeService.getRootNode(Utils.convertToStoreRef(store));
nodeRefs = new ArrayList<NodeRef>();
nodeRefs.add(rootNode);
}
return nodeRefs;
}
/**
* Returns the current Spring WebApplicationContext object
*
* @param msgContext
* SOAP message context
* @return The Spring WebApplicationContext
*/
public static WebApplicationContext getSpringContext(
MessageContext msgContext)
{
// get hold of the web application context via the message context
HttpServletRequest req = (HttpServletRequest) msgContext
.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
ServletContext servletCtx = req.getSession().getServletContext();
return WebApplicationContextUtils
.getRequiredWebApplicationContext(servletCtx);
}
/**
* Returns a UserTransaction that can be used within a service call
*
* @param msgContext
* SOAP message context
* @return a UserTransaction
*/
public static UserTransaction getUserTransaction(MessageContext msgContext)
{
// get the service regsistry
ServiceRegistry svcReg = (ServiceRegistry) getSpringContext(msgContext)
.getBean(ServiceRegistry.SERVICE_REGISTRY);
TransactionService transactionService = svcReg.getTransactionService();
return transactionService.getUserTransaction();
}
/**
* Returns the value of the <code>fetchSize</code> from the
* QueryConfiguration SOAP header (if present)
*
* @param msgContext
* The SOAP MessageContext
* @return The current batch size or -1 if the header is not present
*/
public static int getBatchSize(MessageContext msgContext)
{
int batchSize = -1;
Integer batchConfigSize = (Integer) MessageContext.getCurrentContext()
.getProperty(QueryConfigHandler.ALF_FETCH_SIZE);
if (batchConfigSize != null)
{
batchSize = batchConfigSize.intValue();
}
return batchSize;
}
/**
* Converts a repository version object into a web service version object.
*
* @param version
* the repository version object
* @return the web service version object
*/
public static Version convertToVersion(
org.alfresco.service.cmr.version.Version version)
{
Version webServiceVersion = new Version();
// Set the basic properties
webServiceVersion.setId(Utils.convertToReference(version
.getFrozenStateNodeRef()));
webServiceVersion.setCreator(version.getCreator());
webServiceVersion.setLabel(version.getVersionLabel());
// Set the created date
Date createdDate = version.getCreatedDate();
Calendar calendar = Calendar.getInstance();
calendar.setTime(createdDate);
webServiceVersion.setCreated(calendar);
// Set the falg to indicate whether the version was mojor or minor
boolean isMajor = false;
VersionType versionType = version.getVersionType();
if (versionType != null
&& versionType.equals(VersionType.MAJOR) == true)
{
isMajor = true;
}
webServiceVersion.setMajor(isMajor);
// Set the commetary values
Map<String, Serializable> versionProps = version.getVersionProperties();
NamedValue[] namedValues = new NamedValue[versionProps.size()];
int iIndex = 0;
for (Map.Entry<String, Serializable> entry : versionProps.entrySet())
{
String value = null;
try
{
value = DefaultTypeConverter.INSTANCE.convert(String.class, entry.getValue());
}
catch (Throwable exception)
{
value = entry.getValue().toString();
}
namedValues[iIndex] = new NamedValue(entry.getKey(), value);
iIndex++;
}
webServiceVersion.setCommentaries(namedValues);
return webServiceVersion;
}
/**
* Creates a ClassDefinition web service type object for the given
* repository ClassDefinition
*
* @param ddClassDef The repository ClassDefinition to generate
* @return The web service ClassDefinition representation
*/
public static ClassDefinition setupClassDefObject(org.alfresco.service.cmr.dictionary.ClassDefinition ddClassDef)
{
ClassDefinition classDef = new ClassDefinition();
classDef.setName(ddClassDef.getName().toString());
classDef.setIsAspect(ddClassDef.isAspect());
if (ddClassDef.getTitle() != null)
{
classDef.setTitle(ddClassDef.getTitle());
}
if (ddClassDef.getDescription() != null)
{
classDef.setDescription(ddClassDef.getDescription());
}
if (ddClassDef.getParentName() != null)
{
classDef.setSuperClass(ddClassDef.getParentName().toString());
}
// represent the properties
Map<QName, org.alfresco.service.cmr.dictionary.PropertyDefinition> props = ddClassDef.getProperties();
if (props != null)
{
PropertyDefinition[] propDefs = new PropertyDefinition[props.size()];
int pos = 0;
for (org.alfresco.service.cmr.dictionary.PropertyDefinition ddPropDef : props.values())
{
PropertyDefinition propDef = new PropertyDefinition();
propDef.setName(ddPropDef.getName().toString());
propDef.setDataType(ddPropDef.getDataType().getName().toString());
propDef.setMandatory(ddPropDef.isMandatory());
propDef.setReadOnly(ddPropDef.isProtected());
if (ddPropDef.getDefaultValue() != null)
{
propDef.setDefaultValue(ddPropDef.getDefaultValue());
}
if (ddPropDef.getTitle() != null)
{
propDef.setTitle(ddPropDef.getTitle());
}
if (ddPropDef.getDescription() != null)
{
propDef.setDescription(ddPropDef.getDescription());
}
// add it to the array
propDefs[pos] = propDef;
pos++;
}
// add properties to the overall ClassDefinition
classDef.setProperties(propDefs);
}
// TODO need to get the child associations as well !!
// represent the associations
Map<QName, org.alfresco.service.cmr.dictionary.AssociationDefinition> assocs = ddClassDef.getAssociations();
if (assocs != null)
{
AssociationDefinition[] assocDefs = new AssociationDefinition[assocs.size()];
int pos = 0;
for (org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef : assocs.values())
{
AssociationDefinition assocDef = new AssociationDefinition();
assocDef.setName(ddAssocDef.getName().toString());
assocDef.setIsChild(ddAssocDef.isChild());
if (ddAssocDef.getTitle() != null)
{
assocDef.setTitle(ddAssocDef.getTitle());
}
if (ddAssocDef.getDescription() != null)
{
assocDef.setDescription(ddAssocDef.getDescription());
}
RoleDefinition sourceRole = new RoleDefinition();
if (ddAssocDef.getSourceRoleName() != null)
{
sourceRole.setName(ddAssocDef.getSourceRoleName().toString());
}
sourceRole.setCardinality(setupSourceCardinalityObject(ddAssocDef));
assocDef.setSourceRole(sourceRole);
RoleDefinition targetRole = new RoleDefinition();
if (ddAssocDef.getTargetRoleName() != null)
{
targetRole.setName(ddAssocDef.getTargetRoleName().toString());
}
targetRole.setCardinality(setupTargetCardinalityObject(ddAssocDef));;
assocDef.setTargetRole(targetRole);
assocDef.setTargetClass(ddAssocDef.getTargetClass().getName().toString());
assocDefs[pos] = assocDef;
pos++;
}
classDef.setAssociations(assocDefs);
}
return classDef;
}
/**
* Creates a web service Cardinality type for the source from the given repository AssociationDefinition
*
* @param ddAssocDef The AssociationDefinition to get the cardinality from
* @return The Cardinality
*/
private static Cardinality setupSourceCardinalityObject(org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef)
{
if (ddAssocDef.isSourceMandatory() == false && ddAssocDef.isSourceMany() == false)
{
// 0..1
return Cardinality.value1;
}
else if (ddAssocDef.isSourceMandatory() && ddAssocDef.isSourceMany() == false)
{
// 1
return Cardinality.value2;
}
else if (ddAssocDef.isSourceMandatory() && ddAssocDef.isSourceMany())
{
// 1..*
return Cardinality.value4;
}
else
{
// *
return Cardinality.value3;
}
}
/**
* Creates a web service Cardinality type for the target from the given repository AssociationDefinition
*
* @param ddAssocDef The AssociationDefinition to get the cardinality from
* @return The Cardinality
*/
private static Cardinality setupTargetCardinalityObject(org.alfresco.service.cmr.dictionary.AssociationDefinition ddAssocDef)
{
if (ddAssocDef.isTargetMandatory() == false && ddAssocDef.isTargetMany() == false)
{
// 0..1
return Cardinality.value1;
}
else if (ddAssocDef.isTargetMandatory() && ddAssocDef.isTargetMany() == false)
{
// 1
return Cardinality.value2;
}
else if (ddAssocDef.isTargetMandatory() && ddAssocDef.isTargetMany())
{
// 1..*
return Cardinality.value4;
}
else
{
// *
return Cardinality.value3;
}
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.authentication;
import java.rmi.RemoteException;
import org.alfresco.example.webservice.TicketHolder;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the AuthenticationService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/authentication-service.wsdl
*
* @author gavinc
*/
public class AuthenticationWebService implements AuthenticationServiceSoapPort
{
private static Log logger = LogFactory.getLog(AuthenticationWebService.class);
private AuthenticationService authenticationService;
/**
* Sets the AuthenticationService instance to use
*
* @param authenticationSvc
* The AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationSvc)
{
this.authenticationService = authenticationSvc;
}
/**
* @see org.alfresco.repo.webservice.authentication.AuthenticationServiceSoapPort#startSession(java.lang.String,
* java.lang.String)
*/
public AuthenticationResult startSession(String username, String password)
throws RemoteException, AuthenticationFault
{
try
{
this.authenticationService.authenticate(username, password.toCharArray());
String ticket = this.authenticationService.getCurrentTicket();
if (logger.isDebugEnabled())
{
logger.debug("Issued ticket '" + ticket + "' for '" + username + "'");
}
return new AuthenticationResult(username, ticket);
}
catch (AuthenticationException ae)
{
throw new AuthenticationFault(100, ae.getMessage());
}
catch (Throwable e)
{
throw new AuthenticationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authentication.AuthenticationServiceSoapPort#endSession()
*/
public void endSession() throws RemoteException, AuthenticationFault
{
try
{
String ticket = TicketHolder.ticket;
if (ticket != null)
{
this.authenticationService.invalidateTicket(ticket);
this.authenticationService.clearCurrentSecurityContext();
if (logger.isDebugEnabled())
{
logger.debug("Session ended for ticket '" + ticket + "'");
}
}
}
catch (Throwable e)
{
throw new AuthenticationFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,804 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.authoring;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.ContentFormat;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.ParentReference;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.VersionHistory;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.version.Version;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the AuthoringService. The WSDL for this service
* can be accessed from
* http://localhost:8080/alfresco/wsdl/authoring-service.wsdl
*
* @author gavinc
*/
public class AuthoringWebService extends AbstractWebService implements
AuthoringServiceSoapPort
{
/**
* Logger
*/
private static Log logger = LogFactory.getLog(AuthoringWebService.class);
/**
* The check in check out service
*/
private CheckOutCheckInService cociService;
/**
* The lock service
*/
private LockService lockService;
/**
* The version service
*/
private VersionService versionService;
/**
* The transaction service
*/
private TransactionService transactionService;
/**
* Sets the CheckInCheckOutService to use
*
* @param cociService
* The CheckInCheckOutService
*/
public void setCheckOutCheckinService(CheckOutCheckInService cociService)
{
this.cociService = cociService;
}
/**
* Sets the LockService to use
*
* @param lockService the lock service
*/
public void setLockService(LockService lockService)
{
this.lockService = lockService;
}
/**
* Set the version service
*
* @param versionService the version service
*/
public void setVersionService(VersionService versionService)
{
this.versionService = versionService;
}
/**
* Set the transaction service
*
* @param transactionService
* the transaction service
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkout(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.ParentReference)
*/
public CheckoutResult checkout(final Predicate items, final ParentReference destination) throws RemoteException,
AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CheckoutResult>()
{
public CheckoutResult doWork()
{
List<NodeRef> nodes = Utils.resolvePredicate(items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
CheckoutResult checkoutResult = new CheckoutResult();
Reference[] originals = new Reference[nodes.size()];
Reference[] workingCopies = new Reference[nodes.size()];
// get a repository NodeRef for the destination (if
// there is one)
NodeRef destinationRef = null;
if (destination != null)
{
destinationRef = Utils.convertToNodeRef(
destination,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
}
for (int x = 0; x < nodes.size(); x++)
{
// get the current node
NodeRef original = nodes.get(x);
// call the appropriate service method depending on
// whether a destination has been provided
NodeRef workingCopy = null;
if (destinationRef != null)
{
workingCopy = AuthoringWebService.this.cociService
.checkout(
original,
destinationRef,
QName.createQName(destination.getAssociationType()),
QName.createQName(destination.getChildName()));
} else
{
workingCopy = AuthoringWebService.this.cociService
.checkout(original);
}
// store the results
originals[x] = Utils.convertToReference(original);
workingCopies[x] = Utils.convertToReference(workingCopy);
}
// setup the result object
checkoutResult.setOriginals(originals);
checkoutResult.setWorkingCopies(workingCopies);
return checkoutResult;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkin(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.NamedValue[], boolean)
*/
public CheckinResult checkin(final Predicate items,
final NamedValue[] comments, final boolean keepCheckedOut)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CheckinResult>()
{
public CheckinResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Map the comments into the expected map
Map<String, Serializable> mapComments = new HashMap<String, Serializable>(comments.length);
for (NamedValue value : comments)
{
mapComments.put(value.getName(), value.getValue());
}
Reference[] checkedIn = new Reference[nodes.size()];
List<Reference> listWorkingCopies = new ArrayList<Reference>(nodes.size());
int iIndex = 0;
// Execute checkin for each node
// TODO should be able to do this as a batch so that all the nodes are versioned together
for (NodeRef node : nodes)
{
// Checkin the node
NodeRef checkedInNode = AuthoringWebService.this.cociService.checkin(node, mapComments, null, keepCheckedOut);
// Add the results to the array
checkedIn[iIndex] = Utils.convertToReference(checkedInNode);
// Only return the working copies if the node is keep checked out otherwise the working copies have been deleted
if (keepCheckedOut == true)
{
listWorkingCopies.add(Utils.convertToReference(node));
}
iIndex++;
}
// Sort out the working copy list
Reference[] workingCopies = listWorkingCopies.toArray(new Reference[listWorkingCopies.size()]);
if (workingCopies == null)
{
workingCopies = new Reference[0];
}
// Create the result object
CheckinResult result = new CheckinResult();
result.setCheckedIn(checkedIn);
result.setWorkingCopies(workingCopies);
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#checkinExternal(org.alfresco.repo.webservice.types.Reference, org.alfresco.repo.webservice.types.NamedValue[], boolean, org.alfresco.repo.webservice.types.ContentFormat, byte[])
*/
public Reference checkinExternal(final Reference node, final NamedValue[] comments, final boolean keepCheckedOut, final ContentFormat format, final byte[] content)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference>()
{
public Reference doWork()
{
// Get the passed nodes
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Write the content to the server
// TODO: Need to get the property QName into this method
ContentWriter contentWriter = AuthoringWebService.this.contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, false);
if (contentWriter == null)
{
throw new RuntimeException("Unable to write external content before checkin.");
}
InputStream is = new ByteArrayInputStream(content);
contentWriter.setEncoding(format.getEncoding());
contentWriter.setMimetype(format.getMimetype());
contentWriter.putContent(is);
String contentUrl = contentWriter.getContentUrl();
// Get the version properties map
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(comments.length);
for (NamedValue namedValue : comments)
{
versionProperties.put(namedValue.getName(), namedValue.getValue());
}
// CheckIn the content
NodeRef origNodeRef = AuthoringWebService.this.cociService.checkin(
nodeRef,
versionProperties,
contentUrl,
keepCheckedOut);
// Return the orig node ref
return Utils.convertToReference(origNodeRef);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#cancelCheckout(org.alfresco.repo.webservice.types.Predicate)
*/
public CancelCheckoutResult cancelCheckout(final Predicate items)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CancelCheckoutResult>()
{
public CancelCheckoutResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Create the arrays to hold results
Reference[] origNodes = new Reference[nodes.size()];
Reference[] workingCopies = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
// Cancel the checkout
NodeRef origNode = AuthoringWebService.this.cociService.cancelCheckout(node);
// Set the value in the arrays
origNodes[iIndex] = Utils.convertToReference(origNode);
workingCopies[iIndex] = Utils.convertToReference(node);
iIndex ++;
}
CancelCheckoutResult result = new CancelCheckoutResult();
result.setOriginals(origNodes);
result.setWorkingCopies(workingCopies);
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#lock(org.alfresco.repo.webservice.types.Predicate,
* boolean, org.alfresco.repo.webservice.authoring.LockTypeEnum)
*/
public Reference[] lock(final Predicate items, final boolean lockChildren, final LockTypeEnum lockType)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference[]>()
{
public Reference[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
Reference[] result = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
LockType convertedLockType = convertToLockType(lockType);
AuthoringWebService.this.lockService.lock(node, convertedLockType, 0, lockChildren);
result[iIndex] = Utils.convertToReference(node);
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* Convert from the web service lock type to the Lock type enum value used by the service interface
*
* @param lockTypeEnum web service lock type value
* @return lock type enum value used by the service interface
*/
private LockType convertToLockType(LockTypeEnum lockTypeEnum)
{
LockType lockType = null;
if (lockTypeEnum.equals(LockTypeEnum.write) == true)
{
lockType = LockType.WRITE_LOCK;
}
else
{
lockType = LockType.READ_ONLY_LOCK;
}
return lockType;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#unlock(org.alfresco.repo.webservice.types.Predicate,
* boolean)
*/
public Reference[] unlock(final Predicate items, final boolean unlockChildren)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Reference[]>()
{
public Reference[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
Reference[] result = new Reference[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
AuthoringWebService.this.lockService.unlock(node, unlockChildren);
result[iIndex] = Utils.convertToReference(node);
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#getLockStatus(org.alfresco.repo.webservice.types.Predicate)
*/
public LockStatus[] getLockStatus(final Predicate items)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<LockStatus[]>()
{
public LockStatus[] doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Gather together the results
LockStatus[] result = new LockStatus[nodes.size()];
int iIndex = 0;
for (NodeRef node : nodes)
{
// Get the lock owner
String lockOwner = (String)AuthoringWebService.this.nodeService.getProperty(node, ContentModel.PROP_LOCK_OWNER);
// Get the lock type
LockTypeEnum lockTypeEnum = convertFromLockType(AuthoringWebService.this.lockService.getLockType(node));
LockStatus lockStatus = new LockStatus();
lockStatus.setLockOwner(lockOwner);
lockStatus.setLockType(lockTypeEnum);
lockStatus.setNode(Utils.convertToReference(node));
result[iIndex] = lockStatus;
iIndex++;
}
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new AuthoringFault(0, e.getMessage());
}
}
private LockTypeEnum convertFromLockType(LockType lockType)
{
LockTypeEnum result = null;
if (lockType != null)
{
switch (lockType)
{
case WRITE_LOCK:
result = LockTypeEnum.write;
break;
case READ_ONLY_LOCK:
result = LockTypeEnum.read;
break;
}
}
return result;
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#createVersion(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.types.NamedValue[], boolean)
*/
public VersionResult createVersion(final Predicate items, final NamedValue[] comments, final boolean versionChildren)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionResult>()
{
public VersionResult doWork()
{
// Get the passed nodes
List<NodeRef> nodes = Utils.resolvePredicate(
items,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
// Map the comments into the expected map
Map<String, Serializable> mapComments = new HashMap<String, Serializable>(comments.length);
for (NamedValue value : comments)
{
mapComments.put(value.getName(), value.getValue());
}
List<Reference> versionedReferences = new ArrayList<Reference>(nodes.size());
List<org.alfresco.repo.webservice.types.Version> webServiceVersions = new ArrayList<org.alfresco.repo.webservice.types.Version>(nodes.size());
// Version each node
for (NodeRef node : nodes)
{
Collection<Version> versions = AuthoringWebService.this.versionService.createVersion(node, mapComments, versionChildren);
for (Version version : versions)
{
versionedReferences.add(Utils.convertToReference(version.getVersionedNodeRef()));
webServiceVersions.add(Utils.convertToVersion(version));
}
}
VersionResult result = new VersionResult();
result.setNodes(versionedReferences.toArray(new Reference[versionedReferences.size()]));
result.setVersions(webServiceVersions.toArray(new org.alfresco.repo.webservice.types.Version[webServiceVersions.size()]));
return result;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#getVersionHistory(org.alfresco.repo.webservice.types.Reference)
*/
public VersionHistory getVersionHistory(final Reference node)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionHistory>()
{
public VersionHistory doWork()
{
org.alfresco.service.cmr.version.VersionHistory versionHistory =
AuthoringWebService.this.versionService.getVersionHistory(
Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService));
VersionHistory webServiceVersionHistory = new VersionHistory();
if (versionHistory != null)
{
Collection<Version> versions = versionHistory.getAllVersions();
org.alfresco.repo.webservice.types.Version[] webServiceVersions = new org.alfresco.repo.webservice.types.Version[versions.size()];
int iIndex = 0;
for (Version version : versions)
{
webServiceVersions[iIndex] = Utils.convertToVersion(version);
iIndex ++;
}
webServiceVersionHistory.setVersions(webServiceVersions);
}
return webServiceVersionHistory;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#revertVersion(org.alfresco.repo.webservice.types.Reference,
* java.lang.String)
*/
@SuppressWarnings("unchecked")
public void revertVersion(final Reference node, final String versionLabel)
throws RemoteException, AuthoringFault
{
try
{
TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork()
{
public Object doWork()
{
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
org.alfresco.service.cmr.version.VersionHistory versionHistory = AuthoringWebService.this.versionService.getVersionHistory(nodeRef);
if (versionHistory != null)
{
Version version = versionHistory.getVersion(versionLabel);
if (version != null)
{
AuthoringWebService.this.versionService.revert(nodeRef, version);
}
else
{
throw new RuntimeException("The node could not be reverted because the version label is invalid.");
}
}
else
{
throw new RuntimeException("A unversioned node cannot be reverted.");
}
return null;
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.authoring.AuthoringServiceSoapPort#deleteAllVersions(org.alfresco.repo.webservice.types.Reference)
*/
public VersionHistory deleteAllVersions(final Reference node)
throws RemoteException, AuthoringFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<VersionHistory>()
{
public VersionHistory doWork()
{
NodeRef nodeRef = Utils.convertToNodeRef(
node,
AuthoringWebService.this.nodeService,
AuthoringWebService.this.searchService,
AuthoringWebService.this.namespaceService);
AuthoringWebService.this.versionService.deleteVersionHistory(nodeRef);
return new VersionHistory();
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new AuthoringFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.QueryConfiguration;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Axis handler to extract the fetchSize parameter from the QueryConfiguration SOAP header.
* The value of fetchSize is then placed in the MessageContext with a property name of
* ALF_FETCH_SIZE
*
* @author gavinc
*/
public class QueryConfigHandler extends BasicHandler
{
public static final String ALF_FETCH_SIZE = "ALF_FETCH_SIZE";
private static final long serialVersionUID = 6467938074555362971L;
private static Log logger = LogFactory.getLog(QueryConfigHandler.class);
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke(MessageContext msgContext) throws AxisFault
{
try
{
// determine the method we are calling
String opName = "Unknown method";
OperationDesc op = msgContext.getOperation();
if (op != null)
{
opName = op.getName();
}
// try and find the appropriate header and extract info from it
SOAPEnvelope env = msgContext.getRequestMessage().getSOAPEnvelope();
SOAPHeaderElement header = env.getHeaderByName(Utils.REPOSITORY_SERVICE_NAMESPACE, "QueryHeader");
if (header != null)
{
if (logger.isDebugEnabled())
logger.debug("Found QueryHeader for call to " + opName);
QueryConfiguration queryCfg = (QueryConfiguration)header.getObjectValue(QueryConfiguration.class);
if (queryCfg != null)
{
int fetchSize = queryCfg.getFetchSize();
if (logger.isDebugEnabled())
logger.debug("Fetch size for query = " + fetchSize);
msgContext.setProperty(ALF_FETCH_SIZE, new Integer(fetchSize));
}
else
{
if (logger.isDebugEnabled())
logger.debug("Failed to find QueryConfiguration within QueryHeader");
}
}
else
{
if (logger.isDebugEnabled())
{
logger.debug("QueryHeader was not found for call to " + opName);
}
}
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
logger.debug("Failed to determine fetch size", e);
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.alfresco.repo.webservice.Utils;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.RPCProvider;
import org.springframework.web.context.WebApplicationContext;
/**
* A custom Axis RPC Provider that retrieves services via Spring
*
* @author gavinc
*/
public class SpringBeanRPCProvider extends RPCProvider
{
private static final long serialVersionUID = 2173234269124176995L;
private static final String OPTION_NAME = "springBean";
private WebApplicationContext webAppCtx;
/**
* Retrieves the class of the bean represented by the given name
*
* @see org.apache.axis.providers.java.JavaProvider#getServiceClass(java.lang.String, org.apache.axis.handlers.soap.SOAPService, org.apache.axis.MessageContext)
*/
@Override
protected Class getServiceClass(String beanName, SOAPService service, MessageContext msgCtx) throws AxisFault
{
Class clazz = null;
Object bean = getBean(msgCtx, beanName);
if (bean != null)
{
clazz = bean.getClass();
}
return clazz;
}
/**
* @see org.apache.axis.providers.java.JavaProvider#getServiceClassNameOptionName()
*/
@Override
protected String getServiceClassNameOptionName()
{
return OPTION_NAME;
}
/**
* Retrieves the bean with the given name from the current spring context
*
* @see org.apache.axis.providers.java.JavaProvider#makeNewServiceObject(org.apache.axis.MessageContext, java.lang.String)
*/
@Override
protected Object makeNewServiceObject(MessageContext msgCtx, String beanName) throws Exception
{
return getBean(msgCtx, beanName);
}
/**
* Retrieves the bean with the given name from the current spring context
*
* @param msgCtx Axis MessageContext
* @param beanName Name of the bean to lookup
* @return The instance of the bean
*/
private Object getBean(MessageContext msgCtx, String beanName) throws AxisFault
{
return getWebAppContext(msgCtx).getBean(beanName);
}
/**
* Retrieves the Spring context from the web application
*
* @param msgCtx Axis MessageContext
* @return The Spring web app context
*/
private WebApplicationContext getWebAppContext(MessageContext msgCtx) throws AxisFault
{
if (this.webAppCtx == null && msgCtx != null)
{
this.webAppCtx = Utils.getSpringContext(msgCtx);
}
if (this.webAppCtx == null)
{
throw new AxisFault("Failed to retrieve the Spring web application context");
}
return this.webAppCtx;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.webservice.authentication.AuthenticationFault;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSPasswordCallback;
/**
* CallbackHandler that verifies the given ticket in the password element of the UsernameToken
* header is still a valid ticket
*
* @author gavinc
*/
public class TicketCallbackHandler implements CallbackHandler
{
private static final Log logger = LogFactory.getLog(TicketCallbackHandler.class);
private AuthenticationService authenticationService;
/**
* Sets the AuthenticationService instance to use
*
* @param authenticationService The AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof WSPasswordCallback)
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String ticket = pc.getPassword();
if (logger.isDebugEnabled())
{
logger.debug("Verifying ticket for: " + pc.getIdentifer());
logger.debug("Ticket: " + ticket);
}
// ensure the ticket is valid
try
{
this.authenticationService.validate(ticket);
}
catch (AuthenticationException ae)
{
if (logger.isDebugEnabled())
logger.debug("Ticket validation failed: " + ae.getMessage());
// NOTE: Throwing AuthenticationFault just gets consumed and the ws-security handler
// reports a missing password; we would need to modify the WSS4J code to let
// the exception bubble up so for now just let the default message get thrown
throw new AuthenticationFault(701, "Authentication failed due to an invalid ticket");
}
if (logger.isDebugEnabled())
logger.debug("Ticket validated successfully");
// if all is well set the password to return as the given ticket
pc.setPassword(pc.getPassword());
}
else
{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* Axis handler that retrieves the TicketCallbackHandler instance from
* a Spring context. The authentication service is injected by Spring
* so that when it gets called by the WSS4J handler it can verify the
* ticket passed to the service.
* The callback handler is then added to the MessageContext under the standard
* WsHandlerConstants.PW_CALLBACK_REF property.
*
* @author gavinc
*/
public class TicketCallbackSpringHandler extends BasicHandler
{
private static final Log logger = LogFactory.getLog(TicketCallbackSpringHandler.class);
private static final String BEAN_NAME = "ticketCallbackHandler";
private static final long serialVersionUID = -135125831180499667L;
/**
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke(MessageContext msgContext) throws AxisFault
{
// get hold of the Spring context and retrieve the AuthenticationService
HttpServletRequest req = (HttpServletRequest)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
ServletContext servletCtx = req.getSession().getServletContext();
WebApplicationContext webAppCtx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletCtx);
TicketCallbackHandler callback = (TicketCallbackHandler)webAppCtx.getBean(BEAN_NAME);
// store the callback in the context where the WS-Security handler can pick it up from
msgContext.setProperty(WSHandlerConstants.PW_CALLBACK_REF, callback);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.axis;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.Handler;
import org.apache.axis.deployment.wsdd.WSDDProvider;
import org.apache.axis.deployment.wsdd.WSDDService;
/**
* Provider class loaded by Axis, used to identify and
* create an instance of our SpringRPC provider which in
* turn loads service endpoints from Spring configured beans
*
* @see org.alfresco.repo.webservice.axis.SpringBeanRPCProvider
* @author gavinc
*/
public class WSDDSpringBeanRPCProvider extends WSDDProvider
{
private static final String PROVIDER_NAME = "SpringRPC";
/**
* @see org.apache.axis.deployment.wsdd.WSDDProvider#newProviderInstance(org.apache.axis.deployment.wsdd.WSDDService, org.apache.axis.EngineConfiguration)
*/
@Override
public Handler newProviderInstance(WSDDService service, EngineConfiguration registry)
throws Exception
{
return new SpringBeanRPCProvider();
}
/**
* @see org.apache.axis.deployment.wsdd.WSDDProvider#getName()
*/
@Override
public String getName()
{
return PROVIDER_NAME;
}
}

View File

@@ -0,0 +1,454 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.classification;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.Category;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.Classification;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the ClassificationService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/classification-service.wsdl
*
* @author gavinc
*/
public class ClassificationWebService extends AbstractWebService implements
ClassificationServiceSoapPort
{
private static Log logger = LogFactory.getLog(ClassificationWebService.class);
/**
* The category service
*/
private CategoryService categoryService;
/**
* The dictionary service
*/
private DictionaryService dictionaryService;
/**
* The transaction service
*/
private TransactionService transactionService;
/**
* Set the category service
*
* @param categoryService the category service
*/
public void setCategoryService(CategoryService categoryService)
{
this.categoryService = categoryService;
}
/**
* Set the transaction service
*
* @param transactionService the transaction service
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Set the dictionary service
*
* @param dictionaryService the dictionary service
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getClassifications()
*/
public Classification[] getClassifications(final Store store) throws RemoteException,
ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Classification[]>()
{
public Classification[] doWork()
{
List<Classification> classifications = new ArrayList<Classification>();
Collection<QName> categoryAspects = ClassificationWebService.this.categoryService.getClassificationAspects();
for (QName aspect : categoryAspects)
{
// Get the title of the cateogry
String title = null;
org.alfresco.service.cmr.dictionary.ClassDefinition aspectDefinition = ClassificationWebService.this.dictionaryService.getClass(aspect);
if (aspectDefinition != null)
{
title = aspectDefinition.getTitle();
}
if (logger.isDebugEnabled())
{
logger.debug("Category aspect found: " + title + " (" + aspect.toString() + ")");
}
Collection<ChildAssociationRef> assocs = ClassificationWebService.this.categoryService.getCategories(
Utils.convertToStoreRef(store),
aspect,
CategoryService.Depth.IMMEDIATE);
for (ChildAssociationRef assoc : assocs)
{
NodeRef categoryNodeRef = assoc.getChildRef();
Classification classification = new Classification();
classification.setClassification(aspect.toString());
classification.setTitle(title);
// TODO set the description
classification.setRootCategory(convertToCategory(categoryNodeRef));
classifications.add(classification);
}
}
return classifications.toArray(new Classification[classifications.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
private Category convertToCategory(NodeRef nodeRef)
{
String title = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
if (logger.isDebugEnabled())
{
logger.debug("Category: " + title + "(" + nodeRef.toString() + ")");
}
Category category = new Category();
category.setId(Utils.convertToReference(nodeRef));
category.setTitle(title);
// TODO need to set the description
return category;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getChildCategories(org.alfresco.repo.webservice.types.Reference)
*/
public Category[] getChildCategories(final Reference parentCategory)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<Category[]>()
{
public Category[] doWork()
{
NodeRef parentNodeRef = Utils.convertToNodeRef(
parentCategory,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
Collection<ChildAssociationRef> assocs = ClassificationWebService.this.categoryService.getChildren(
parentNodeRef,
CategoryService.Mode.SUB_CATEGORIES,
CategoryService.Depth.IMMEDIATE);
List<Category> categories = new ArrayList<Category>(assocs.size());
for (ChildAssociationRef assoc : assocs)
{
NodeRef categoryNodeRef = assoc.getChildRef();
categories.add(convertToCategory(categoryNodeRef));
}
return categories.toArray(new Category[categories.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#getCategories(org.alfresco.repo.webservice.types.Predicate)
*/
public CategoriesResult[] getCategories(final Predicate items)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CategoriesResult[]>()
{
public CategoriesResult[] doWork()
{
List<CategoriesResult> result = new ArrayList<CategoriesResult>();
List<NodeRef> nodeRefs = Utils.resolvePredicate(
items,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
List<AppliedCategory> appliedCategories = new ArrayList<AppliedCategory>();
Set<QName> apsects = ClassificationWebService.this.nodeService.getAspects(nodeRef);
for (QName aspect : apsects)
{
if (ClassificationWebService.this.dictionaryService.isSubClass(aspect, ContentModel.ASPECT_CLASSIFIABLE) == true)
{
QName categoryPropertyName = getPropertyName(aspect);
if (categoryPropertyName != null)
{
// Get the category value
Collection<NodeRef> categoryNodeRefs = DefaultTypeConverter.INSTANCE.getCollection(
NodeRef.class,
ClassificationWebService.this.nodeService.getProperty(nodeRef, categoryPropertyName));
Reference[] categoryReferences = new Reference[categoryNodeRefs.size()];
int iIndex = 0;
for (NodeRef categoryNodeRef : categoryNodeRefs)
{
categoryReferences[iIndex] = Utils.convertToReference(categoryNodeRef);
iIndex ++;
}
// Create the applied category object
AppliedCategory appliedCategory = new AppliedCategory();
appliedCategory.setClassification(aspect.toString());
appliedCategory.setCategories(categoryReferences);
appliedCategories.add(appliedCategory);
}
}
}
// Create the category result object
CategoriesResult categoryResult = new CategoriesResult();
categoryResult.setNode(Utils.convertToReference(nodeRef));
categoryResult.setCategories(appliedCategories.toArray(new AppliedCategory[appliedCategories.size()]));
result.add(categoryResult);
}
return result.toArray(new CategoriesResult[result.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* Get the category property qname for a classifiable apsect
*
* @param aspect the aspect qname
* @return the property qname, null if none found
*/
private QName getPropertyName(QName aspect)
{
QName categoryPropertyName = null;
// Need to get category property
org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition = ClassificationWebService.this.dictionaryService.getClass(aspect);
for (PropertyDefinition propertyDefintion : classDefinition.getProperties().values())
{
if (DataTypeDefinition.CATEGORY.equals(propertyDefintion.getDataType().getName()) == true)
{
// We have found the category property (assume there is only one)
categoryPropertyName = propertyDefintion.getName();
break;
}
}
return categoryPropertyName;
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#setCategories(org.alfresco.repo.webservice.types.Predicate,
* org.alfresco.repo.webservice.classification.AppliedCategory[])
*/
public CategoriesResult[] setCategories(final Predicate items, final AppliedCategory[] categories)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<CategoriesResult[]>()
{
public CategoriesResult[] doWork()
{
List<CategoriesResult> result = new ArrayList<CategoriesResult>();
List<NodeRef> nodeRefs = Utils.resolvePredicate(
items,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService);
for (NodeRef nodeRef : nodeRefs)
{
List<AppliedCategory> appliedCategories = new ArrayList<AppliedCategory>();
for (AppliedCategory category : categories)
{
QName aspect = QName.createQName(category.getClassification());
QName propertyName = getPropertyName(aspect);
if (propertyName != null)
{
// First check that the aspect has been applied to the node
if (ClassificationWebService.this.nodeService.hasAspect(nodeRef, aspect) == false)
{
ClassificationWebService.this.nodeService.addAspect(nodeRef, aspect, null);
}
ArrayList<NodeRef> categoryNodeRefs = new ArrayList<NodeRef>(category.getCategories().length);
for (Reference categoryReference : category.getCategories())
{
categoryNodeRefs.add(Utils.convertToNodeRef(
categoryReference,
ClassificationWebService.this.nodeService,
ClassificationWebService.this.searchService,
ClassificationWebService.this.namespaceService));
}
ClassificationWebService.this.nodeService.setProperty(nodeRef, propertyName, categoryNodeRefs);
// Create the applied category object
AppliedCategory appliedCategory = new AppliedCategory();
appliedCategory.setClassification(category.getClassification());
appliedCategory.setCategories(category.getCategories());
appliedCategories.add(appliedCategory);
}
}
// Create the category result object
CategoriesResult categoryResult = new CategoriesResult();
categoryResult.setNode(Utils.convertToReference(nodeRef));
categoryResult.setCategories(appliedCategories.toArray(new AppliedCategory[appliedCategories.size()]));
result.add(categoryResult);
}
return result.toArray(new CategoriesResult[result.size()]);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.classification.ClassificationServiceSoapPort#describeClassification(org.alfresco.repo.webservice.types.Reference)
*/
public ClassDefinition describeClassification(final String classification)
throws RemoteException, ClassificationFault
{
try
{
return TransactionUtil.executeInUserTransaction(
this.transactionService,
new TransactionUtil.TransactionWork<ClassDefinition>()
{
public ClassDefinition doWork()
{
org.alfresco.service.cmr.dictionary.ClassDefinition classDefinition = ClassificationWebService.this.dictionaryService.getClass(QName.createQName(classification));
return Utils.setupClassDefObject(classDefinition);
}
});
}
catch (Throwable e)
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ClassificationFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<import resource="classpath:alfresco/application-context.xml" />
<import resource="classpath:web-services-application-context.xml" />
</beans>

View File

@@ -0,0 +1,300 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.content;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.rmi.RemoteException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.ContentFormat;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName;
import org.apache.axis.MessageContext;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the ContentService. The WSDL for this service
* can be accessed from http://localhost:8080/alfresco/wsdl/content-service.wsdl
*
* @author gavinc
*/
public class ContentWebService extends AbstractWebService implements
ContentServiceSoapPort
{
private static Log logger = LogFactory.getLog(ContentWebService.class);
private static final String BROWSER_URL = "{0}://{1}{2}/download/direct/{3}/{4}/{5}/{6}";
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#read(org.alfresco.repo.webservice.types.Reference)
*/
public Content[] read(Predicate items, String property)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// resolve the predicates
List<NodeRef> nodes = Utils.resolvePredicate(items, this.nodeService, this.searchService, this.namespaceService);
List<Content> results = new ArrayList<Content>(nodes.size());
for (NodeRef nodeRef : nodes)
{
// Add content to the result
results.add(createContent(nodeRef, property));
}
// commit the transaction
tx.commit();
return results.toArray(new Content[results.size()]);
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
/**
* Create the content object
*
* @param nodeRef the node reference
* @param property the content property
* @return the content object
* @throws UnsupportedEncodingException
*/
private Content createContent(NodeRef nodeRef, String property)
throws UnsupportedEncodingException
{
Content content = null;
// Lets have a look and see if this node has any content on this node
ContentReader contentReader = this.contentService.getReader(nodeRef, QName.createQName(property));
if (contentReader != null)
{
// Work out what the server, port and context path are
HttpServletRequest req = (HttpServletRequest)MessageContext.getCurrentContext().getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
String address = req.getLocalName();
if (req.getLocalPort() != 80)
{
address = address + ":" + req.getLocalPort();
}
// Get the file name
String filename = (String)this.nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
// format the URL that can be used to download the content
String downloadUrl = MessageFormat.format(BROWSER_URL,
new Object[] { req.getScheme(), address,
req.getContextPath(),
nodeRef.getStoreRef().getProtocol(),
nodeRef.getStoreRef().getIdentifier(),
nodeRef.getId(),
URLEncoder.encode(filename, "UTF-8") });
// Create the content object
ContentFormat format = new ContentFormat(contentReader.getMimetype(), contentReader.getEncoding());
content = new Content(Utils.convertToReference(nodeRef), property, contentReader.getSize(), format, downloadUrl);
// Debug
if (logger.isDebugEnabled())
{
logger.debug("Content: " + nodeRef.getId() + " name="
+ filename + " encoding="
+ content.getFormat().getEncoding() + " mimetype="
+ content.getFormat().getMimetype() + " size="
+ content.getLength() + " downloadURL="
+ content.getUrl());
}
}
else
{
// Create an empty content object
content = new Content(Utils.convertToReference(nodeRef), property, 0, null, null);
// Debug
if (logger.isDebugEnabled())
{
logger.debug("No content found: " + nodeRef.getId());
}
}
return content;
}
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#write(org.alfresco.repo.webservice.types.Reference,
* byte[])
*/
public Content write(Reference node, String property, byte[] content, ContentFormat format)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// create a NodeRef from the parent reference
NodeRef nodeRef = Utils.convertToNodeRef(node, this.nodeService,
this.searchService, this.namespaceService);
// Get the content writer
ContentWriter writer = this.contentService.getWriter(nodeRef, QName.createQName(property), true);
// Set the content format details (if they have been specified)
if (format != null)
{
writer.setEncoding(format.getEncoding());
writer.setMimetype(format.getMimetype());
}
// Write the content
writer.putContent(new String(content));
// Debug
if (logger.isDebugEnabled())
{
logger.debug("Updated content for node with id: " + nodeRef.getId());
}
// Commit the transaction
tx.commit();
// Return the content object
return createContent(nodeRef, property);
}
catch (Throwable e)
{
// Rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.content.ContentServiceSoapPort#clear(org.alfresco.repo.webservice.types.Predicate,
* java.lang.String)
*/
public Content[] clear(Predicate items, String property)
throws RemoteException, ContentFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<NodeRef> nodes = Utils.resolvePredicate(items, this.nodeService,this.searchService, this.namespaceService);
Content[] contents = new Content[nodes.size()];
// delete each node in the predicate
for (int x = 0; x < nodes.size(); x++)
{
NodeRef nodeRef = nodes.get(x);
// Clear the content
this.nodeService.setProperty(nodeRef, QName.createQName(property), null);
if (logger.isDebugEnabled())
{
logger.debug("Cleared content node with id: " + nodeRef.getId());
}
contents[x] = createContent(nodeRef, property);
}
// commit the transaction
tx.commit();
return contents;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new ContentFault(0, e.getMessage());
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import org.alfresco.util.GUID;
/**
* Abstract implementation of a QuerySession providing support
* for automatic id generation and provides support for
* paging through query results.
*
* @author gavinc
*/
public abstract class AbstractQuerySession implements QuerySession
{
protected int batchSize;
protected int position = 0;
private String id;
/**
* Common constructor that initialises the session's id and batch size
*
* @param batchSize The batch size this session will use
*/
public AbstractQuerySession(int batchSize)
{
this.id = GUID.generate();
this.batchSize = batchSize;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getId()
*/
public String getId()
{
return this.id;
}
/**
* Calculates the index of the last row to retrieve.
*
* @param totalRowCount The total number of rows in the results
* @return The index of the last row to return
*/
protected int calculateLastRowIndex(int totalRowCount)
{
int lastRowIndex = totalRowCount;
// set the last row index if there are more results available
// than the batch size
if ((this.batchSize != -1) && ((this.position + this.batchSize) < totalRowCount))
{
lastRowIndex = this.position + this.batchSize;
}
return lastRowIndex;
}
/**
* Calculates the value of the next position.
* If the end of the result set is reached the position is set to -1
*
* @param totalRowCount The total number of rows in the results
* @param queryResult The QueryResult object being returned to the client,
* if there are no more results the id is removed from the QueryResult instance
*/
protected void updatePosition(int totalRowCount, QueryResult queryResult)
{
this.position += this.batchSize;
if (this.position >= totalRowCount)
{
// signify that there are no more results
this.position = -1;
queryResult.setQuerySession(null);
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for
* associations
*
* @author Roy Wetherall
*/
public class AssociatedQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = 6488008047324436124L;
private transient static Log logger = LogFactory
.getLog(AssociatedQuerySession.class);
private Reference node;
/**
* Constructs a AssociatedQuerySession
*
* @param batchSize
* The batch size to use for this session
* @param node
* The node to retrieve the associations
*/
public AssociatedQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService,
* org.alfresco.service.cmr.repository.NodeService,
* org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService,
NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService,
searchService, namespaceService);
List<AssociationRef> assocs = nodeService.getTargetAssocs(nodeRef,
RegexQNamePattern.MATCH_ALL);
int totalRows = assocs.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows
+ ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
AssociationRef assoc = assocs.get(x);
NodeRef childNodeRef = assoc.getTargetRef();
ResultSetRowNode rowNode = new ResultSetRowNode(childNodeRef
.getId(), nodeService.getType(childNodeRef).toString(),
null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService
.getProperties(childNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for children
*
* @author gavinc
*/
public class ChildrenQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = -5347036309571057074L;
private transient static Log logger = LogFactory.getLog(ChildrenQuerySession.class);
private Reference node;
/**
* Constructs a ChildrenQuerySession
*
* @param batchSize The batch size to use for this session
* @param node The node to retrieve the parents
*/
public ChildrenQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
List<ChildAssociationRef> kids = nodeService.getChildAssocs(nodeRef);
int totalRows = kids.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ChildAssociationRef assoc = kids.get(x);
NodeRef childNodeRef = assoc.getChildRef();
ResultSetRowNode rowNode = new ResultSetRowNode(childNodeRef.getId(), nodeService.getType(childNodeRef).toString(), null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService.getProperties(childNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.ResultSetRow;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that stores the results from a query for parents
*
* @author gavinc
*/
public class ParentsQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = 2539375863409175463L;
private transient static Log logger = LogFactory.getLog(ParentsQuerySession.class);
private Reference node;
/**
* Constructs a ParentsQuerySession
*
* @param batchSize The batch size to use for this session
* @param node The node to retrieve the parents
*/
public ParentsQuerySession(int batchSize, Reference node)
{
super(batchSize);
this.node = node;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// create the node ref and get the children from the repository
NodeRef nodeRef = Utils.convertToNodeRef(this.node, nodeService, searchService, namespaceService);
List<ChildAssociationRef> parents = nodeService.getParentAssocs(nodeRef);
int totalRows = parents.size();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ChildAssociationRef assoc = parents.get(x);
NodeRef parentNodeRef = assoc.getParentRef();
ResultSetRowNode rowNode = new ResultSetRowNode(parentNodeRef.getId(), nodeService.getType(parentNodeRef).toString(), null);
// create columns for all the properties of the node
// get the data for the row and build up the columns structure
Map<QName, Serializable> props = nodeService.getProperties(parentNodeRef);
NamedValue[] columns = new NamedValue[props.size()];
int col = 0;
for (QName propName : props.keySet())
{
String value = null;
Serializable valueObj = props.get(propName);
if (valueObj != null)
{
value = valueObj.toString();
}
columns[col] = new NamedValue(propName.toString(), value);
col++;
}
ResultSetRow row = new ResultSetRow();
row.setRowIndex(x);
row.setNode(rowNode);
row.setColumns(columns);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" node-id=").append(this.node.getUuid()).append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
/**
* Interface definition for a QuerySession.
*
* @author gavinc
*/
public interface QuerySession extends Serializable
{
/**
* Retrieves the id this query session can be identified as
*
* @return Id of this query session
*/
public String getId();
/**
* Returns a QueryResult object representing the next batch of results.
* QueryResult will contain a maximum of items as determined by the
* <code>fetchSize</code> element of the QueryConfiguration SOAP header.
*
* When the last batch of results is being returned the querySession of
* QueryResult will be null.
*
* @see org.alfresco.repo.webservice.repository.QuerySession#getId()
* @param searchService The SearchService to use for gathering the results
* @param nodeService The NodeService to use for gathering the results
* @param namespaceService The NamespaceService to use
* @return QueryResult containing the next batch of results or null if there
* are no more results
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService,
NamespaceService namespaceService);
}

View File

@@ -0,0 +1,681 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.transaction.UserTransaction;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.webservice.AbstractWebService;
import org.alfresco.repo.webservice.CMLUtil;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.CML;
import org.alfresco.repo.webservice.types.ClassDefinition;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Node;
import org.alfresco.repo.webservice.types.NodeDefinition;
import org.alfresco.repo.webservice.types.Predicate;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.QueryLanguageEnum;
import org.alfresco.repo.webservice.types.Reference;
import org.alfresco.repo.webservice.types.Store;
import org.alfresco.repo.webservice.types.StoreEnum;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName;
import org.apache.axis.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Web service implementation of the RepositoryService. The WSDL for this
* service can be accessed from
* http://localhost:8080/alfresco/wsdl/repository-service.wsdl
*
* @author gavinc
*/
public class RepositoryWebService extends AbstractWebService implements
RepositoryServiceSoapPort
{
private static Log logger = LogFactory.getLog(RepositoryWebService.class);
private DictionaryService dictionaryService;
private CMLUtil cmlUtil;
private SimpleCache<String, QuerySession> querySessionCache;
/**
* Sets the instance of the DictionaryService to be used
*
* @param dictionaryService
* The DictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Sets the CML Util
*
* @param cmlUtil CML util object
*/
public void setCmlUtil(CMLUtil cmlUtil)
{
this.cmlUtil = cmlUtil;
}
/**
* Sets the instance of the SimpleCache to be used
*
* @param querySessionCache
* The SimpleCache
*/
public void setQuerySessionCache(
SimpleCache<String, QuerySession> querySessionCache)
{
this.querySessionCache = querySessionCache;
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#getStores()
*/
public Store[] getStores() throws RemoteException, RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<StoreRef> stores = this.nodeService.getStores();
Store[] returnStores = new Store[stores.size()];
for (int x = 0; x < stores.size(); x++)
{
StoreRef storeRef = stores.get(x);
if (logger.isDebugEnabled() == true)
{
logger.debug("Store protocol :" + storeRef.getProtocol());
}
StoreEnum storeEnum = StoreEnum.fromString(storeRef
.getProtocol());
Store store = new Store(storeEnum, storeRef.getIdentifier());
returnStores[x] = store;
}
// commit the transaction
tx.commit();
return returnStores;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#query(org.alfresco.repo.webservice.types.Store,
* org.alfresco.repo.webservice.types.Query, boolean)
*/
public QueryResult query(Store store, Query query, boolean includeMetaData)
throws RemoteException, RepositoryFault
{
QueryLanguageEnum langEnum = query.getLanguage();
if (langEnum.equals(QueryLanguageEnum.cql)
|| langEnum.equals(QueryLanguageEnum.xpath))
{
throw new RepositoryFault(110, "Only '"
+ QueryLanguageEnum.lucene.getValue()
+ "' queries are currently supported!");
}
UserTransaction tx = null;
MessageContext msgContext = MessageContext.getCurrentContext();
try
{
tx = Utils.getUserTransaction(msgContext);
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ResultSetQuerySession(Utils
.getBatchSize(msgContext), store, query, includeMetaData);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
e.printStackTrace();
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryChildren(org.alfresco.repo.webservice.types.Reference)
*/
public QueryResult queryChildren(Reference node) throws RemoteException,
RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ChildrenQuerySession(Utils
.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryParents(org.alfresco.repo.webservice.types.Reference)
*/
public QueryResult queryParents(Reference node) throws RemoteException,
RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new ParentsQuerySession(Utils
.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#queryAssociated(org.alfresco.repo.webservice.types.Reference,
* org.alfresco.repo.webservice.repository.Association[])
*/
public QueryResult queryAssociated(Reference node, Association[] association)
throws RemoteException, RepositoryFault
{
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// setup a query session and get the first batch of results
QuerySession querySession = new AssociatedQuerySession(Utils.getBatchSize(MessageContext.getCurrentContext()), node);
QueryResult queryResult = querySession
.getNextResultsBatch(this.searchService, this.nodeService,
this.namespaceService);
// add the session to the cache if there are more results to come
if (queryResult.getQuerySession() != null)
{
// this.querySessionCache.putQuerySession(querySession);
this.querySessionCache.put(queryResult.getQuerySession(),
querySession);
}
// commit the transaction
tx.commit();
return queryResult;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#fetchMore(java.lang.String)
*/
public QueryResult fetchMore(String querySession) throws RemoteException,
RepositoryFault
{
QueryResult queryResult = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// try and get the QuerySession with the given id from the cache
QuerySession session = this.querySessionCache.get(querySession);
if (session == null)
{
if (logger.isDebugEnabled())
logger.debug("Invalid querySession id requested: "
+ querySession);
throw new RepositoryFault(4, "querySession with id '"
+ querySession + "' is invalid");
}
// get the next batch of results
queryResult = session.getNextResultsBatch(this.searchService,
this.nodeService, this.namespaceService);
// remove the QuerySession from the cache if there are no more
// results to come
if (queryResult.getQuerySession() == null)
{
this.querySessionCache.remove(querySession);
}
// commit the transaction
tx.commit();
return queryResult;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (e instanceof RepositoryFault)
{
throw (RepositoryFault) e;
} else
{
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#update(org.alfresco.repo.webservice.types.CML)
*/
public UpdateResult[] update(CML statements) throws RemoteException,
RepositoryFault
{
UpdateResult[] result = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
result = this.cmlUtil.executeCML(statements);
// commit the transaction
tx.commit();
return result;
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#describe(org.alfresco.repo.webservice.types.Predicate)
*/
public NodeDefinition[] describe(Predicate items) throws RemoteException,
RepositoryFault
{
NodeDefinition[] nodeDefs = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
List<NodeRef> nodes = Utils
.resolvePredicate(items, this.nodeService,
this.searchService, this.namespaceService);
nodeDefs = new NodeDefinition[nodes.size()];
for (int x = 0; x < nodes.size(); x++)
{
nodeDefs[x] = setupNodeDefObject(nodes.get(x));
}
// commit the transaction
tx.commit();
return nodeDefs;
} catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
} catch (Exception ex)
{
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
}
/**
* Creates a NodeDefinition web service type object for the given
* repository NodeRef instance
*
* @param nodeRef The NodeRef to generate the NodeDefinition for
* @return The NodeDefinition representation of nodeRef
*/
private NodeDefinition setupNodeDefObject(NodeRef nodeRef)
{
if (logger.isDebugEnabled())
logger.debug("Building NodeDefinition for node: " + nodeRef);
TypeDefinition ddTypeDef = this.dictionaryService
.getType(this.nodeService.getType(nodeRef));
// create the web service ClassDefinition type from the data dictionary TypeDefinition
ClassDefinition typeDef = Utils.setupClassDefObject(ddTypeDef);
// create the web service ClassDefinition types to represent the aspects
ClassDefinition[] aspectDefs = null;
List<AspectDefinition> aspects = ddTypeDef.getDefaultAspects();
if (aspects != null)
{
aspectDefs = new ClassDefinition[aspects.size()];
int pos = 0;
for (AspectDefinition ddAspectDef : aspects)
{
aspectDefs[pos] = Utils.setupClassDefObject(ddAspectDef);
pos++;
}
}
return new NodeDefinition(typeDef, aspectDefs);
}
/**
* Gets the nodes associatiated with the predicate provided. Usefull when the store and ids of the required
* nodes are known.
*
* @see org.alfresco.repo.webservice.repository.RepositoryServiceSoapPort#get(org.alfresco.repo.webservice.types.Predicate)
*/
public Node[] get(Predicate where) throws RemoteException, RepositoryFault
{
Node[] nodes = null;
UserTransaction tx = null;
try
{
tx = Utils.getUserTransaction(MessageContext.getCurrentContext());
tx.begin();
// Resolve the predicate to a list of node references
List<NodeRef> nodeRefs = Utils.resolvePredicate(where, this.nodeService, this.searchService, this.namespaceService);
nodes = new Node[nodeRefs.size()];
int index = 0;
for (NodeRef nodeRef : nodeRefs)
{
// Get the nodes reference
Reference reference = Utils.convertToReference(nodeRef);
// Get the nodes type
String type = this.nodeService.getType(nodeRef).toString();
// Get the nodes aspects
Set<QName> aspectQNames = this.nodeService.getAspects(nodeRef);
String[] aspects = new String[aspectQNames.size()];
int aspectIndex = 0;
for (QName aspectQName : aspectQNames)
{
aspects[aspectIndex] = aspectQName.toString();
aspectIndex++;
}
// Get the nodes properties
Map<QName, Serializable> propertyMap = this.nodeService.getProperties(nodeRef);
NamedValue[] properties = new NamedValue[propertyMap.size()];
int propertyIndex = 0;
for (Map.Entry<QName, Serializable> entry : propertyMap.entrySet())
{
String value = null;
try
{
value = DefaultTypeConverter.INSTANCE.convert(String.class, entry.getValue());
}
catch (Throwable exception)
{
value = entry.getValue().toString();
}
properties[propertyIndex] = new NamedValue(entry.getKey().toString(), value);
propertyIndex++;
}
// Create the node and add to the array
Node node = new Node(reference, type, aspects, properties);
nodes[index] = node;
index++;
}
// commit the transaction
tx.commit();
}
catch (Throwable e)
{
// rollback the transaction
try
{
if (tx != null)
{
tx.rollback();
}
}
catch (Exception ex)
{
// Ignore
}
if (logger.isDebugEnabled())
{
logger.error("Unexpected error occurred", e);
}
throw new RepositoryFault(0, e.getMessage());
}
return nodes;
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package org.alfresco.repo.webservice.repository;
import java.io.Serializable;
import java.util.Map;
import org.alfresco.repo.webservice.Utils;
import org.alfresco.repo.webservice.types.NamedValue;
import org.alfresco.repo.webservice.types.Query;
import org.alfresco.repo.webservice.types.ResultSetRowNode;
import org.alfresco.repo.webservice.types.Store;
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.ResultSetRow;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Implementation of a QuerySession that retrieves results from a repository ResultSet
*
* @author gavinc
*/
public class ResultSetQuerySession extends AbstractQuerySession
{
private static final long serialVersionUID = -9154514445963635138L;
private transient static Log logger = LogFactory.getLog(ResultSetQuerySession.class);
private Store store;
private Query query;
private boolean includeMetaData;
/**
* Constructs a ResultSetQuerySession
*
* @param batchSize The batch size to use for this session
* @param store The repository store to query against
* @param query The query to execute
* @param includeMetaData Whether to include metadata in the query results
*/
public ResultSetQuerySession(int batchSize, Store store, Query query, boolean includeMetaData)
{
super(batchSize);
this.store = store;
this.query = query;
this.includeMetaData = includeMetaData;
}
/**
* @see org.alfresco.repo.webservice.repository.QuerySession#getNextResultsBatch(org.alfresco.service.cmr.search.SearchService, org.alfresco.service.cmr.repository.NodeService, org.alfresco.service.namespace.NamespaceService)
*/
public QueryResult getNextResultsBatch(SearchService searchService, NodeService nodeService, NamespaceService namespaceService)
{
QueryResult queryResult = null;
if (this.position != -1)
{
if (logger.isDebugEnabled())
logger.debug("Before getNextResultsBatch: " + toString());
// handle the special search string of * meaning, get everything
String statement = query.getStatement();
if (statement.equals("*"))
{
statement = "ISNODE:*";
}
ResultSet searchResults = null;
try
{
searchResults = searchService.query(Utils.convertToStoreRef(this.store),
this.query.getLanguage().getValue(), statement);
int totalRows = searchResults.length();
int lastRow = calculateLastRowIndex(totalRows);
int currentBatchSize = lastRow - this.position;
if (logger.isDebugEnabled())
logger.debug("Total rows = " + totalRows + ", current batch size = " + currentBatchSize);
org.alfresco.repo.webservice.types.ResultSet batchResults = new org.alfresco.repo.webservice.types.ResultSet();
org.alfresco.repo.webservice.types.ResultSetRow[] rows = new org.alfresco.repo.webservice.types.ResultSetRow[currentBatchSize];
int arrPos = 0;
for (int x = this.position; x < lastRow; x++)
{
ResultSetRow origRow = searchResults.getRow(x);
NodeRef nodeRef = origRow.getNodeRef();
ResultSetRowNode rowNode = new ResultSetRowNode(nodeRef.getId(), nodeService.getType(nodeRef).toString(), null);
// get the data for the row and build up the columns structure
Map<Path, Serializable> values = origRow.getValues();
NamedValue[] columns = new NamedValue[values.size()];
int col = 0;
for (Path path : values.keySet())
{
String value = null;
Serializable valueObj = values.get(path);
if (valueObj != null)
{
value = valueObj.toString();
}
// Get the attribute QName from the result path
String attributeName = path.last().toString();
if (attributeName.startsWith("@") == true)
{
attributeName = attributeName.substring(1);
}
columns[col] = new NamedValue(attributeName, value);
col++;
}
org.alfresco.repo.webservice.types.ResultSetRow row = new org.alfresco.repo.webservice.types.ResultSetRow();
row.setColumns(columns);
row.setScore(origRow.getScore());
row.setRowIndex(x);
row.setNode(rowNode);
// add the row to the overall results
rows[arrPos] = row;
arrPos++;
}
// TODO: build up the meta data data structure if we've been asked to
// add the rows to the result set and set the total row count
batchResults.setRows(rows);
batchResults.setTotalRowCount(totalRows);
queryResult = new QueryResult(getId(), batchResults);
// move the position on
updatePosition(totalRows, queryResult);
if (logger.isDebugEnabled())
logger.debug("After getNextResultsBatch: " + toString());
}
finally
{
if (searchResults != null)
{
searchResults.close();
}
}
}
return queryResult;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(super.toString());
builder.append(" (id=").append(getId());
builder.append(" batchSize=").append(this.batchSize);
builder.append(" position=").append(this.position);
builder.append(" store=").append(this.store.getScheme().getValue()).append(":").append(this.store.getAddress());
builder.append(" language=").append(this.query.getLanguage().getValue());
builder.append(" statement=").append(this.query.getStatement());
builder.append(")");
return builder.toString();
}
}