Merged V3.2 to HEAD

17905 : ETHREEOH-3809 - WCM - First test server deploy fails.
    - added yet another transaction to read the previous snapshot transaction.
    - added a new system test based upon the WCM services.    The beginnings of testing against layered authored sandboxes.
  18370 : ETHREEOH-4045 - Web Deployed space appears even when there is no Web Projects space
    - moved the patch to the wcm bootstrap.
  18373 : show storeNamePattern property on avm-target.xml
  18434 : ETHREEOH-4032 - Warning "Type not found: {http://www.alfresco.org/model/workflow/1.0}inviteToSiteTask" appears during upgrade
  18616 : ETHREEOH-4181 - Access denied exception when deploying via avm deployment receiver
  18694 : change to comment in deployment.properties
  18701 : Merge DEV_TEMPORARY to V3.2
    18693 : ETHREEOH-4182: ASR deployer fails to set the contentUrl of documents on the target system
               - Merged in fix related to closing output streams.
               - Increased coverage of unit test.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18704 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Mark Rogers
2010-02-18 15:26:52 +00:00
parent b53f50865e
commit 74aa6b71fb
4 changed files with 379 additions and 44 deletions

View File

@@ -131,6 +131,51 @@
</mandatory-aspects>
</type>
<!-- Deprecated workflow task from Alfresco 3.0 -->
<!-- Needs to be defined for patch.InvitationMigration which gets rid of it. -->
<type name="wf:inviteToSiteTask">
<parent>bpm:startTask</parent>
<properties>
<property name="wf:serverPath">
<type>d:text</type>
</property>
<property name="wf:acceptUrl">
<type>d:text</type>
</property>
<property name="wf:rejectUrl">
<type>d:text</type>
</property>
<property name="wf:inviteTicket">
<type>d:text</type>
</property>
<property name="wf:inviterUserName">
<type>d:text</type>
</property>
<property name="wf:inviteeUserName">
<type>d:text</type>
</property>
<property name="wf:inviteeFirstName">
<type>d:text</type>
</property>
<property name="wf:inviteeLastName">
<type>d:text</type>
</property>
<property name="wf:inviteeGenPassword">
<type>d:text</type>
</property>
<property name="wf:siteShortName">
<type>d:text</type>
</property>
<property name="wf:inviteeSiteRole">
<type>d:text</type>
</property>
</properties>
<mandatory-aspects>
<aspect>bpm:assignee</aspect>
</mandatory-aspects>
</type>
</types>
<aspects>

View File

