diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index cfa9c774f4..821560d3a5 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -482,7 +482,23 @@ false - + + + + + + + + + + + + + + false + + + diff --git a/config/alfresco/clt-context.xml b/config/alfresco/clt-context.xml index 72b9b44a0e..ce645f1e29 100644 --- a/config/alfresco/clt-context.xml +++ b/config/alfresco/clt-context.xml @@ -2,6 +2,9 @@ + + + @@ -11,7 +14,7 @@ - rmi://localhost:1313/avm + rmi://localhost:50500/avm org.alfresco.service.cmr.remote.AVMRemoteTransport @@ -29,7 +32,7 @@ - rmi://localhost:1313/avmsync + rmi://localhost:50500/avmsync org.alfresco.service.cmr.remote.AVMSyncServiceTransport @@ -41,7 +44,7 @@ - rmi://localhost:1313/authentication + rmi://localhost:50500/authentication org.alfresco.service.cmr.security.AuthenticationService @@ -53,7 +56,7 @@ - rmi://localhost:1313/repo + rmi://localhost:50500/repo org.alfresco.service.cmr.remote.RepoRemoteTransport diff --git a/config/alfresco/messages/action-config.properties b/config/alfresco/messages/action-config.properties index d70c54bcc6..6eebeed7e2 100644 --- a/config/alfresco/messages/action-config.properties +++ b/config/alfresco/messages/action-config.properties @@ -115,6 +115,16 @@ avm-undo-list.title=Make a list of Nodes in a store transparent to staging. avm-undo-list.description=This acts as a mistake eraser for a user's sandbox. avm-undo-list.node-list.display-label=The string encoded list of nodes to revert. +avm-deploy-snapshot.title=Deploy a snapshot to a remote server. +avm-deploy-snapshot.description=This deploys a website snapshot to a remote server. +avm-deploy-snapshot.website.display-label=NodeRef of the website the deploy is occurring from. +avm-deploy-snapshot.target-server.display-label=The name or IP address of the remote server to deploy to. +avm-deploy-snapshot.default-rmi-port.display-label=The default RMI port to connect to if it is not supplied in target-server parameter. +avm-deploy-snapshot.remote-username.display-label=The username to connect as. +avm-deploy-snapshot.remote-password.display-label=The password for the remote-username. +avm-deploy-snapshot.deploy-callback.display-label=The DeploymentCallback listener object. +avm-deploy-snapshot.delay.display-label=An optional delay to apply to the start of a deployment. + start-avm-workflow.title=Start a WCM Workflow start-avm-workflow.description=Starts a workflow expecting an AVM workflow package start-avm-workflow.store-name.display-label=Store name for start task diff --git a/config/alfresco/model/wcmAppModel.xml b/config/alfresco/model/wcmAppModel.xml index 78d47f370a..bce82da2df 100644 --- a/config/alfresco/model/wcmAppModel.xml +++ b/config/alfresco/model/wcmAppModel.xml @@ -32,6 +32,20 @@ Default Webapp d:text + + Deploy To + d:text + true + + + Servers Selected For Deployment + d:text + true + + + Snapshot Version Selected For Deployment + d:int + @@ -67,6 +81,17 @@ true + + + false + false + + + wca:deploymentreport + false + true + + @@ -181,6 +206,42 @@ XForms Capture Form Folder cm:folder + + + Website Deployment Report + cm:content + + + Server Deployed To + d:text + true + + + Snapshot Version Deployed + d:int + true + + + Time Deploy Started + d:datetime + true + + + Time Deploy Finished + d:datetime + true + + + Deployment Successful + d:boolean + false + + + Failure Reason + d:text + + + diff --git a/config/alfresco/public-services-context.xml b/config/alfresco/public-services-context.xml index e6f7effdfb..7eaab5de4d 100644 --- a/config/alfresco/public-services-context.xml +++ b/config/alfresco/public-services-context.xml @@ -767,6 +767,7 @@ getAspects hasAspect getAPath + getGuid @@ -813,6 +814,7 @@ renameStore getSystemStore revert + setGuid @@ -888,22 +890,41 @@ - + + + + - - + + + + + - + - - + deployDifference + deployDifferenceFS + + + + + + + + org.alfresco.service.cmr.avm.deploy.DeploymentService + + + + deploymentService + + + + deploymentServiceReadTxnAdvisor - --> @@ -1079,4 +1100,4 @@ - + \ No newline at end of file diff --git a/config/alfresco/remote-avm-test-context.xml b/config/alfresco/remote-avm-test-context.xml index 4eb26fc473..432f833013 100644 --- a/config/alfresco/remote-avm-test-context.xml +++ b/config/alfresco/remote-avm-test-context.xml @@ -6,7 +6,7 @@ - rmi://localhost:1313/authentication + rmi://localhost:50500/authentication org.alfresco.service.cmr.security.AuthenticationService @@ -16,17 +16,23 @@ + + + + + + - rmi://localhost:1313/avm + rmi://localhost:50500/avm org.alfresco.service.cmr.remote.AVMRemoteTransport @@ -40,11 +46,14 @@ + + + - rmi://localhost:1313/avmsync + rmi://localhost:50500/avmsync org.alfresco.service.cmr.remote.AVMSyncServiceTransport diff --git a/source/java/org/alfresco/model/WCMAppModel.java b/source/java/org/alfresco/model/WCMAppModel.java index 5d0e4e4a8f..db72577fd4 100644 --- a/source/java/org/alfresco/model/WCMAppModel.java +++ b/source/java/org/alfresco/model/WCMAppModel.java @@ -36,9 +36,13 @@ public interface WCMAppModel static final QName TYPE_AVMWEBFOLDER = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webfolder"); static final QName PROP_AVMSTORE = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "avmstore"); static final QName PROP_DEFAULTWEBAPP = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "defaultwebapp"); + static final QName PROP_DEPLOYTO = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deployto"); + static final QName PROP_SELECTEDDEPLOYTO = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "selecteddeployto"); + static final QName PROP_SELECTEDDEPLOYVERSION = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "selecteddeployversion"); static final QName ASSOC_WEBUSER = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webuser"); static final QName ASSOC_WEBFORM = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webform"); static final QName ASSOC_WEBWORKFLOWDEFAULTS = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webworkflowdefaults"); + static final QName ASSOC_DEPLOYMENTREPORT = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deploymentreport"); // AVM web user reference static final QName TYPE_WEBUSER = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webuser"); @@ -63,6 +67,15 @@ public interface WCMAppModel // AVM web workflow defaults static final QName TYPE_WEBWORKFLOWDEFAULTS = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webworkflowdefaults"); + // AVM website deployment report + static final QName TYPE_DEPLOYMENTREPORT = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deploymentreport"); + static final QName PROP_DEPLOYSERVER = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deployserver"); + static final QName PROP_DEPLOYVERSION = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deployversion"); + static final QName PROP_DEPLOYSUCCESSFUL = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deploysuccessful"); + static final QName PROP_DEPLOYFAILEDREASON = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deployfailedreason"); + static final QName PROP_DEPLOYSTARTTIME = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deploystarttime"); + static final QName PROP_DEPLOYENDTIME = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "deployendtime"); + // AVM webapp aspect static final QName ASPECT_WEBAPP = QName.createQName(NamespaceService.WCMAPP_MODEL_1_0_URI, "webapp"); diff --git a/source/java/org/alfresco/repo/avm/AVMNode.java b/source/java/org/alfresco/repo/avm/AVMNode.java index 4963f08d5e..1194ee5f26 100644 --- a/source/java/org/alfresco/repo/avm/AVMNode.java +++ b/source/java/org/alfresco/repo/avm/AVMNode.java @@ -215,4 +215,16 @@ public interface AVMNode * @param other The other node. */ public void copyMetaDataFrom(AVMNode other); -} \ No newline at end of file + + /** + * Get the GUID associated with this version. + * @return The GUID. + */ + public String getGuid(); + + /** + * Set the GUID associated with this version. + * @param guid + */ + public void setGuid(String guid); +} diff --git a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java index b720f2e4ea..6173d9604f 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java @@ -33,6 +33,7 @@ import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.avm.AVMReadOnlyException; import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; /** * Base class for all repository file system like objects. @@ -77,6 +78,11 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ private AVMStore fStoreNew; + /** + * The GUID for this version. + */ + private String fGUID; + /** * Default constructor. */ @@ -109,6 +115,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable time, time); fStoreNew = store; + fGUID = GUID.generate(); } /** @@ -515,4 +522,20 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable throw new AVMReadOnlyException("Write Operation on R/O Node."); } } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#getGuid() + */ + public String getGuid() + { + return fGUID; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMNode#setGuid(java.lang.String) + */ + public void setGuid(String guid) + { + fGUID = guid; + } } diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java index 484062077f..cfb3b11f06 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeService.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java @@ -193,7 +193,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } else { - throw new InvalidStoreRefException("Not Found.", storeRef); + throw new InvalidStoreRefException(storeName +":/" + " not found.", storeRef); } } @@ -297,7 +297,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", parentRef); + throw new InvalidNodeRefException(avmPath + " not found.", parentRef); } catch (AVMExistsException e) { @@ -480,7 +480,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi avmVersionPath.getSecond()); if (desc == null) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } if (desc.isPlainDirectory()) { @@ -794,7 +794,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() +" not found.", nodeRef); } } @@ -821,7 +821,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi childVersionPath.getSecond()); if (child == null) { - throw new InvalidNodeRefException("Not Found.", childRef); + throw new InvalidNodeRefException(childVersionPath.getSecond() + " not found.", childRef); } Pair parentVersionPath = AVMNodeConverter.ToAVMVersionPath(parentRef); if (parentVersionPath.getFirst() >= 0) @@ -870,7 +870,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi String [] childPathBase = AVMNodeConverter.SplitBase(childPath); if (childPathBase[0] == null || !childPathBase[0].equals(parentPath)) { - throw new InvalidNodeRefException("Not a child.", childRef); + throw new InvalidNodeRefException(childPath + " not a child of " + parentPath, childRef); } try { @@ -887,7 +887,8 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not found.", childRef); + throw new InvalidNodeRefException(childPathBase[1] + " not found in " + childPathBase[0], + childRef); } } @@ -944,7 +945,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } Map result = new HashMap(); for (QName qName : props.keySet()) @@ -1017,7 +1018,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } } @@ -1052,7 +1053,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi avmVersionPath.getSecond()); if (desc == null) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } if (qName.equals(ContentModel.PROP_CREATED)) { @@ -1153,7 +1154,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi AVMNodeDescriptor desc = fAVMService.lookup(-1, avmVersionPath.getSecond()); if (desc == null) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } if (desc.isPlainFile()) { @@ -1171,7 +1172,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } } @@ -1256,7 +1257,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi } catch (AVMNotFoundException e) { - throw new InvalidNodeRefException("Not Found.", nodeRef); + throw new InvalidNodeRefException(avmVersionPath.getSecond() + " not found.", nodeRef); } } diff --git a/source/java/org/alfresco/repo/avm/AVMRemoteLocal.java b/source/java/org/alfresco/repo/avm/AVMRemoteLocal.java index 9978f18eae..78820a4dcb 100644 --- a/source/java/org/alfresco/repo/avm/AVMRemoteLocal.java +++ b/source/java/org/alfresco/repo/avm/AVMRemoteLocal.java @@ -496,4 +496,12 @@ public class AVMRemoteLocal implements AVMRemote { return fService.getAPath(desc); } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.remote.AVMRemote#setGuid(java.lang.String, java.lang.String) + */ + public void setGuid(String path, String guid) + { + fService.setGuid(path, guid); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMRemoteTransportService.java b/source/java/org/alfresco/repo/avm/AVMRemoteTransportService.java index 7708879cb1..a34888fe30 100644 --- a/source/java/org/alfresco/repo/avm/AVMRemoteTransportService.java +++ b/source/java/org/alfresco/repo/avm/AVMRemoteTransportService.java @@ -1018,4 +1018,13 @@ public class AVMRemoteTransportService implements AVMRemoteTransport, Runnable fAuthService.validate(ticket); return fAVMService.getAPath(desc); } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.remote.AVMRemoteTransport#setGuid(java.lang.String, java.lang.String, java.lang.String) + */ + public void setGuid(String ticket, String path, String guid) + { + fAuthService.validate(ticket); + fAVMService.setGuid(path, guid); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index dab5c1ab27..f5b3137d41 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -51,6 +51,7 @@ import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; import org.alfresco.util.Pair; import org.apache.log4j.Logger; @@ -2442,4 +2443,29 @@ public class AVMRepository fLookupCount.set(null); } } + + /** + * Set the GUID on a node. + * @param path + * @param guid + */ + public void setGuid(String path, String guid) + { + fLookupCount.set(1); + try + { + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + if (store == null) + { + throw new AVMNotFoundException("Store not found:" + pathParts[0]); + } + fLookupCache.onWrite(pathParts[0]); + store.setGuid(pathParts[1], guid); + } + finally + { + fLookupCount.set(null); + } + } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index 68334f495e..58b7bb1d80 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -1458,4 +1458,17 @@ public class AVMServiceImpl implements AVMService AlfrescoTransactionSupport.bindListener(fTransactionListener); fAVMRepository.revert(baseName[0], baseName[1], toRevertTo); } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.AVMService#setGuid(java.lang.String, java.lang.String) + */ + public void setGuid(String path, String guid) + { + if (path == null || guid == null) + { + throw new AVMBadArgumentException("Illegal Null Argument."); + } + AlfrescoTransactionSupport.bindListener(fTransactionListener); + fAVMRepository.setGuid(path, guid); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 786c14d830..819aafc3d3 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -60,6 +60,8 @@ import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avm.LayeringDescriptor; import org.alfresco.service.cmr.avm.VersionDescriptor; +import org.alfresco.service.cmr.avm.deploy.DeploymentReport; +import org.alfresco.service.cmr.avm.deploy.DeploymentService; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncException; import org.alfresco.service.cmr.model.FileFolderService; @@ -82,6 +84,73 @@ import org.alfresco.util.Pair; */ public class AVMServiceTest extends AVMServiceTestBase { + /** + * Test Deployment. + */ + public void testDeployment() + { + try + { + DeploymentService depService = (DeploymentService)fContext.getBean("DeploymentService"); + setupBasicTree(); + TestDeploymentCallback callback = new TestDeploymentCallback(); + fService.createStore("target"); + DeploymentReport report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, callback); + System.out.println(report); + assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getGuid(), + fService.lookup(-1, "target:/a/b/c/foo").getGuid()); + assertEquals(fService.lookup(-1, "main:/a/b/c/bar").getGuid(), + fService.lookup(-1, "target:/a/b/c/bar").getGuid()); + fService.createFile("main:/a/b", "biz").close(); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, true, callback); + System.out.println(report); + System.out.println(recursiveList("target", -1, true)); + assertNull(fService.lookup(-1, "target:/a/b/biz")); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, callback); + System.out.println(report); + assertEquals(fService.lookup(-1, "main:/a/b/biz").getGuid(), + fService.lookup(-1, "target:/a/b/biz").getGuid()); + fService.removeNode("main:/a/b/c/foo"); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, true, false, callback); + System.out.println(report); + assertNotNull(fService.lookup(-1, "target:/a/b/c/foo")); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, callback); + System.out.println(report); + assertNull(fService.lookup(-1, "target:/a/b/c/foo")); + fService.removeNode("main:/a/b/c/bar"); + fService.createDirectory("main:/a/b/c", "bar"); + report = depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target:/a", false, false, false, callback); + System.out.println(report); + depService.deployDifference(-1, "main:/a", "localhost", 50500, "admin", "admin", "target2:/wiggly/diggly", true, false, false, callback); + System.out.println(report); + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + } + + /** + * Test of GUIDs on AVM Nodes. + */ + public void testGuids() + { + try + { + setupBasicTree(); + System.out.println(fService.lookup(-1, "main:/a/b/c/foo").getGuid()); + String guid = GUID.generate(); + fService.setGuid("main:/a/b/c/foo", guid); + assertEquals(guid, fService.lookup(-1, "main:/a/b/c/foo").getGuid()); + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + } + /** * Test the revert to version action. */ diff --git a/source/java/org/alfresco/repo/avm/AVMStore.java b/source/java/org/alfresco/repo/avm/AVMStore.java index 2099f102ec..adf0c171a4 100644 --- a/source/java/org/alfresco/repo/avm/AVMStore.java +++ b/source/java/org/alfresco/repo/avm/AVMStore.java @@ -470,4 +470,11 @@ public interface AVMStore * @param toRevertTo The descriptor of the version to revert to. */ public void revert(String path, String name, AVMNodeDescriptor toRevertTo); -} \ No newline at end of file + + /** + * Set the GUID on a node. + * @param path + * @param guid + */ + public void setGuid(String path, String guid); +} diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index 4a2226f2d6..7bb37987d1 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -58,6 +58,7 @@ 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.alfresco.util.GUID; /** * A Repository contains a current root directory and a list of @@ -948,6 +949,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMNode node = lPath.getCurrentNode(); node.setProperty(name, value); + node.setGuid(GUID.generate()); } /** @@ -964,6 +966,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMNode node = lPath.getCurrentNode(); node.setProperties(properties); + node.setGuid(GUID.generate()); } /** @@ -1014,6 +1017,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + node.setGuid(GUID.generate()); node.deleteProperty(name); } @@ -1029,6 +1033,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMNotFoundException("Path " + path + " not found."); } AVMNode node = lPath.getCurrentNode(); + node.setGuid(GUID.generate()); node.deleteProperties(); } @@ -1137,6 +1142,7 @@ public class AVMStoreImpl implements AVMStore, Serializable throw new AVMWrongTypeException("File Expected."); } node.updateModTime(); + node.setGuid(GUID.generate()); return ((FileNode)node).getContentData(lPath); } @@ -1174,6 +1180,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMNode node = lPath.getCurrentNode(); node.copyMetaDataFrom(from); + node.setGuid(GUID.generate()); } /** @@ -1197,6 +1204,7 @@ public class AVMStoreImpl implements AVMStore, Serializable new AVMAspectNameImpl(); newName.setNode(node); newName.setName(aspectName); + node.setGuid(GUID.generate()); AVMDAOs.Instance().fAVMAspectNameDAO.save(newName); } @@ -1245,6 +1253,7 @@ public class AVMStoreImpl implements AVMStore, Serializable { AVMDAOs.Instance().fAVMNodePropertyDAO.delete(node, name); } + node.setGuid(GUID.generate()); } /** @@ -1279,6 +1288,7 @@ public class AVMStoreImpl implements AVMStore, Serializable } AVMNode node = lPath.getCurrentNode(); node.setAcl(acl); + node.setGuid(GUID.generate()); } /** @@ -1355,4 +1365,18 @@ public class AVMStoreImpl implements AVMStore, Serializable PropertyValue value = new PropertyValue(null, toRevertTo.getId()); toLink.setProperty(WCMModel.PROP_REVERTED_ID, value); } + + /* (non-Javadoc) + * @see org.alfresco.repo.avm.AVMStore#setGuid(java.lang.String, java.lang.String) + */ + public void setGuid(String path, String guid) + { + Lookup lPath = lookup(-1, path, true, true); + if (lPath == null) + { + throw new AVMNotFoundException("Path not found: " + path); + } + AVMNode node = lPath.getCurrentNode(); + node.setGuid(guid); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMTestRemote.java b/source/java/org/alfresco/repo/avm/AVMTestRemote.java index 89a1df3d09..b762dab108 100644 --- a/source/java/org/alfresco/repo/avm/AVMTestRemote.java +++ b/source/java/org/alfresco/repo/avm/AVMTestRemote.java @@ -28,6 +28,7 @@ import java.io.OutputStream; import java.util.List; import org.alfresco.repo.remote.ClientTicketHolder; +import org.alfresco.repo.remote.ClientTicketHolderGlobal; import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; @@ -72,7 +73,7 @@ public class AVMTestRemote extends TestCase fAuthService = (AuthenticationService)fContext.getBean("authenticationService"); fAuthService.authenticate("admin", "admin".toCharArray()); String ticket = fAuthService.getCurrentTicket(); - ClientTicketHolder.SetTicket(ticket); + ((ClientTicketHolder)fContext.getBean("clientTicketHolder")).setTicket(ticket); } @Override diff --git a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java index 36bef60dfa..165dd8f76f 100644 --- a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java @@ -121,6 +121,7 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -149,6 +150,7 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -179,6 +181,7 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index dd2cf4628b..e8f5e0ff18 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -719,6 +719,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), indirect, fPrimaryIndirection, @@ -748,6 +749,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), getUnderlying(lPath), fPrimaryIndirection, @@ -788,6 +790,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), indirection, fPrimaryIndirection, diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java index b55b006382..1cf09e9cb7 100644 --- a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java @@ -165,6 +165,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), getUnderlying(lPath), false, @@ -193,6 +194,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), getUnderlying(lPath), false, @@ -223,6 +225,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), fIndirection, false, diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index c13570c4e5..66424a876f 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -375,6 +375,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -403,6 +404,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -433,6 +435,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index 78c9eb5f25..d571b84cda 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -200,6 +200,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -228,6 +229,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, @@ -258,6 +260,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode attrs.getModDate(), attrs.getAccessDate(), getId(), + getGuid(), getVersionID(), null, false, diff --git a/source/java/org/alfresco/repo/avm/TestDeploymentCallback.java b/source/java/org/alfresco/repo/avm/TestDeploymentCallback.java new file mode 100644 index 0000000000..62cc1051d6 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/TestDeploymentCallback.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.repo.avm; + +import org.alfresco.service.cmr.avm.deploy.DeploymentCallback; +import org.alfresco.service.cmr.avm.deploy.DeploymentEvent; + +/** + * Trivial deployment callback for testing. + * @author britt + */ +public class TestDeploymentCallback implements DeploymentCallback +{ + public void eventOccurred(DeploymentEvent event) + { + System.out.println(event); + } +} diff --git a/source/java/org/alfresco/repo/avm/actions/AVMDeploySnapshotAction.java b/source/java/org/alfresco/repo/avm/actions/AVMDeploySnapshotAction.java new file mode 100644 index 0000000000..3351bcf329 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/actions/AVMDeploySnapshotAction.java @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ + +package org.alfresco.repo.avm.actions; + +import java.io.PrintWriter; +import java.io.Serializable; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMAppModel; +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.avm.deploy.DeploymentCallback; +import org.alfresco.service.cmr.avm.deploy.DeploymentEvent; +import org.alfresco.service.cmr.avm.deploy.DeploymentReport; +import org.alfresco.service.cmr.avm.deploy.DeploymentService; +import org.alfresco.service.cmr.avmsync.AVMSyncException; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Deploys a website snapshot to a remote server. + * + * @author gavinc + */ +public class AVMDeploySnapshotAction extends ActionExecuterAbstractBase +{ + public static final String NAME = "avm-deploy-snapshot"; + + public static final String PARAM_WEBSITE = "website"; + public static final String PARAM_TARGET_SERVER = "target-server"; + public static final String PARAM_DEFAULT_RMI_PORT = "default-rmi-port"; + public static final String PARAM_REMOTE_USERNAME = "remote-username"; + public static final String PARAM_REMOTE_PASSWORD = "remote-password"; + public static final String PARAM_CALLBACK = "deploy-callback"; + public static final String PARAM_DELAY = "delay"; + + private DeploymentService deployService; + private ContentService contentService; + private NodeService nodeService; + + private static Log logger = LogFactory.getLog(AVMDeploySnapshotAction.class); + private static Log delayDeploymentLogger = LogFactory.getLog("alfresco.deployment.delay"); + + /** + * @param service The NodeService instance + */ + public void setNodeService(NodeService service) + { + this.nodeService = service; + } + + /** + * @param contentService The ContentService instance + */ + public void setContentService(ContentService contentService) + { + this.contentService = contentService; + } + + /** + * @param service The AVM Deployment Service instance + */ + public void setDeploymentService(DeploymentService service) + { + deployService = service; + } + + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add(new ParameterDefinitionImpl(PARAM_WEBSITE, DataTypeDefinition.NODE_REF, true, + getParamDisplayLabel(PARAM_WEBSITE))); + paramList.add(new ParameterDefinitionImpl(PARAM_TARGET_SERVER, DataTypeDefinition.TEXT, true, + getParamDisplayLabel(PARAM_TARGET_SERVER))); + paramList.add(new ParameterDefinitionImpl(PARAM_DEFAULT_RMI_PORT, DataTypeDefinition.INT, true, + getParamDisplayLabel(PARAM_DEFAULT_RMI_PORT))); + paramList.add(new ParameterDefinitionImpl(PARAM_REMOTE_USERNAME, DataTypeDefinition.TEXT, true, + getParamDisplayLabel(PARAM_REMOTE_USERNAME))); + paramList.add(new ParameterDefinitionImpl(PARAM_REMOTE_PASSWORD, DataTypeDefinition.TEXT, true, + getParamDisplayLabel(PARAM_REMOTE_PASSWORD))); + paramList.add(new ParameterDefinitionImpl(PARAM_CALLBACK, DataTypeDefinition.ANY, false, + getParamDisplayLabel(PARAM_CALLBACK))); + paramList.add(new ParameterDefinitionImpl(PARAM_DELAY, DataTypeDefinition.INT, false, + getParamDisplayLabel(PARAM_DELAY))); + } + + @Override + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) + { + // the actionedUponNodeRef is the path of the sandbox to deploy + Pair avmVersionPath = AVMNodeConverter.ToAVMVersionPath(actionedUponNodeRef); + int version = avmVersionPath.getFirst(); + String path = avmVersionPath.getSecond(); + + // get store name and path parts. + String [] storePath = path.split(":"); + if (storePath.length != 2) + { + throw new AVMSyncException("Malformed source path: " + path); + } + + // get the NodeRef representing the website being deployed + NodeRef websiteRef = (NodeRef)action.getParameterValue(PARAM_WEBSITE); + if (this.nodeService.exists(websiteRef) == false) + { + throw new IllegalStateException("The website NodeRef (" + websiteRef + + ") provided does not exist!"); + } + + // get the callback object + DeploymentCallback callback = (DeploymentCallback)action.getParameterValue(PARAM_CALLBACK); + + // get the remote machine + String targetServer = (String)action.getParameterValue(PARAM_TARGET_SERVER); + String remoteUsername = (String)action.getParameterValue(PARAM_REMOTE_USERNAME); + String remotePassword = (String)action.getParameterValue(PARAM_REMOTE_PASSWORD); + int defaultRmiPort = (Integer)action.getParameterValue(PARAM_DEFAULT_RMI_PORT); + int delay = -1; + if (action.getParameterValue(PARAM_DELAY) != null) + { + delay = (Integer)action.getParameterValue(PARAM_DELAY); + } + + // if "localhost" is passed as the target server add "live" to the end of the + // store name, this store will then get created automatically. + String targetPath = null; + if (targetServer.equalsIgnoreCase("localhost") || targetServer.equalsIgnoreCase("127.0.0.1")) + { + targetPath = storePath[0] + "live:" + storePath[1]; + } + else + { + // TODO: Check that the actual host name of the machine hasn't been passed + + targetPath = path; + } + + // take a note of the current date/time + Date startDate = new Date(); + + if (logger.isDebugEnabled()) + logger.debug("Starting deployment of " + actionedUponNodeRef.toString() + + " to " + targetServer + " at " + startDate); + + if (delayDeploymentLogger.isDebugEnabled() && delay > 0) + { + delayDeploymentLogger.debug("Delaying deployment by " + delay + "s..."); + + // add a delay for testing purposes if the delay logger level is debug + try { Thread.sleep(1000*delay); } catch (Throwable e) {} + } + + // make the deploy call passing in the DeploymentCallback, if present + Throwable deployError = null; + DeploymentReport report = null; + try + { + int port = defaultRmiPort; + + // check whether there is a port number present, if so, use it + int idx = targetServer.indexOf(":"); + if (idx != -1) + { + String strPort = targetServer.substring(idx+1); + port = Integer.parseInt(strPort); + } + + // TODO: we need to capture username/password for the remote server at some + // point, for now we use the admin/admin account, need to externalise this too! + report = this.deployService.deployDifference(version, path, targetServer, port, + remoteUsername, remotePassword, targetPath, true, false, false, callback); + } + catch (Throwable err) + { + deployError = err; + logger.error(deployError); + + // report the error to the callback object + // TODO: See if this can be incorporated into the DeploymentCallback I/F + if (callback != null) + { + // to avoid a circular dependency use reflection to call the method + try + { + Method method = callback.getClass().getMethod("errorOccurred", new Class[] {Throwable.class}); + if (method != null) + { + method.invoke(callback, new Object[] {err}); + } + } + catch (Throwable e) + { + logger.warn("Failed to inform deployment monitor of deployment failure", e); + } + } + } + + if (report != null) + { + if (logger.isDebugEnabled()) + logger.debug("Differences successfully applied to " + targetServer); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Failed to apply differences to " + targetServer); + } + + // create the deployment report node + createDeploymentReportNode(report, (String)action.getParameterValue(PARAM_TARGET_SERVER), + version, websiteRef, startDate, deployError); + } + + /** + * Creates a deployment report node as a child of the given website. + * + * @param report The DeploymentReport result from the deploy, + * will be null if the deploy failed + * @param targetServer The server the deploy was going to + * @param version The version of the site bebing deployed (the snapshot) + * @param websiteRef The NodeRef of the folder representing the website + * @param startDate The date/time the deployment started + * @param error The error that caused the deployment to fail, null if the + * deployment was successful + * @return The created deployment report NodeRef + */ + private NodeRef createDeploymentReportNode(DeploymentReport report, String targetServer, + int version, NodeRef websiteRef, Date startDate, Throwable error) + { + NodeRef reportRef = null; + + Map props = new HashMap(4, 1.0f); + props.put(ContentModel.PROP_NAME, targetServer.replace(':', '_') + " deployment report.txt"); + props.put(WCMAppModel.PROP_DEPLOYSERVER, targetServer); + props.put(WCMAppModel.PROP_DEPLOYVERSION, version); + props.put(WCMAppModel.PROP_DEPLOYSTARTTIME, startDate); + props.put(WCMAppModel.PROP_DEPLOYENDTIME, new Date()); + props.put(WCMAppModel.PROP_DEPLOYSUCCESSFUL, (report != null)); + if (report == null && error != null) + { + // add error message as fail reason if appropriate + props.put(WCMAppModel.PROP_DEPLOYFAILEDREASON, error.getMessage()); + } + reportRef = this.nodeService.createNode(websiteRef, + WCMAppModel.ASSOC_DEPLOYMENTREPORT, WCMAppModel.ASSOC_DEPLOYMENTREPORT, + WCMAppModel.TYPE_DEPLOYMENTREPORT, props).getChildRef(); + ContentWriter writer = contentService.getWriter(reportRef, ContentModel.PROP_CONTENT, true); + writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN); + writer.setEncoding("UTF-8"); + + if (report == null) + { + if (error == null) + { + writer.putContent(""); + } + else + { + // add the full stack trace of the error as the content + StringWriter stack = new StringWriter(); + PrintWriter stackPrint = new PrintWriter(stack); + error.printStackTrace(stackPrint); + writer.putContent(stack.toString()); + } + } + else + { + // TODO: revisit this, is it better to stream to a temp file? + StringBuilder builder = new StringBuilder(); + for (DeploymentEvent event : report) + { + builder.append(event.getType()); + builder.append(" "); + builder.append(event.getDestination()); + builder.append("\r\n"); + } + + writer.putContent(builder.toString()); + } + + if (logger.isDebugEnabled()) + logger.debug("Created deplyoment report node (" + reportRef + ") for targetServer " + + targetServer); + + return reportRef; + } +} diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml index 4f10625a4a..35dc1d15a7 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml +++ b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml @@ -32,6 +32,7 @@ won't cause violations in the db during saves. --> + diff --git a/source/java/org/alfresco/repo/clt/CltBase.java b/source/java/org/alfresco/repo/clt/CltBase.java index 583e9f666a..c7dee7138e 100644 --- a/source/java/org/alfresco/repo/clt/CltBase.java +++ b/source/java/org/alfresco/repo/clt/CltBase.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.Map; import org.alfresco.repo.remote.ClientTicketHolder; +import org.alfresco.repo.remote.ClientTicketHolderGlobal; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.remote.AVMRemote; import org.alfresco.service.cmr.remote.RepoRemote; @@ -71,7 +72,7 @@ public abstract class CltBase fAuthenticationService = (AuthenticationService)fContext.getBean("authenticationService"); fAuthenticationService.authenticate(System.getenv("ALFUSER"), System.getenv("ALFPASSWORD").toCharArray()); String ticket = fAuthenticationService.getCurrentTicket(); - ClientTicketHolder.SetTicket(ticket); + ((ClientTicketHolder)fContext.getBean("clientTicketHolder")).setTicket(ticket); } /** diff --git a/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java new file mode 100644 index 0000000000..5a7d62f4d4 --- /dev/null +++ b/source/java/org/alfresco/repo/deploy/DeploymentServiceImpl.java @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.repo.deploy; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; + +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.util.SimplePath; +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.repo.remote.AVMRemoteImpl; +import org.alfresco.repo.remote.ClientTicketHolder; +import org.alfresco.repo.remote.ClientTicketHolderThread; +import org.alfresco.service.cmr.avm.AVMException; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMNotFoundException; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.avm.AVMWrongTypeException; +import org.alfresco.service.cmr.avm.deploy.DeploymentCallback; +import org.alfresco.service.cmr.avm.deploy.DeploymentEvent; +import org.alfresco.service.cmr.avm.deploy.DeploymentReport; +import org.alfresco.service.cmr.avm.deploy.DeploymentService; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.remote.AVMRemote; +import org.alfresco.service.cmr.remote.AVMRemoteTransport; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; +import org.springframework.remoting.rmi.RmiProxyFactoryBean; + +/** + * Implementation of DeploymentService. + * @author britt + */ +public class DeploymentServiceImpl implements DeploymentService +{ + /** + * The local AVMService Instance. + */ + private AVMService fAVMService; + + /** + * The Ticket holder. + */ + private ClientTicketHolder fTicketHolder; + + /** + * Default constructor. + */ + public DeploymentServiceImpl() + { + fTicketHolder = new ClientTicketHolderThread(); + } + + /** + * Setter. + * @param service The instance to set. + */ + public void setAvmService(AVMService service) + { + fAVMService = service; + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifference(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean) + */ + public DeploymentReport deployDifference(int version, String srcPath, String hostName, int port, String userName, String password, String dstPath, boolean createDst, boolean dontDelete, boolean dontDo, DeploymentCallback callback) + { + try + { + DeploymentReport report = new DeploymentReport(); + AVMRemote remote = getRemote(hostName, port, userName, password); + if (callback != null) + { + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.START, + new Pair(version, srcPath), + dstPath); + callback.eventOccurred(event); + } + // Get the root of the deployment from this server. + AVMNodeDescriptor srcRoot = fAVMService.lookup(version, srcPath); + if (srcRoot == null) + { + throw new AVMNotFoundException("Directory Not Found: " + srcPath); + } + if (!srcRoot.isDirectory()) + { + throw new AVMWrongTypeException("Not a directory: " + srcPath); + } + // Create a snapshot on the destination store. + String [] storePath = dstPath.split(":"); + int snapshot = -1; + AVMNodeDescriptor dstParent = null; + if (!dontDo) + { + String[] parentBase = AVMNodeConverter.SplitBase(dstPath); + dstParent = remote.lookup(-1, parentBase[0]); + if (dstParent == null) + { + if (createDst) + { + createDestination(remote, parentBase[0]); + dstParent = remote.lookup(-1, parentBase[0]); + } + else + { + throw new AVMNotFoundException("Node Not Found: " + parentBase[0]); + } + } + snapshot = remote.createSnapshot(storePath[0], "PreDeploy", "Pre Deployment Snapshot"); + } + // Get the root of the deployment on the destination server. + AVMNodeDescriptor dstRoot = remote.lookup(-1, dstPath); + if (dstRoot == null) + { + // If it doesn't exist, do a copyDirectory to create it. + DeploymentEvent event = + new DeploymentEvent(DeploymentEvent.Type.COPIED, + new Pair(version, srcPath), + dstPath); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return report; + } + copyDirectory(version, srcRoot, dstParent, remote); + if (callback != null) + { + event = new DeploymentEvent(DeploymentEvent.Type.END, + new Pair(version, srcPath), + dstPath); + callback.eventOccurred(event); + } + return report; + } + if (!dstRoot.isDirectory()) + { + throw new AVMWrongTypeException("Not a Directory: " + dstPath); + } + // The corresponding directory exists so recursively deploy. + try + { + deployDirectoryPush(version, srcRoot, dstRoot, remote, dontDelete, dontDo, report, callback); + if (callback != null) + { + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.END, + new Pair(version, srcPath), + dstPath); + callback.eventOccurred(event); + } + return report; + } + catch (AVMException e) + { + try + { + if (snapshot != -1) + { + AVMSyncService syncService = getSyncService(hostName, port); + List diffs = syncService.compare(snapshot, dstPath, -1, dstPath, null); + syncService.update(diffs, null, false, false, true, true, "Abortd Deployment", "Aborted Deployment"); + } + } + catch (Exception ee) + { + throw new AVMException("Failed to rollback to version " + snapshot + " on " + hostName, ee); + } + throw new AVMException("Deployment to " + hostName + "failed.", e); + } + } + finally + { + fTicketHolder.setTicket(null); + } + } + + /** + * Deploy all the children of corresponding directories. + * @param src The source directory. + * @param dst The destination directory. + * @param remote The AVMRemote instance. + * @param dontDelete Flag for not deleting. + * @param dontDo Flag for dry run. + */ + private void deployDirectoryPush(int version, + AVMNodeDescriptor src, AVMNodeDescriptor dst, + AVMRemote remote, boolean dontDelete, boolean dontDo, + DeploymentReport report, + DeploymentCallback callback) + { + // Get the listing for the source. + SortedMap srcList = fAVMService.getDirectoryListing(src); + // Get the listing for the destination. + SortedMap dstList = remote.getDirectoryListing(dst); + for (Map.Entry entry : srcList.entrySet()) + { + String name = entry.getKey(); + AVMNodeDescriptor srcNode = entry.getValue(); + AVMNodeDescriptor dstNode = dstList.get(name); + deploySinglePush(version, srcNode, dst, dstNode, remote, dontDelete, dontDo, report, callback); + } + // Delete nodes that are missing in the source. + if (dontDelete) + { + return; + } + for (String name : dstList.keySet()) + { + if (!srcList.containsKey(name)) + { + Pair source = + new Pair(version, AVMNodeConverter.ExtendAVMPath(src.getPath(), name)); + String destination = AVMNodeConverter.ExtendAVMPath(dst.getPath(), name); + DeploymentEvent event = + new DeploymentEvent(DeploymentEvent.Type.DELETED, + source, + destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + continue; + } + remote.removeNode(dst.getPath(), name); + } + } + } + + /** + * Push out a single node. + * @param src The source node. + * @param dstParent The destination parent. + * @param dst The destination node. May be null. + * @param remote The AVMRemote instance. + * @param dontDelete Flag for whether deletions should happen. + * @param dontDo Dry run flag. + */ + private void deploySinglePush(int version, + AVMNodeDescriptor src, AVMNodeDescriptor dstParent, + AVMNodeDescriptor dst, AVMRemote remote, + boolean dontDelete, boolean dontDo, + DeploymentReport report, + DeploymentCallback callback) + { + // Destination does not exist. + if (dst == null) + { + if (src.isDirectory()) + { + // Recursively copy a source directory. + Pair source = + new Pair(version, src.getPath()); + String destination = AVMNodeConverter.ExtendAVMPath(dstParent.getPath(), src.getName()); + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, + source, + destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return; + } + copyDirectory(version, src, dstParent, remote); + return; + } + Pair source = + new Pair(version, src.getPath()); + String destination = AVMNodeConverter.ExtendAVMPath(dstParent.getPath(), src.getName()); + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, + source, + destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return; + } + // Copy a source file. + OutputStream out = remote.createFile(dstParent.getPath(), src.getName()); + InputStream in = fAVMService.getFileInputStream(src); + copyStream(in, out); + copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + src.getName()), remote); + return; + } + // Destination exists. + if (src.isDirectory()) + { + // If the destination is also a directory, recursively deploy. + if (dst.isDirectory()) + { + deployDirectoryPush(version, src, dst, remote, dontDelete, dontDo, report, callback); + return; + } + Pair source = + new Pair(version, src.getPath()); + String destination = dst.getPath(); + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.COPIED, + source, destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return; + } + remote.removeNode(dstParent.getPath(), src.getName()); + copyDirectory(version, src, dstParent, remote); + return; + } + // Source is a file. + if (dst.isFile()) + { + // Destination is also a file. Overwrite if the GUIDS are different. + if (src.getGuid().equals(dst.getGuid())) + { + return; + } + Pair source = + new Pair(version, src.getPath()); + String destination = dst.getPath(); + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED, + source, + destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return; + } + InputStream in = fAVMService.getFileInputStream(src); + OutputStream out = remote.getFileOutputStream(dst.getPath()); + copyStream(in, out); + copyMetadata(version, src, dst, remote); + return; + } + Pair source = + new Pair(version, src.getPath()); + String destination = AVMNodeConverter.ExtendAVMPath(dstParent.getPath(), src.getName()); + DeploymentEvent event = new DeploymentEvent(DeploymentEvent.Type.UPDATED, + source, + destination); + report.add(event); + if (callback != null) + { + callback.eventOccurred(event); + } + if (dontDo) + { + return; + } + // Destination is a directory and the source is a file. + // Delete the destination directory and copy the file over. + remote.removeNode(dstParent.getPath(), dst.getName()); + InputStream in = fAVMService.getFileInputStream(src); + OutputStream out = remote.createFile(dstParent.getPath(), src.getName()); + copyStream(in, out); + copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + dst.getName()), remote); + } + + /** + * Recursively copy a directory. + * @param src + * @param parent + * @param remote + */ + private void copyDirectory(int version, AVMNodeDescriptor src, AVMNodeDescriptor parent, + AVMRemote remote) + { + // Create the destination directory. + remote.createDirectory(parent.getPath(), src.getName()); + AVMNodeDescriptor newParent = remote.lookup(-1, parent.getPath() + '/' + src.getName()); + copyMetadata(version, src, newParent, remote); + SortedMap list = + fAVMService.getDirectoryListing(src); + // For each child in the source directory. + for (AVMNodeDescriptor child : list.values()) + { + // If it's a file, copy it over and move on. + if (child.isFile()) + { + InputStream in = fAVMService.getFileInputStream(child); + OutputStream out = remote.createFile(newParent.getPath(), child.getName()); + copyStream(in, out); + copyMetadata(version, child, remote.lookup(-1, newParent.getPath() + '/' + child.getName()), remote); + continue; + } + // Otherwise copy the child directory recursively. + copyDirectory(version, child, newParent, remote); + } + } + + /** + * Utility for copying from one stream to another. + * @param in The input stream. + * @param out The output stream. + */ + private void copyStream(InputStream in, OutputStream out) + { + byte[] buff = new byte[8192]; + int read = 0; + try + { + while ((read = in.read(buff)) != -1) + { + out.write(buff, 0, read); + } + in.close(); + out.close(); + } + catch (IOException e) + { + throw new AVMException("I/O Exception", e); + } + } + + private void copyMetadata(int version, AVMNodeDescriptor src, AVMNodeDescriptor dst, AVMRemote remote) + { + Map props = fAVMService.getNodeProperties(version, src.getPath()); + remote.setNodeProperties(dst.getPath(), props); + List aspects = fAVMService.getAspects(version, src.getPath()); + for (QName aspect : aspects) + { + remote.addAspect(dst.getPath(), aspect); + } + remote.setGuid(dst.getPath(), src.getGuid()); + } + + /** + * Utility to get an AVMRemote from a remote Alfresco Server. + * @param hostName + * @param port + * @param userName + * @param password + * @return + */ + private AVMRemote getRemote(String hostName, int port, String userName, String password) + { + try + { + RmiProxyFactoryBean authFactory = new RmiProxyFactoryBean(); + authFactory.setRefreshStubOnConnectFailure(true); + authFactory.setServiceInterface(AuthenticationService.class); + authFactory.setServiceUrl("rmi://" + hostName + ":" + port + "/authentication"); + authFactory.afterPropertiesSet(); + AuthenticationService authService = (AuthenticationService)authFactory.getObject(); + authService.authenticate(userName, password.toCharArray()); + String ticket = authService.getCurrentTicket(); + fTicketHolder.setTicket(ticket); + RmiProxyFactoryBean remoteFactory = new RmiProxyFactoryBean(); + remoteFactory.setRefreshStubOnConnectFailure(true); + remoteFactory.setServiceInterface(AVMRemoteTransport.class); + remoteFactory.setServiceUrl("rmi://" + hostName + ":" + port + "/avm"); + remoteFactory.afterPropertiesSet(); + AVMRemoteTransport transport = (AVMRemoteTransport)remoteFactory.getObject(); + AVMRemoteImpl remote = new AVMRemoteImpl(); + remote.setAvmRemoteTransport(transport); + remote.setClientTicketHolder(fTicketHolder); + return remote; + } + catch (Exception e) + { + throw new AVMException("Could not Initialize Remote Connection to " + hostName, e); + } + } + + /** + * Utility to get the sync service for rolling back after a failed deployment. + * @param hostName The target machine. + * @param port The port. + * @return An AVMSyncService instance. + */ + private AVMSyncService getSyncService(String hostName, int port) + { + try + { + RmiProxyFactoryBean syncFactory = new RmiProxyFactoryBean(); + syncFactory.setRefreshStubOnConnectFailure(true); + syncFactory.setServiceInterface(AVMSyncService.class); + syncFactory.setServiceUrl("rmi://" + hostName + ":" + port + "/avmsync"); + syncFactory.afterPropertiesSet(); + AVMSyncService syncService = (AVMSyncService)syncFactory.getObject(); + return syncService; + } + catch (Exception e) + { + throw new AVMException("Could not roll back failed deployment to " + hostName, e); + } + } + + /** + * Helper function to create a non existent destination. + * @param remote The AVMRemote instance. + * @param dstPath The destination path to create. + */ + private void createDestination(AVMRemote remote, String dstPath) + { + String[] storePath = dstPath.split(":"); + String storeName = storePath[0]; + String path = storePath[1]; + AVMStoreDescriptor storeDesc = remote.getStore(storeName); + if (storeDesc == null) + { + remote.createStore(storeName); + } + SimplePath simpPath = new SimplePath(path); + if (simpPath.size() == 0) + { + return; + } + String prevPath = storeName + ":/"; + for (int i = 0; i < simpPath.size(); i++) + { + String currPath = AVMNodeConverter.ExtendAVMPath(prevPath, simpPath.get(i)); + AVMNodeDescriptor desc = remote.lookup(-1, currPath); + if (desc == null) + { + remote.createDirectory(prevPath, simpPath.get(i)); + } + prevPath = currPath; + } + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.avm.deploy.DeploymentService#deployDifferenceFS(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean) + */ + public DeploymentReport deployDifferenceFS(int version, String srcPath, String hostName, int port, String userName, String password, String dstPath, boolean createDst, boolean dontDelete, boolean dontDo, DeploymentCallback callback) + { + return null; + } +} diff --git a/source/java/org/alfresco/repo/remote/AVMRemoteImpl.java b/source/java/org/alfresco/repo/remote/AVMRemoteImpl.java index 7efa30e77c..c49303bed1 100644 --- a/source/java/org/alfresco/repo/remote/AVMRemoteImpl.java +++ b/source/java/org/alfresco/repo/remote/AVMRemoteImpl.java @@ -31,6 +31,11 @@ public class AVMRemoteImpl implements AVMRemote */ private AVMRemoteTransport fTransport; + /** + * The client ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * Default constructor. */ @@ -46,12 +51,17 @@ public class AVMRemoteImpl implements AVMRemote fTransport = transport; } + public void setClientTicketHolder(ClientTicketHolder ticketHolder) + { + fTicketHolder = ticketHolder; + } + /* (non-Javadoc) * @see org.alfresco.repo.avm.AVMRemote#createAVMStore(java.lang.String) */ public void createStore(String name) { - fTransport.createStore(ClientTicketHolder.GetTicket(), name); + fTransport.createStore(fTicketHolder.getTicket(), name); } /* (non-Javadoc) @@ -60,7 +70,7 @@ public class AVMRemoteImpl implements AVMRemote public void createBranch(int version, String srcPath, String dstPath, String name) { - fTransport.createBranch(ClientTicketHolder.GetTicket(), version, + fTransport.createBranch(fTicketHolder.getTicket(), version, srcPath, dstPath, name); } @@ -69,7 +79,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void createDirectory(String path, String name) { - fTransport.createDirectory(ClientTicketHolder.GetTicket(), path, name); + fTransport.createDirectory(fTicketHolder.getTicket(), path, name); } /* (non-Javadoc) @@ -77,7 +87,7 @@ public class AVMRemoteImpl implements AVMRemote */ public OutputStream createFile(String path, String name) { - return new AVMRemoteOutputStream(fTransport.createFile(ClientTicketHolder.GetTicket(), path, name), fTransport); + return new AVMRemoteOutputStream(fTransport.createFile(fTicketHolder.getTicket(), path, name), fTransport, fTicketHolder); } /* (non-Javadoc) @@ -86,7 +96,7 @@ public class AVMRemoteImpl implements AVMRemote public void createLayeredDirectory(String targetPath, String parent, String name) { - fTransport.createLayeredDirectory(ClientTicketHolder.GetTicket(), targetPath, parent, name); + fTransport.createLayeredDirectory(fTicketHolder.getTicket(), targetPath, parent, name); } /* (non-Javadoc) @@ -94,7 +104,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void createLayeredFile(String targetPath, String parent, String name) { - fTransport.createLayeredFile(ClientTicketHolder.GetTicket(), targetPath, parent, name); + fTransport.createLayeredFile(fTicketHolder.getTicket(), targetPath, parent, name); } /* (non-Javadoc) @@ -102,7 +112,7 @@ public class AVMRemoteImpl implements AVMRemote */ public int createSnapshot(String store, String label, String comment) { - return fTransport.createSnapshot(ClientTicketHolder.GetTicket(), store, label, comment); + return fTransport.createSnapshot(fTicketHolder.getTicket(), store, label, comment); } /* (non-Javadoc) @@ -110,7 +120,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void deleteNodeProperties(String path) { - fTransport.deleteNodeProperties(ClientTicketHolder.GetTicket(), path); + fTransport.deleteNodeProperties(fTicketHolder.getTicket(), path); } /* (non-Javadoc) @@ -118,7 +128,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void deleteNodeProperty(String path, QName name) { - fTransport.deleteNodeProperty(ClientTicketHolder.GetTicket(), path, name); + fTransport.deleteNodeProperty(fTicketHolder.getTicket(), path, name); } /* (non-Javadoc) @@ -126,7 +136,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void deleteStoreProperty(String store, QName name) { - fTransport.deleteStoreProperty(ClientTicketHolder.GetTicket(), store, name); + fTransport.deleteStoreProperty(fTicketHolder.getTicket(), store, name); } /* (non-Javadoc) @@ -134,7 +144,7 @@ public class AVMRemoteImpl implements AVMRemote */ public AVMStoreDescriptor getStore(String name) { - return fTransport.getStore(ClientTicketHolder.GetTicket(), name); + return fTransport.getStore(fTicketHolder.getTicket(), name); } /* (non-Javadoc) @@ -142,7 +152,7 @@ public class AVMRemoteImpl implements AVMRemote */ public AVMNodeDescriptor getStoreRoot(int version, String name) { - return fTransport.getStoreRoot(ClientTicketHolder.GetTicket(), version, name); + return fTransport.getStoreRoot(fTicketHolder.getTicket(), version, name); } /* (non-Javadoc) @@ -150,7 +160,7 @@ public class AVMRemoteImpl implements AVMRemote */ public List getStoreVersions(String name) { - return fTransport.getStoreVersions(ClientTicketHolder.GetTicket(), name); + return fTransport.getStoreVersions(fTicketHolder.getTicket(), name); } /* (non-Javadoc) @@ -159,7 +169,7 @@ public class AVMRemoteImpl implements AVMRemote public List getStoreVersions(String name, Date from, Date to) { - return fTransport.getStoreVersions(ClientTicketHolder.GetTicket(), name); + return fTransport.getStoreVersions(fTicketHolder.getTicket(), name); } /* (non-Javadoc) @@ -167,7 +177,7 @@ public class AVMRemoteImpl implements AVMRemote */ public List getStores() { - return fTransport.getStores(ClientTicketHolder.GetTicket()); + return fTransport.getStores(fTicketHolder.getTicket()); } /* (non-Javadoc) @@ -176,7 +186,7 @@ public class AVMRemoteImpl implements AVMRemote public AVMNodeDescriptor getCommonAncestor(AVMNodeDescriptor left, AVMNodeDescriptor right) { - return fTransport.getCommonAncestor(ClientTicketHolder.GetTicket(), left, right); + return fTransport.getCommonAncestor(fTicketHolder.getTicket(), left, right); } /* (non-Javadoc) @@ -184,7 +194,7 @@ public class AVMRemoteImpl implements AVMRemote */ public List getDeleted(int version, String path) { - return fTransport.getDeleted(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getDeleted(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -193,7 +203,7 @@ public class AVMRemoteImpl implements AVMRemote public SortedMap getDirectoryListing( int version, String path) { - return fTransport.getDirectoryListing(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getDirectoryListing(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -202,7 +212,7 @@ public class AVMRemoteImpl implements AVMRemote public SortedMap getDirectoryListing( AVMNodeDescriptor dir) { - return fTransport.getDirectoryListing(ClientTicketHolder.GetTicket(), dir); + return fTransport.getDirectoryListing(fTicketHolder.getTicket(), dir); } /* (non-Javadoc) @@ -211,7 +221,7 @@ public class AVMRemoteImpl implements AVMRemote public SortedMap getDirectoryListingDirect( int version, String path) { - return fTransport.getDirectoryListing(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getDirectoryListing(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -219,8 +229,8 @@ public class AVMRemoteImpl implements AVMRemote */ public InputStream getFileInputStream(int version, String path) { - return new AVMRemoteInputStream(fTransport.getInputHandle(ClientTicketHolder.GetTicket(), version, path), - fTransport); + return new AVMRemoteInputStream(fTransport.getInputHandle(fTicketHolder.getTicket(), version, path), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -228,8 +238,8 @@ public class AVMRemoteImpl implements AVMRemote */ public InputStream getFileInputStream(AVMNodeDescriptor desc) { - return new AVMRemoteInputStream(fTransport.getInputHandle(ClientTicketHolder.GetTicket(), desc), - fTransport); + return new AVMRemoteInputStream(fTransport.getInputHandle(fTicketHolder.getTicket(), desc), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -237,8 +247,8 @@ public class AVMRemoteImpl implements AVMRemote */ public OutputStream getFileOutputStream(String path) { - return new AVMRemoteOutputStream(fTransport.getOutputHandle(ClientTicketHolder.GetTicket(), path), - fTransport); + return new AVMRemoteOutputStream(fTransport.getOutputHandle(fTicketHolder.getTicket(), path), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -246,7 +256,7 @@ public class AVMRemoteImpl implements AVMRemote */ public List getHistory(AVMNodeDescriptor desc, int count) { - return fTransport.getHistory(ClientTicketHolder.GetTicket(), desc, count); + return fTransport.getHistory(fTicketHolder.getTicket(), desc, count); } /* (non-Javadoc) @@ -254,7 +264,7 @@ public class AVMRemoteImpl implements AVMRemote */ public String getIndirectionPath(int version, String path) { - return fTransport.getIndirectionPath(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getIndirectionPath(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -262,7 +272,7 @@ public class AVMRemoteImpl implements AVMRemote */ public int getLatestSnapshotID(String storeName) { - return fTransport.getLatestSnapshotID(ClientTicketHolder.GetTicket(), storeName); + return fTransport.getLatestSnapshotID(fTicketHolder.getTicket(), storeName); } /* (non-Javadoc) @@ -270,7 +280,7 @@ public class AVMRemoteImpl implements AVMRemote */ public int getNextVersionID(String storeName) { - return fTransport.getNextVersionID(ClientTicketHolder.GetTicket(), storeName); + return fTransport.getNextVersionID(fTicketHolder.getTicket(), storeName); } /* (non-Javadoc) @@ -278,7 +288,7 @@ public class AVMRemoteImpl implements AVMRemote */ public LayeringDescriptor getLayeringInfo(int version, String path) { - return fTransport.getLayeringInfo(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getLayeringInfo(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -286,7 +296,7 @@ public class AVMRemoteImpl implements AVMRemote */ public Map getNodeProperties(int version, String path) { - return fTransport.getNodeProperties(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getNodeProperties(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -294,7 +304,7 @@ public class AVMRemoteImpl implements AVMRemote */ public PropertyValue getNodeProperty(int version, String path, QName name) { - return fTransport.getNodeProperty(ClientTicketHolder.GetTicket(), version, path, name); + return fTransport.getNodeProperty(fTicketHolder.getTicket(), version, path, name); } /* (non-Javadoc) @@ -302,7 +312,7 @@ public class AVMRemoteImpl implements AVMRemote */ public Map getStoreProperties(String store) { - return fTransport.getStoreProperties(ClientTicketHolder.GetTicket(), store); + return fTransport.getStoreProperties(fTicketHolder.getTicket(), store); } /* (non-Javadoc) @@ -310,7 +320,7 @@ public class AVMRemoteImpl implements AVMRemote */ public PropertyValue getStoreProperty(String store, QName name) { - return fTransport.getStoreProperty(ClientTicketHolder.GetTicket(), store, name); + return fTransport.getStoreProperty(fTicketHolder.getTicket(), store, name); } /* (non-Javadoc) @@ -318,7 +328,7 @@ public class AVMRemoteImpl implements AVMRemote */ public AVMNodeDescriptor lookup(int version, String path) { - return fTransport.lookup(ClientTicketHolder.GetTicket(), version, path); + return fTransport.lookup(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -326,7 +336,7 @@ public class AVMRemoteImpl implements AVMRemote */ public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name) { - return fTransport.lookup(ClientTicketHolder.GetTicket(), dir, name); + return fTransport.lookup(fTicketHolder.getTicket(), dir, name); } /* (non-Javadoc) @@ -334,7 +344,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void makePrimary(String path) { - fTransport.makePrimary(ClientTicketHolder.GetTicket(), path); + fTransport.makePrimary(fTicketHolder.getTicket(), path); } /* (non-Javadoc) @@ -342,7 +352,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void purgeStore(String name) { - fTransport.purgeStore(ClientTicketHolder.GetTicket(), name); + fTransport.purgeStore(fTicketHolder.getTicket(), name); } /* (non-Javadoc) @@ -350,7 +360,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void purgeVersion(int version, String name) { - fTransport.purgeVersion(ClientTicketHolder.GetTicket(), version, name); + fTransport.purgeVersion(fTicketHolder.getTicket(), version, name); } /* (non-Javadoc) @@ -359,7 +369,7 @@ public class AVMRemoteImpl implements AVMRemote public Map queryStorePropertyKey(String store, QName keyPattern) { - return fTransport.queryStorePropertyKey(ClientTicketHolder.GetTicket(), store, keyPattern); + return fTransport.queryStorePropertyKey(fTicketHolder.getTicket(), store, keyPattern); } /* (non-Javadoc) @@ -368,7 +378,7 @@ public class AVMRemoteImpl implements AVMRemote public Map> queryStoresPropertyKey( QName keyPattern) { - return fTransport.queryStoresPropertyKey(ClientTicketHolder.GetTicket(), keyPattern); + return fTransport.queryStoresPropertyKey(fTicketHolder.getTicket(), keyPattern); } /* (non-Javadoc) @@ -376,7 +386,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void removeNode(String parent, String name) { - fTransport.removeNode(ClientTicketHolder.GetTicket(), parent, name); + fTransport.removeNode(fTicketHolder.getTicket(), parent, name); } /* (non-Javadoc) @@ -385,7 +395,7 @@ public class AVMRemoteImpl implements AVMRemote public void rename(String srcParent, String srcName, String dstParent, String dstName) { - fTransport.rename(ClientTicketHolder.GetTicket(), srcParent, srcName, dstParent, dstName); + fTransport.rename(fTicketHolder.getTicket(), srcParent, srcName, dstParent, dstName); } /* (non-Javadoc) @@ -393,7 +403,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void retargetLayeredDirectory(String path, String target) { - fTransport.retargetLayeredDirectory(ClientTicketHolder.GetTicket(), path, target); + fTransport.retargetLayeredDirectory(fTicketHolder.getTicket(), path, target); } /* (non-Javadoc) @@ -402,7 +412,7 @@ public class AVMRemoteImpl implements AVMRemote public void setNodeProperties(String path, Map properties) { - fTransport.setNodeProperties(ClientTicketHolder.GetTicket(), path, properties); + fTransport.setNodeProperties(fTicketHolder.getTicket(), path, properties); } /* (non-Javadoc) @@ -410,7 +420,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void setNodeProperty(String path, QName name, PropertyValue value) { - fTransport.setNodeProperty(ClientTicketHolder.GetTicket(), path, name, value); + fTransport.setNodeProperty(fTicketHolder.getTicket(), path, name, value); } /* (non-Javadoc) @@ -418,7 +428,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void setOpacity(String path, boolean opacity) { - fTransport.setOpacity(ClientTicketHolder.GetTicket(), path, opacity); + fTransport.setOpacity(fTicketHolder.getTicket(), path, opacity); } /* (non-Javadoc) @@ -426,7 +436,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void setStoreProperties(String store, Map props) { - fTransport.setStoreProperties(ClientTicketHolder.GetTicket(), store, props); + fTransport.setStoreProperties(fTicketHolder.getTicket(), store, props); } /* (non-Javadoc) @@ -434,7 +444,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void setStoreProperty(String store, QName name, PropertyValue value) { - fTransport.setStoreProperty(ClientTicketHolder.GetTicket(), store, name, value); + fTransport.setStoreProperty(fTicketHolder.getTicket(), store, name, value); } /* (non-Javadoc) @@ -442,7 +452,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void uncover(String dirPath, String name) { - fTransport.uncover(ClientTicketHolder.GetTicket(), dirPath, name); + fTransport.uncover(fTicketHolder.getTicket(), dirPath, name); } /* (non-Javadoc) @@ -450,7 +460,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void renameStore(String sourceName, String destName) { - fTransport.renameStore(ClientTicketHolder.GetTicket(), sourceName, destName); + fTransport.renameStore(fTicketHolder.getTicket(), sourceName, destName); } /* (non-Javadoc) @@ -458,7 +468,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void addAspect(String path, QName aspectName) { - fTransport.addAspect(ClientTicketHolder.GetTicket(), path, aspectName); + fTransport.addAspect(fTicketHolder.getTicket(), path, aspectName); } /* (non-Javadoc) @@ -466,7 +476,7 @@ public class AVMRemoteImpl implements AVMRemote */ public List getAspects(int version, String path) { - return fTransport.getAspects(ClientTicketHolder.GetTicket(), version, path); + return fTransport.getAspects(fTicketHolder.getTicket(), version, path); } /* (non-Javadoc) @@ -474,7 +484,7 @@ public class AVMRemoteImpl implements AVMRemote */ public boolean hasAspect(int version, String path, QName aspectName) { - return fTransport.hasAspect(ClientTicketHolder.GetTicket(), version, path, aspectName); + return fTransport.hasAspect(fTicketHolder.getTicket(), version, path, aspectName); } /* (non-Javadoc) @@ -482,7 +492,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void removeAspect(String path, QName aspectName) { - fTransport.removeAspect(ClientTicketHolder.GetTicket(), path, aspectName); + fTransport.removeAspect(fTicketHolder.getTicket(), path, aspectName); } /* (non-Javadoc) @@ -490,7 +500,7 @@ public class AVMRemoteImpl implements AVMRemote */ public void revert(String path, AVMNodeDescriptor toRevertTo) { - fTransport.revert(ClientTicketHolder.GetTicket(), path, toRevertTo); + fTransport.revert(fTicketHolder.getTicket(), path, toRevertTo); } /* (non-Javadoc) @@ -498,6 +508,14 @@ public class AVMRemoteImpl implements AVMRemote */ public Pair getAPath(AVMNodeDescriptor desc) { - return fTransport.getAPath(ClientTicketHolder.GetTicket(), desc); + return fTransport.getAPath(fTicketHolder.getTicket(), desc); + } + + /* (non-Javadoc) + * @see org.alfresco.service.cmr.remote.AVMRemote#setGuid(java.lang.String, java.lang.String) + */ + public void setGuid(String path, String guid) + { + fTransport.setGuid(fTicketHolder.getTicket(), path, guid); } } diff --git a/source/java/org/alfresco/repo/remote/AVMRemoteInputStream.java b/source/java/org/alfresco/repo/remote/AVMRemoteInputStream.java index b8ccf0ffe8..7415c19b24 100644 --- a/source/java/org/alfresco/repo/remote/AVMRemoteInputStream.java +++ b/source/java/org/alfresco/repo/remote/AVMRemoteInputStream.java @@ -39,6 +39,11 @@ public class AVMRemoteInputStream extends InputStream */ private AVMRemoteTransport fAVMRemote; + /** + * The client ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * The handle to the input stream. */ @@ -49,10 +54,12 @@ public class AVMRemoteInputStream extends InputStream * @param handle The handle returned by getInputStream(); * @param remote The AVMRemote instance. */ - public AVMRemoteInputStream(String handle, AVMRemoteTransport remote) + public AVMRemoteInputStream(String handle, AVMRemoteTransport remote, + ClientTicketHolder ticketHolder) { fHandle = handle; fAVMRemote = remote; + fTicketHolder = ticketHolder; } /** @@ -64,7 +71,7 @@ public class AVMRemoteInputStream extends InputStream { try { - byte [] buff = fAVMRemote.readInput(ClientTicketHolder.GetTicket(), fHandle, 1); + byte [] buff = fAVMRemote.readInput(fTicketHolder.getTicket(), fHandle, 1); if (buff.length == 0) { return -1; @@ -89,7 +96,7 @@ public class AVMRemoteInputStream extends InputStream { try { - byte [] buff = fAVMRemote.readInput(ClientTicketHolder.GetTicket(), fHandle, len); + byte [] buff = fAVMRemote.readInput(fTicketHolder.getTicket(), fHandle, len); if (buff.length == 0) { return -1; @@ -111,7 +118,7 @@ public class AVMRemoteInputStream extends InputStream { try { - fAVMRemote.closeInputHandle(ClientTicketHolder.GetTicket(), fHandle); + fAVMRemote.closeInputHandle(fTicketHolder.getTicket(), fHandle); } catch (Exception e) { diff --git a/source/java/org/alfresco/repo/remote/AVMRemoteOutputStream.java b/source/java/org/alfresco/repo/remote/AVMRemoteOutputStream.java index 23b2f06660..c28ffe3925 100644 --- a/source/java/org/alfresco/repo/remote/AVMRemoteOutputStream.java +++ b/source/java/org/alfresco/repo/remote/AVMRemoteOutputStream.java @@ -33,15 +33,19 @@ public class AVMRemoteOutputStream extends OutputStream private String fHandle; + private ClientTicketHolder fTicketHolder; + /** * Create a new one. * @param handle The handle returned from an AVMRemote call. * @param remote The AVMRemote instance. */ - public AVMRemoteOutputStream(String handle, AVMRemoteTransport remote) + public AVMRemoteOutputStream(String handle, AVMRemoteTransport remote, + ClientTicketHolder ticketHolder) { fAVMRemote = remote; fHandle = handle; + fTicketHolder = ticketHolder; } /** @@ -66,7 +70,7 @@ public class AVMRemoteOutputStream extends OutputStream { try { - fAVMRemote.closeOutputHandle(ClientTicketHolder.GetTicket(), fHandle); + fAVMRemote.closeOutputHandle(fTicketHolder.getTicket(), fHandle); } catch (Exception e) { @@ -88,13 +92,13 @@ public class AVMRemoteOutputStream extends OutputStream { if (off == 0) { - fAVMRemote.writeOutput(ClientTicketHolder.GetTicket(), fHandle, b, len); + fAVMRemote.writeOutput(fTicketHolder.getTicket(), fHandle, b, len); } else { byte [] buff = new byte[len]; System.arraycopy(b, off, buff, 0, len); - fAVMRemote.writeOutput(ClientTicketHolder.GetTicket(), fHandle, buff, len); + fAVMRemote.writeOutput(fTicketHolder.getTicket(), fHandle, buff, len); } } catch (Exception e) diff --git a/source/java/org/alfresco/repo/remote/AVMSyncServiceClient.java b/source/java/org/alfresco/repo/remote/AVMSyncServiceClient.java index a5d2072f58..db91874091 100644 --- a/source/java/org/alfresco/repo/remote/AVMSyncServiceClient.java +++ b/source/java/org/alfresco/repo/remote/AVMSyncServiceClient.java @@ -21,6 +21,11 @@ public class AVMSyncServiceClient implements AVMSyncService */ private AVMSyncServiceTransport fTransport; + /** + * The ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * Default constructor. */ @@ -36,13 +41,22 @@ public class AVMSyncServiceClient implements AVMSyncService fTransport = transport; } + /** + * Setter. + * @param ticketHolder To set. + */ + public void setClientTicketHolder(ClientTicketHolder ticketHolder) + { + fTicketHolder = ticketHolder; + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.avmsync.AVMSyncService#compare(int, java.lang.String, int, java.lang.String) */ public List compare(int srcVersion, String srcPath, int dstVersion, String dstPath, NameMatcher excluder) { - return fTransport.compare(ClientTicketHolder.GetTicket(), srcVersion, srcPath, dstVersion, dstPath, excluder); + return fTransport.compare(fTicketHolder.getTicket(), srcVersion, srcPath, dstVersion, dstPath, excluder); } /* (non-Javadoc) @@ -50,7 +64,7 @@ public class AVMSyncServiceClient implements AVMSyncService */ public void flatten(String layerPath, String underlyingPath) { - fTransport.flatten(ClientTicketHolder.GetTicket(), layerPath, underlyingPath); + fTransport.flatten(fTicketHolder.getTicket(), layerPath, underlyingPath); } /* (non-Javadoc) @@ -58,7 +72,7 @@ public class AVMSyncServiceClient implements AVMSyncService */ public void resetLayer(String layerPath) { - fTransport.resetLayer(ClientTicketHolder.GetTicket(), layerPath); + fTransport.resetLayer(fTicketHolder.getTicket(), layerPath); } /* (non-Javadoc) @@ -69,6 +83,6 @@ public class AVMSyncServiceClient implements AVMSyncService boolean ignoreOlder, boolean overrideConflicts, boolean overrideOlder, String tag, String description) { - fTransport.update(ClientTicketHolder.GetTicket(), diffList, excluder, ignoreConflicts, ignoreOlder, overrideConflicts, overrideOlder, tag, description); + fTransport.update(fTicketHolder.getTicket(), diffList, excluder, ignoreConflicts, ignoreOlder, overrideConflicts, overrideOlder, tag, description); } } diff --git a/source/java/org/alfresco/repo/remote/ClientTicketHolder.java b/source/java/org/alfresco/repo/remote/ClientTicketHolder.java index 5bc6ab83ee..4439f1046c 100644 --- a/source/java/org/alfresco/repo/remote/ClientTicketHolder.java +++ b/source/java/org/alfresco/repo/remote/ClientTicketHolder.java @@ -1,32 +1,18 @@ -/** - * - */ package org.alfresco.repo.remote; /** - * Remote client utility to hold an authentication ticket. + * Interface for Authentication ticket caching. * @author britt */ -public class ClientTicketHolder +public interface ClientTicketHolder { - /** - * Thread local tickets. - */ - private static String fTicket; - /** * Set the ticket. */ - public static void SetTicket(String ticket) - { - fTicket = ticket; - } + public void setTicket(String ticket); /** * Get the ticket. */ - public static String GetTicket() - { - return fTicket; - } + public String getTicket(); } diff --git a/source/java/org/alfresco/repo/remote/ClientTicketHolderGlobal.java b/source/java/org/alfresco/repo/remote/ClientTicketHolderGlobal.java new file mode 100644 index 0000000000..8342443c86 --- /dev/null +++ b/source/java/org/alfresco/repo/remote/ClientTicketHolderGlobal.java @@ -0,0 +1,32 @@ +/** + * + */ +package org.alfresco.repo.remote; + +/** + * Remote client utility to hold an authentication ticket. + * @author britt + */ +public class ClientTicketHolderGlobal implements ClientTicketHolder +{ + /** + * Thread local tickets. + */ + private String fTicket; + + /* (non-Javadoc) + * @see org.alfresco.repo.remote.ClientTicketHolder#setTicket(java.lang.String) + */ + public void setTicket(String ticket) + { + fTicket = ticket; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.remote.ClientTicketHolder#getTicket() + */ + public String getTicket() + { + return fTicket; + } +} diff --git a/source/java/org/alfresco/repo/remote/ClientTicketHolderThread.java b/source/java/org/alfresco/repo/remote/ClientTicketHolderThread.java new file mode 100644 index 0000000000..7b36e191b4 --- /dev/null +++ b/source/java/org/alfresco/repo/remote/ClientTicketHolderThread.java @@ -0,0 +1,34 @@ +package org.alfresco.repo.remote; + +/** + * A Ticket holder that holds a ticket per thread. + * @author britt + */ +public class ClientTicketHolderThread implements ClientTicketHolder +{ + /** + * The Thread Local storage for tickets. + */ + private ThreadLocal fTicket; + + public ClientTicketHolderThread() + { + fTicket = new ThreadLocal(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.remote.ClientTicketHolder#getTicket() + */ + public String getTicket() + { + return fTicket.get(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.remote.ClientTicketHolder#setTicket(java.lang.String) + */ + public void setTicket(String ticket) + { + fTicket.set(ticket); + } +} diff --git a/source/java/org/alfresco/repo/remote/ReauthenticatingAdvice.java b/source/java/org/alfresco/repo/remote/ReauthenticatingAdvice.java index 898d07c993..1a66165abc 100644 --- a/source/java/org/alfresco/repo/remote/ReauthenticatingAdvice.java +++ b/source/java/org/alfresco/repo/remote/ReauthenticatingAdvice.java @@ -21,6 +21,11 @@ public class ReauthenticatingAdvice implements MethodInterceptor */ private AuthenticationService fAuthService; + /** + * The ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * The user name. */ @@ -52,6 +57,14 @@ public class ReauthenticatingAdvice implements MethodInterceptor fAuthService = service; } + /** + * Setter. + */ + public void setClientTicketHolder(ClientTicketHolder ticketHolder) + { + fTicketHolder = ticketHolder; + } + /** * Setter. */ @@ -104,7 +117,7 @@ public class ReauthenticatingAdvice implements MethodInterceptor // Reauthenticate. fAuthService.authenticate(fUser, fPassword.toCharArray()); String ticket = fAuthService.getCurrentTicket(); - ClientTicketHolder.SetTicket(ticket); + fTicketHolder.setTicket(ticket); // Modify the ticket argument. mi.getArguments()[0] = ticket; } diff --git a/source/java/org/alfresco/repo/remote/RepoRemoteImpl.java b/source/java/org/alfresco/repo/remote/RepoRemoteImpl.java index 8bd6817833..c5c8f0f2c2 100644 --- a/source/java/org/alfresco/repo/remote/RepoRemoteImpl.java +++ b/source/java/org/alfresco/repo/remote/RepoRemoteImpl.java @@ -23,6 +23,11 @@ public class RepoRemoteImpl implements RepoRemote */ private RepoRemoteTransport fTransport; + /** + * The ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * Default constructor. */ @@ -38,12 +43,21 @@ public class RepoRemoteImpl implements RepoRemote fTransport = transport; } + /** + * Setter. + * @param ticketHolder To set. + */ + public void setClientTicketHolder(ClientTicketHolder ticketHolder) + { + fTicketHolder = ticketHolder; + } + /* (non-Javadoc) * @see org.alfresco.service.cmr.remote.RepoRemote#createDirectory(org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ public NodeRef createDirectory(NodeRef base, String path) { - return fTransport.createDirectory(ClientTicketHolder.GetTicket(), base, path); + return fTransport.createDirectory(fTicketHolder.getTicket(), base, path); } /* (non-Javadoc) @@ -51,8 +65,8 @@ public class RepoRemoteImpl implements RepoRemote */ public OutputStream createFile(NodeRef base, String path) { - return new RepoRemoteOutputStream(fTransport.createFile(ClientTicketHolder.GetTicket(), base, path), - fTransport); + return new RepoRemoteOutputStream(fTransport.createFile(fTicketHolder.getTicket(), base, path), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -60,7 +74,7 @@ public class RepoRemoteImpl implements RepoRemote */ public Map> getListing(NodeRef dir) { - return fTransport.getListing(ClientTicketHolder.GetTicket(), dir); + return fTransport.getListing(fTicketHolder.getTicket(), dir); } /* (non-Javadoc) @@ -68,7 +82,7 @@ public class RepoRemoteImpl implements RepoRemote */ public NodeRef getRoot() { - return fTransport.getRoot(ClientTicketHolder.GetTicket()); + return fTransport.getRoot(fTicketHolder.getTicket()); } /* (non-Javadoc) @@ -76,7 +90,7 @@ public class RepoRemoteImpl implements RepoRemote */ public Pair lookup(NodeRef base, String path) { - return fTransport.lookup(ClientTicketHolder.GetTicket(), base, path); + return fTransport.lookup(fTicketHolder.getTicket(), base, path); } /* (non-Javadoc) @@ -84,8 +98,8 @@ public class RepoRemoteImpl implements RepoRemote */ public InputStream readFile(NodeRef fileRef) { - return new RepoRemoteInputStream(fTransport.readFile(ClientTicketHolder.GetTicket(), fileRef), - fTransport); + return new RepoRemoteInputStream(fTransport.readFile(fTicketHolder.getTicket(), fileRef), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -93,8 +107,8 @@ public class RepoRemoteImpl implements RepoRemote */ public InputStream readFile(NodeRef base, String path) { - return new RepoRemoteInputStream(fTransport.readFile(ClientTicketHolder.GetTicket(), base, path), - fTransport); + return new RepoRemoteInputStream(fTransport.readFile(fTicketHolder.getTicket(), base, path), + fTransport, fTicketHolder); } /* (non-Javadoc) @@ -102,7 +116,7 @@ public class RepoRemoteImpl implements RepoRemote */ public void removeNode(NodeRef toRemove) { - fTransport.removeNode(ClientTicketHolder.GetTicket(), toRemove); + fTransport.removeNode(fTicketHolder.getTicket(), toRemove); } /* (non-Javadoc) @@ -110,7 +124,7 @@ public class RepoRemoteImpl implements RepoRemote */ public void removeNode(NodeRef base, String path) { - fTransport.removeNode(ClientTicketHolder.GetTicket(), base, path); + fTransport.removeNode(fTicketHolder.getTicket(), base, path); } /* (non-Javadoc) @@ -118,7 +132,7 @@ public class RepoRemoteImpl implements RepoRemote */ public void rename(NodeRef base, String src, String dst) { - fTransport.rename(ClientTicketHolder.GetTicket(), base, src, dst); + fTransport.rename(fTicketHolder.getTicket(), base, src, dst); } /* (non-Javadoc) @@ -126,7 +140,7 @@ public class RepoRemoteImpl implements RepoRemote */ public OutputStream writeFile(NodeRef base, String path) { - return new RepoRemoteOutputStream(fTransport.writeFile(ClientTicketHolder.GetTicket(), base, path), - fTransport); + return new RepoRemoteOutputStream(fTransport.writeFile(fTicketHolder.getTicket(), base, path), + fTransport, fTicketHolder); } } diff --git a/source/java/org/alfresco/repo/remote/RepoRemoteInputStream.java b/source/java/org/alfresco/repo/remote/RepoRemoteInputStream.java index 1b9f576bc7..a2c01a334b 100644 --- a/source/java/org/alfresco/repo/remote/RepoRemoteInputStream.java +++ b/source/java/org/alfresco/repo/remote/RepoRemoteInputStream.java @@ -20,6 +20,11 @@ public class RepoRemoteInputStream extends InputStream */ private RepoRemoteTransport fRepoRemote; + /** + * The ticket holder. + */ + private ClientTicketHolder fTicketHolder; + /** * The handle to the input stream. */ @@ -30,10 +35,12 @@ public class RepoRemoteInputStream extends InputStream * @param handle The handle returned by getInputStream(); * @param remote The AVMRemote instance. */ - public RepoRemoteInputStream(String handle, RepoRemoteTransport remote) + public RepoRemoteInputStream(String handle, RepoRemoteTransport remote, + ClientTicketHolder ticketHolder) { fHandle = handle; fRepoRemote = remote; + fTicketHolder = ticketHolder; } /** @@ -45,7 +52,7 @@ public class RepoRemoteInputStream extends InputStream { try { - byte [] buff = fRepoRemote.readInput(ClientTicketHolder.GetTicket(), fHandle, 1); + byte [] buff = fRepoRemote.readInput(fTicketHolder.getTicket(), fHandle, 1); if (buff.length == 0) { return -1; @@ -70,7 +77,7 @@ public class RepoRemoteInputStream extends InputStream { try { - byte [] buff = fRepoRemote.readInput(ClientTicketHolder.GetTicket(), fHandle, len); + byte [] buff = fRepoRemote.readInput(fTicketHolder.getTicket(), fHandle, len); if (buff.length == 0) { return -1; @@ -92,7 +99,7 @@ public class RepoRemoteInputStream extends InputStream { try { - fRepoRemote.closeInputHandle(ClientTicketHolder.GetTicket(), fHandle); + fRepoRemote.closeInputHandle(fTicketHolder.getTicket(), fHandle); } catch (Exception e) { diff --git a/source/java/org/alfresco/repo/remote/RepoRemoteOutputStream.java b/source/java/org/alfresco/repo/remote/RepoRemoteOutputStream.java index 8a63ceb716..851f72527d 100644 --- a/source/java/org/alfresco/repo/remote/RepoRemoteOutputStream.java +++ b/source/java/org/alfresco/repo/remote/RepoRemoteOutputStream.java @@ -19,15 +19,19 @@ public class RepoRemoteOutputStream extends OutputStream private String fHandle; + private ClientTicketHolder fTicketHolder; + /** * Create a new one. * @param handle The handle returned from an RepoRemoteTransport call. * @param remote The AVMRemote instance. */ - public RepoRemoteOutputStream(String handle, RepoRemoteTransport remote) + public RepoRemoteOutputStream(String handle, RepoRemoteTransport remote, + ClientTicketHolder ticketHolder) { fRepoRemote = remote; fHandle = handle; + fTicketHolder = ticketHolder; } /** @@ -52,7 +56,7 @@ public class RepoRemoteOutputStream extends OutputStream { try { - fRepoRemote.closeOutputHandle(ClientTicketHolder.GetTicket(), fHandle); + fRepoRemote.closeOutputHandle(fTicketHolder.getTicket(), fHandle); } catch (Exception e) { @@ -74,13 +78,13 @@ public class RepoRemoteOutputStream extends OutputStream { if (off == 0) { - fRepoRemote.writeOutput(ClientTicketHolder.GetTicket(), fHandle, b, len); + fRepoRemote.writeOutput(fTicketHolder.getTicket(), fHandle, b, len); } else { byte [] buff = new byte[len]; System.arraycopy(b, off, buff, 0, len); - fRepoRemote.writeOutput(ClientTicketHolder.GetTicket(), fHandle, buff, len); + fRepoRemote.writeOutput(fTicketHolder.getTicket(), fHandle, buff, len); } } catch (Exception e) diff --git a/source/java/org/alfresco/service/cmr/avm/AVMNodeDescriptor.java b/source/java/org/alfresco/service/cmr/avm/AVMNodeDescriptor.java index 02f4b29111..5bb8fa0a5a 100644 --- a/source/java/org/alfresco/service/cmr/avm/AVMNodeDescriptor.java +++ b/source/java/org/alfresco/service/cmr/avm/AVMNodeDescriptor.java @@ -124,6 +124,11 @@ public class AVMNodeDescriptor implements Serializable */ private int fDeletedType; + /** + * The GUID for the node. + */ + private String fGuid; + /** * Make one up. * @param path The looked up path. @@ -136,6 +141,7 @@ public class AVMNodeDescriptor implements Serializable * @param accessDate The access date. * @param id The object id. * @param versionID The version id. + * @param guid The GUID. * @param indirection The indirection. * @param isPrimary Whether this is a primary indirection. * @param layerID The layer id. @@ -152,6 +158,7 @@ public class AVMNodeDescriptor implements Serializable long modDate, long accessDate, long id, + String guid, int versionID, String indirection, boolean isPrimary, @@ -170,6 +177,7 @@ public class AVMNodeDescriptor implements Serializable fModDate = modDate; fAccessDate = accessDate; fID = id; + fGuid = guid; fVersionID = versionID; fIndirection = indirection; fIsPrimary = isPrimary; @@ -485,4 +493,12 @@ public class AVMNodeDescriptor implements Serializable (fDeletedType == AVMNodeType.LAYERED_FILE || fDeletedType == AVMNodeType.PLAIN_FILE); } + + /** + * Get the GUID for the node. + */ + public String getGuid() + { + return fGuid; + } } diff --git a/source/java/org/alfresco/service/cmr/avm/AVMService.java b/source/java/org/alfresco/service/cmr/avm/AVMService.java index 504710fa06..fc214d8462 100644 --- a/source/java/org/alfresco/service/cmr/avm/AVMService.java +++ b/source/java/org/alfresco/service/cmr/avm/AVMService.java @@ -1209,4 +1209,12 @@ public interface AVMService * @throws AVMNotFoundException */ public void revert(String path, AVMNodeDescriptor toRevertTo); + + /** + * Set the GUID on a node. The GUID of a node uniquely identifies + * the state of a node, i.e. its content, metadata, and aspects. + * @param path The path to the node. + * @param guid The GUID to set. + */ + public void setGuid(String path, String guid); } diff --git a/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentCallback.java b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentCallback.java new file mode 100644 index 0000000000..791ff60a0a --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentCallback.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.service.cmr.avm.deploy; + +/** + * Callback interface for deployments. + * @author britt + */ +public interface DeploymentCallback +{ + /** + * Called each time something happens during deployment. + * This is called synchronously by the deployer and should + * therefore be handled rapidly, if possible. + * @param event The event that occurred. + */ + public void eventOccurred(DeploymentEvent event); +} diff --git a/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentEvent.java b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentEvent.java new file mode 100644 index 0000000000..9ac3d06ac5 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentEvent.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ + +package org.alfresco.service.cmr.avm.deploy; + +import java.io.Serializable; + +import org.alfresco.util.Pair; + +/** + * Interface for Deployment Events. + * @author britt + */ +public class DeploymentEvent implements Serializable +{ + private static final long serialVersionUID = 2696116904379321786L; + + /** + * The type of the event. + * @author britt + */ + public static enum Type implements Serializable + { + COPIED, // Copied a source node that did not exist on the destination. + UPDATED, // Overwrote the destination. + DELETED, // Deleted the destination node. + START, // A Deployment has begun. + END // A Deployment has ended. + }; + + private Type fType; + + private Pair fSource; + + private String fDestination; + + public DeploymentEvent(Type type, Pair source, String destination) + { + fType = type; + fSource = source; + fDestination = destination; + } + + /** + * Get the type of the event. + * @return The type. + */ + public Type getType() + { + return fType; + } + + /** + * Get the source node version and path. + * @return + */ + public Pair getSource() + { + return fSource; + } + + /** + * Get the destination path. + * @return + */ + public String getDestination() + { + return fDestination; + } + + /** + * Get a String representation. + */ + public String toString() + { + return fType + ": " + fSource + " -> " + fDestination; + } +} diff --git a/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentReport.java b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentReport.java new file mode 100644 index 0000000000..a131b821e9 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentReport.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ + +package org.alfresco.service.cmr.avm.deploy; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A value class that contains the results of a deployment run. + * @author britt + */ +public class DeploymentReport implements Serializable, Iterable +{ + private static final long serialVersionUID = 5528250199836250533L; + + private List fEvents; + + public DeploymentReport() + { + fEvents = new ArrayList(); + } + + /** + * Get a String representation. + */ + public String toString() + { + StringBuilder builder = new StringBuilder(); + for (DeploymentEvent event : fEvents) + { + builder.append(event.toString()); + builder.append('\n'); + } + return builder.toString(); + } + + /** + * Add an event. + * @param event + */ + public void add(DeploymentEvent event) + { + fEvents.add(event); + } + + /* (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() + { + return fEvents.iterator(); + } +} diff --git a/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentService.java b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentService.java new file mode 100644 index 0000000000..7e31ecbf26 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/deploy/DeploymentService.java @@ -0,0 +1,58 @@ +/** + * + */ +package org.alfresco.service.cmr.avm.deploy; + +/** + * A service to handle AVM repository to remote AVM repository deployment. + * @author britt + */ +public interface DeploymentService +{ + /** + * Deploys the differences between what is is the local source path + * and a destination machine's path. + * @param version The local version. + * @param srcPath The local path. + * @param hostName The remote hostname. + * @param port The remote rmi registry port. + * @param userName The username for authentication. + * @param password The password for authentication. + * @param dstPath The destination path corresponding to source path. + * @param createDst Flag for whether a missing destination should be created. + * @param dontDelete Don't delete assets at the destination. + * @param dontDo If this is set then this is a dry run. + * @param callback A possibly null callback. + */ + public DeploymentReport deployDifference(int version, String srcPath, + String hostName, int port, + String userName, String password, + String dstPath, + boolean createDst, + boolean dontDelete, + boolean dontDo, + DeploymentCallback callback); + + /** + * Deploy to a filesystem on another machine. + * @param version The version to deploy from. + * @param srcPath The path to deploy from. + * @param hostName The hostname of the filesystem receiver. + * @param port The port to connect to. + * @param userName The username for authentication + * @param password The password for authentication + * @param dstPath The destination path. + * @param createDst Flag for whether a missing destination should be created. + * @param dontDelete Don't delete deleted nodes from destination. + * @param dontDo If this is set, this is a dry run. + * @param callback A possibly null callback. + */ + public DeploymentReport deployDifferenceFS(int version, String srcPath, + String hostName, int port, + String userName, String password, + String dstPath, + boolean createDst, + boolean dontDelete, + boolean dontDo, + DeploymentCallback callback); +} diff --git a/source/java/org/alfresco/service/cmr/remote/AVMRemote.java b/source/java/org/alfresco/service/cmr/remote/AVMRemote.java index bcf8d7c768..1fbafebd6c 100644 --- a/source/java/org/alfresco/service/cmr/remote/AVMRemote.java +++ b/source/java/org/alfresco/service/cmr/remote/AVMRemote.java @@ -468,4 +468,11 @@ public interface AVMRemote * @throws AVMNotFoundException */ public Pair getAPath(AVMNodeDescriptor desc); + + /** + * Set the GUID of a node. + * @param path The path to the node. + * @param guid The GUID. + */ + public void setGuid(String path, String guid); } diff --git a/source/java/org/alfresco/service/cmr/remote/AVMRemoteTransport.java b/source/java/org/alfresco/service/cmr/remote/AVMRemoteTransport.java index 6e0069889e..6e1eb5a7b3 100644 --- a/source/java/org/alfresco/service/cmr/remote/AVMRemoteTransport.java +++ b/source/java/org/alfresco/service/cmr/remote/AVMRemoteTransport.java @@ -480,4 +480,12 @@ public interface AVMRemoteTransport * @return version and path. */ public Pair getAPath(String ticket, AVMNodeDescriptor desc); + + /** + * Set the GUID on a node. + * @param ticket The authentication ticket. + * @param path The path to the node. + * @param guid The GUID to set. + */ + public void setGuid(String ticket, String path, String guid); }