@@ -25,17 +25,13 @@
package org.alfresco.repo.deploy;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.repo.avm.AVMServiceTestBase;
import org.alfresco.repo.avm.util.BulkLoader;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.cmr.avm.AVMException;
@@ -49,10 +45,7 @@ import org.alfresco.service.cmr.avm.deploy.DeploymentService;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Deleter;
import org.alfresco.util.NameMatcher;
import java.util.Map;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* End to end test of deployment to an alfresco system receiver (ASR).
@@ -99,6 +92,16 @@ public class ASRDeploymentTest extends AVMServiceTestBase
* set up our test tree
*/
fService.createDirectory("main:/", "a");
String rootText = "Angel is an American television series, a spin-off of the television series Buffy the Vampire Slayer. The series was created by Buffy's creator, Joss Whedon, in collaboration with David Greenwalt, and first aired on October 5, 1999. Like Buffy, it was produced by Whedon's production company, Mutant Enemy.";
fService.createFile("main:/", "rootFile").close();
ContentWriter writer = fService.getContentWriter("main:/rootFile");
// Force a conversion
writer.setEncoding("UTF-16");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent(rootText);
fService.createDirectory("main:/a", "b");
fService.createDirectory("main:/a/b", "c");
fService.createDirectory("main:/", "d");
@@ -107,7 +110,7 @@ public class ASRDeploymentTest extends AVMServiceTestBase
fService.createFile("main:/a/b/c", "foo").close();
String fooText="I am main:/a/b/c/foo";
ContentWriter writer = fService.getContentWriter("main:/a/b/c/foo");
writer = fService.getContentWriter("main:/a/b/c/foo");
writer.setEncoding("UTF-8");
writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);
writer.putContent("I am main:/a/b/c/foo");
@@ -146,8 +149,9 @@ public class ASRDeploymentTest extends AVMServiceTestBase
// validate the deployment report
assertTrue("first deployment no start", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.START, null, destRef)));
assertTrue("first deployment no finish", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.END, null, destRef)));
assertTrue("first deployment wrong size", firstDeployment.size() == 11);
assertTrue("first deployment wrong size", firstDeployment.size() == 12);
assertTrue("Update missing: /a", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.CREATED, null, destRef + "/a")));
assertTrue("Update missing: /rootFile", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.CREATED, null, destRef + "/rootFile")));
assertTrue("Update missing: /a/b", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.CREATED, null, destRef + "/a/b")));
assertTrue("Update missing: /a/b/c", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.CREATED, null, destRef + "/a/b/c")));
assertTrue("Update missing: /d/e", firstDeployment.contains(new DeploymentEvent(DeploymentEvent.Type.CREATED, null, destRef + "/d/e")));
@@ -158,12 +162,12 @@ public class ASRDeploymentTest extends AVMServiceTestBase
// Check that files exist in the destination AVM Store
{
// fService.getNodeProperties(-1, destRef + "/a");
//
// Map<QName, PropertyValue> props = fService.getNodeProperties(-1, destRef + "/a/b/buffy");
// ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
// assertNotNull("content reader is null", reader);
// assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
fService.getNodeProperties(-1, destRef + "/a");
Map<QName, PropertyValue> props = fService.getNodeProperties(-1, destRef + "/a/b/buffy");
ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
assertNotNull("content reader is null", reader);
assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
}
/**
@@ -200,11 +204,10 @@ public class ASRDeploymentTest extends AVMServiceTestBase
// Check that files exist in the destination AVM Store
{
// fService.getNodeProperties(-1, destRef + "/a/b/buffy");
// ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
// assertNotNull("content reader is null", reader);
// assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
fService.getNodeProperties(-1, destRef + "/a/b/buffy");
ContentReader reader = fService.getContentReader(-1, destRef + "/a/b/buffy");
assertNotNull("content reader is null", reader);
assertTrue("UTF-16 buffy text is not correct", reader.getContentString().equals(buffyText));
}
/**

View File

@@ -535,10 +535,12 @@ public class DeploymentServiceImpl implements DeploymentService
{
InputStream in = fAVMService.getFileInputStream(src);
copyStream(in, out);
copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + src.getName()), remote);
}
finally
{
if(out != null)
{
// whatever happens close stream
try
{
out.close();
@@ -547,8 +549,10 @@ public class DeploymentServiceImpl implements DeploymentService
{
throw new AVMException("I/O Exception", e);
}
out = null;
}
}
copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + src.getName()), remote);
return;
}
@@ -597,9 +601,29 @@ public class DeploymentServiceImpl implements DeploymentService
{
return;
}
InputStream in = fAVMService.getFileInputStream(src);
OutputStream out = remote.getFileOutputStream(dst.getPath());
try
{
InputStream in = fAVMService.getFileInputStream(src);
copyStream(in, out);
}
finally
{
if(out != null)
{
// whatever happens close stream
try
{
out.close();
}
catch (IOException e)
{
throw new AVMException("I/O Exception", e);
}
}
}
copyMetadata(version, src, dst, remote);
return;
}
@@ -617,9 +641,28 @@ public class DeploymentServiceImpl implements DeploymentService
// 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());
try
{
InputStream in = fAVMService.getFileInputStream(src);
copyStream(in, out);
}
finally
{
if(out != null)
{
// whatever happens close stream
try
{
out.close();
}
catch (IOException e)
{
throw new AVMException("I/O Exception", e);
}
}
}
copyMetadata(version, src, remote.lookup(-1, dstParent.getPath() + '/' + dst.getName()), remote);
}
@@ -664,9 +707,27 @@ public class DeploymentServiceImpl implements DeploymentService
newParent.getPath() + '/' + child.getName());
processEvent(event, callbacks);
InputStream in = fAVMService.getFileInputStream(child);
OutputStream out = remote.createFile(newParent.getPath(), child.getName());
try
{
InputStream in = fAVMService.getFileInputStream(child);
copyStream(in, out);
}
finally
{
if(out != null)
{
// whatever happens close stream
try
{
out.close();
}
catch (IOException e)
{
throw new AVMException("I/O Exception", e);
}
}
}
copyMetadata(version, child, remote.lookup(-1, newParent.getPath() + '/' + child.getName()), remote);
}
else
@@ -686,6 +747,11 @@ public class DeploymentServiceImpl implements DeploymentService
/**
* Utility for copying from one stream to another.
*
* in is closed.
*
* out is not closed.
*
* @param in The input stream.
* @param out The output stream.
*/
@@ -700,6 +766,8 @@ public class DeploymentServiceImpl implements DeploymentService
out.write(buff, 0, read);
}
in.close();
//out.flush();
//out.close();
}
catch (IOException e)
{
@@ -976,14 +1044,14 @@ public class DeploymentServiceImpl implements DeploymentService
* @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 void deployDifferenceFS(int version,
String srcPath,
final String srcPath,
String adapterName,
String hostName,
int port,
String userName,
String password,
String target,
NameMatcher matcher,
final NameMatcher matcher,
boolean createDst,
boolean dontDelete,
boolean dontDo,
@@ -995,7 +1063,7 @@ public class DeploymentServiceImpl implements DeploymentService
*/
String lockStr = hostName + "." + target;
QName lockQName = QName.createQName("{org.alfresco.deployment.lock}" + lockStr);
Lock lock = new Lock(lockQName);
final Lock lock = new Lock(lockQName);
lock.makeLock();
@@ -1019,7 +1087,7 @@ public class DeploymentServiceImpl implements DeploymentService
try
{
// Kick off the event queue that will process deployment call-backs
LinkedBlockingQueue<DeploymentEvent> eventQueue = new LinkedBlockingQueue<DeploymentEvent>();
final LinkedBlockingQueue<DeploymentEvent> eventQueue = new LinkedBlockingQueue<DeploymentEvent>();
EventQueueWorker eventQueueWorker = new EventQueueWorker(currentEffectiveUser, eventQueue, callbacks);
eventQueueWorker.setName(eventQueueWorker.getClass().getName());
eventQueueWorker.setPriority(Thread.currentThread().getPriority());
@@ -1064,8 +1132,8 @@ public class DeploymentServiceImpl implements DeploymentService
// Go parallel to reduce the problems of high network latency
LinkedBlockingQueue<DeploymentWork> sendQueue = new LinkedBlockingQueue<DeploymentWork>();
List<Exception> errors = Collections.synchronizedList(new ArrayList<Exception>());
final LinkedBlockingQueue<DeploymentWork> sendQueue = new LinkedBlockingQueue<DeploymentWork>();
final List<Exception> errors = Collections.synchronizedList(new ArrayList<Exception>());
SendQueueWorker[] workers = new SendQueueWorker[numberOfSendingThreads];
for(int i = 0; i < numberOfSendingThreads; i++)
@@ -1084,7 +1152,23 @@ public class DeploymentServiceImpl implements DeploymentService
{
DeploymentToken token = service.begin(target, storeName, version, userName, password.toCharArray());
ticket = token.getTicket();
deployDirectoryPushFSR(service, ticket, version, srcPath, "/", matcher, eventQueue, sendQueue, errors, lock);
// run this in its own txn
final DeploymentReceiverService fservice = service;
final String fTicket = ticket;
final int fVersion = version;
RetryingTransactionCallback<Integer> pushFSR = new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
deployDirectoryPushFSR(fservice, fTicket, fVersion, srcPath, "/", matcher, eventQueue, sendQueue, errors, lock);
return 0;
}
};
RetryingTransactionHelper trn = trxService.getRetryingTransactionHelper();
trn.doInTransaction(pushFSR, false, true);
}
catch (Exception e)
{

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2005-2009 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.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.config.JNDIConstants;
import org.alfresco.jlan.smb.dcerpc.UUID;
import org.alfresco.repo.action.ActionImpl;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.AVMNodeType;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.deploy.DeploymentCallback;
import org.alfresco.service.cmr.avm.deploy.DeploymentReport;
import org.alfresco.service.cmr.avm.deploy.DeploymentReportCallback;
import org.alfresco.service.cmr.avm.deploy.DeploymentService;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.GUID;
import org.alfresco.util.NameMatcher;
import org.alfresco.wcm.AbstractWCMServiceImplTest;
import org.alfresco.wcm.actions.WCMSandboxRevertSnapshotAction;
import org.alfresco.wcm.actions.WCMSandboxSubmitAction;
import org.alfresco.wcm.actions.WCMSandboxUndoAction;
import org.alfresco.wcm.asset.AssetInfo;
import org.alfresco.wcm.sandbox.SandboxInfo;
import org.alfresco.wcm.util.WCMUtil;
import org.alfresco.wcm.webproject.WebProjectInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
/**
* Test of deployment to a Test Server.
*
* Through the WCM application rather than directly through AVM.
*
* @author Mark Rogers
*/
public class DeploymentServiceTest extends AbstractWCMServiceImplTest
{
private static Log logger = LogFactory.getLog(DeploymentServiceTest.class);
// base sandbox
private static final String TEST_SANDBOX = TEST_WEBPROJ_DNS+"-sandbox";
private static final int SCALE_USERS = 5;
private static final int SCALE_WEBPROJECTS = 2;
//
// services
//
private AVMService avmService; // non-locking-aware
private DeploymentService deploymentService = null;
private NameMatcher matcher = null;
private File log = null;
private File metadata = null;
private File data = null;
private File target = null;
@Override
protected void setUp() throws Exception
{
super.setUp();
// Get the required services
avmService = (AVMService)ctx.getBean("AVMService");
deploymentService = (DeploymentService)ctx.getBean("DeploymentService");
NameMatcher matcher = (NameMatcher)ctx.getBean("globalPathExcluder");
super.setUp();
log = new File("deplog");
log.mkdir();
metadata = new File("depmetadata");
metadata.mkdir();
data = new File("depdata");
data.mkdir();
target = new File("sampleTarget");
target.mkdir();
/**
* Start the FSR
*/
@SuppressWarnings("unused")
FileSystemXmlApplicationContext receiverContext =
new FileSystemXmlApplicationContext("../deployment/config/application-context.xml");
}
@Override
protected void tearDown() throws Exception
{
if (CLEAN)
{
// Switch back to Admin
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
deleteUser(USER_ONE);
deleteUser(USER_TWO);
deleteUser(USER_THREE);
deleteUser(USER_FOUR);
}
super.tearDown();
}
private String TEST_USER = "Giles";
private String TEST_PASSWORD = "Watcher";
private String TEST_TARGET = "sampleTarget";
public void testSimple() throws Exception
{
int storeCnt = avmService.getStores().size();
String projectName = "DeploymentServiceTestSimple";
// create web project (also creates staging sandbox and admin's author sandbox)
WebProjectInfo wpInfo = wpService.createWebProject(projectName, projectName, TEST_WEBPROJ_TITLE, TEST_WEBPROJ_DESCRIPTION, TEST_WEBPROJ_DEFAULT_WEBAPP, TEST_WEBPROJ_DONT_USE_AS_TEMPLATE, null);
String wpStoreId = wpInfo.getStoreId();
// list 2 sandboxes
assertEquals(2, sbService.listSandboxes(wpStoreId).size());
// list 4 extra AVM stores (2 per sandbox)
assertEquals(storeCnt+4, avmService.getStores().size()); // 2x stating (main,preview), 2x admin author (main, preview)
// get admin's sandbox
SandboxInfo authorInfo = sbService.getAuthorSandbox(wpStoreId);
assertNotNull(authorInfo);
// get staging sandbox
SandboxInfo stagingInfo = sbService.getStagingSandbox(wpStoreId);
assertNotNull(stagingInfo);
DeploymentReport report = new DeploymentReport();
List<DeploymentCallback> callbacks = new ArrayList<DeploymentCallback>();
callbacks.add(new DeploymentReportCallback(report));
/**
* Test Server Admin Sandbox Webapps
*/
String srcPath = projectName + "--admin:/www/avm_webapps";
deploymentService.deployDifferenceFS(-1, srcPath, "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, matcher, false, false, false, callbacks);
/**
* Test Server Admin Sandbox ROOT Webapp
*/
assetService.createFolder(authorInfo.getSandboxId(), "/", "hello", null);
srcPath = projectName + "--admin:/www/avm_webapps/ROOT";
deploymentService.deployDifferenceFS(-1, srcPath, "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, matcher, false, false, false, callbacks);
/**
* Live Server - Staging ROOT
*/
srcPath = projectName + ":/www/avm_webapps/ROOT";
deploymentService.deployDifferenceFS(-1, srcPath, "default", "localhost", 44100, TEST_USER, TEST_PASSWORD, TEST_TARGET, matcher, false, false, false, callbacks);
wpService.deleteWebProject(projectName);
}
}