/* * Copyright (C) 2009-2010 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.repo.transfer; import static org.mockito.Matchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.transaction.UserTransaction; import junit.framework.TestCase; import org.alfresco.model.ContentModel; import org.alfresco.repo.model.Repository; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.transfer.reportd.XMLTransferDestinationReportWriter; import org.alfresco.repo.transfer.requisite.XMLTransferRequsiteWriter; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.transfer.TransferCallback; import org.alfresco.service.cmr.transfer.TransferDefinition; import org.alfresco.service.cmr.transfer.TransferEvent; import org.alfresco.service.cmr.transfer.TransferEventBegin; import org.alfresco.service.cmr.transfer.TransferEventCommittingStatus; import org.alfresco.service.cmr.transfer.TransferEventEndState; import org.alfresco.service.cmr.transfer.TransferEventEnterState; import org.alfresco.service.cmr.transfer.TransferEventError; import org.alfresco.service.cmr.transfer.TransferEventReport; import org.alfresco.service.cmr.transfer.TransferEventSendingContent; import org.alfresco.service.cmr.transfer.TransferEventSendingSnapshot; import org.alfresco.service.cmr.transfer.TransferEventSuccess; import org.alfresco.service.cmr.transfer.TransferException; import org.alfresco.service.cmr.transfer.TransferFailureException; import org.alfresco.service.cmr.transfer.TransferProgress; import org.alfresco.service.cmr.transfer.TransferService2; import org.alfresco.service.cmr.transfer.TransferTarget; import org.alfresco.service.cmr.transfer.TransferEvent.TransferState; import org.alfresco.service.cmr.transfer.TransferProgress.Status; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.ApplicationContextHelper; import org.alfresco.util.GUID; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.context.ApplicationContext; public class TransferServiceCallbackTest extends TestCase { // private static Log log = LogFactory.getLog(TransferServiceImplUnitTest.class); private static final String TRANSFER_TARGET_NAME = "TransferServiceImplUnitTest"; private ApplicationContext applicationContext; private TransferServiceImpl2 transferServiceImpl; private AuthenticationComponent authenticationComponent; private TransferTransmitter mockedTransferTransmitter; private TransferService2 transferService; private TransactionService transactionService; private UserTransaction tx; private Repository repository; private NodeRef companyHome; private FileFolderService fileFolderService; private NodeRef folder1; private NodeRef file1; private NodeRef file2; private NodeRef file3; private String file1ContentUrl; private String file2ContentUrl; private String file3ContentUrl; private TransferTarget target; private Transfer transfer; private TransferCallback mockedCallback; @Override protected void setUp() throws Exception { applicationContext = ApplicationContextHelper.getApplicationContext(); // Get the required services transferServiceImpl = (TransferServiceImpl2) this.applicationContext.getBean("transferService2"); transferService = transferServiceImpl; authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent"); transactionService = (TransactionService) applicationContext.getBean("transactionComponent"); repository = (Repository) applicationContext.getBean("repositoryHelper"); fileFolderService = (FileFolderService) applicationContext.getBean("fileFolderService"); mockedTransferTransmitter = mock(TransferTransmitter.class); mockedCallback = mock(TransferCallback.class); transferServiceImpl.setTransmitter(mockedTransferTransmitter); authenticationComponent.setCurrentUser("admin"); tx = transactionService.getUserTransaction(); tx.begin(); target = createTransferTarget(TRANSFER_TARGET_NAME); tx.commit(); tx = transactionService.getUserTransaction(); tx.begin(); transfer = new Transfer(); transfer.setTransferTarget(target); transfer.setTransferId(GUID.generate()); companyHome = repository.getCompanyHome(); folder1 = fileFolderService.create(companyHome, "folder1", ContentModel.TYPE_FOLDER).getNodeRef(); file1 = fileFolderService.create(folder1, "file1", ContentModel.TYPE_CONTENT).getNodeRef(); fileFolderService.getWriter(file1).putContent("This is purely test content."); file1ContentUrl = fileFolderService.getFileInfo(file1).getContentData().getContentUrl(); file2 = fileFolderService.create(folder1, "file2", ContentModel.TYPE_CONTENT).getNodeRef(); fileFolderService.getWriter(file2).putContent("This is purely test content."); file2ContentUrl = fileFolderService.getFileInfo(file2).getContentData().getContentUrl(); file3 = fileFolderService.create(folder1, "file3", ContentModel.TYPE_CONTENT).getNodeRef(); fileFolderService.getWriter(file3).putContent("This is purely test content."); file3ContentUrl = fileFolderService.getFileInfo(file3).getContentData().getContentUrl(); } @Override protected void tearDown() throws Exception { if (tx.getStatus() == javax.transaction.Status.STATUS_ACTIVE) { tx.rollback(); } authenticationComponent.clearCurrentSecurityContext(); super.tearDown(); } public void testCompleteSuccess() { TransferProgress status0 = new TransferProgress(); status0.setStatus(Status.COMMIT_REQUESTED); status0.setCurrentPosition(0); status0.setEndPosition(0); TransferProgress status1 = new TransferProgress(); status1.setStatus(Status.COMMITTING); status1.setCurrentPosition(0); status1.setEndPosition(4); TransferProgress status2 = new TransferProgress(); status2.setStatus(Status.COMMITTING); status2.setCurrentPosition(3); status2.setEndPosition(4); TransferProgress status3 = new TransferProgress(); status3.setStatus(Status.COMMITTING); status3.setCurrentPosition(5); status3.setEndPosition(8); TransferProgress status4 = new TransferProgress(); status4.setStatus(Status.COMPLETE); status4.setCurrentPosition(8); status4.setEndPosition(8); TransferProgress[] statuses = new TransferProgress[] {status0, status1, status2, status3, status4}; configureBasicMockTransmitter(statuses); when(mockedTransferTransmitter.begin(target)).thenReturn(transfer); TransferDefinition transferDef = new TransferDefinition(); transferDef.setNodes(folder1, file1, file2, file3); transferService.transfer(TRANSFER_TARGET_NAME, transferDef, mockedCallback); List expectedEvents = new ArrayList(); TransferEventImpl event; event = new TransferEventEnterState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventBegin(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventSendingSnapshot(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.PREPARING); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.PREPARING); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.SUCCESS); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.SUCCESS); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.SUCCESS); expectedEvents.add(event); event = new TransferEventSuccess(); event.setTransferState(TransferState.SUCCESS); expectedEvents.add(event); verifyCallback(expectedEvents); } public void testErrorDuringCommit() { Exception error = new TransferException("Commit failed"); TransferProgress status0 = new TransferProgress(); status0.setStatus(Status.COMMIT_REQUESTED); status0.setCurrentPosition(0); status0.setEndPosition(0); TransferProgress status1 = new TransferProgress(); status1.setStatus(Status.COMMITTING); status1.setCurrentPosition(0); status1.setEndPosition(4); TransferProgress status2 = new TransferProgress(); status2.setStatus(Status.COMMITTING); status2.setCurrentPosition(3); status2.setEndPosition(4); TransferProgress status3 = new TransferProgress(); status3.setStatus(Status.COMMITTING); status3.setCurrentPosition(5); status3.setEndPosition(8); TransferProgress status4 = new TransferProgress(); status4.setStatus(Status.ERROR); status4.setCurrentPosition(8); status4.setEndPosition(8); status4.setError(error); TransferProgress[] statuses = new TransferProgress[] {status0, status1, status2, status3, status4}; configureBasicMockTransmitter(statuses); when(mockedTransferTransmitter.begin(target)).thenReturn(transfer); TransferDefinition transferDef = new TransferDefinition(); transferDef.setNodes(folder1, file1, file2, file3); try { transferService.transfer(TRANSFER_TARGET_NAME, transferDef, mockedCallback); fail(); } catch (TransferFailureException ex) { List expectedEvents = new ArrayList(); TransferEventImpl event; event = new TransferEventEnterState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventBegin(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventSendingSnapshot(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.SENDING_SNAPSHOT); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventSendingContent(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.SENDING_CONTENT); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.PREPARING); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.PREPARING); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventCommittingStatus(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.COMMITTING); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventError(); event.setTransferState(TransferState.ERROR); ((TransferEventError)event).setException(error); expectedEvents.add(event); verifyCallback(expectedEvents); } } public void testTargetAlreadyLocked() { configureBasicMockTransmitter(null); when(mockedTransferTransmitter.begin(target)).thenThrow(new TransferException("Simulate lock unavailable")); TransferDefinition transferDef = new TransferDefinition(); transferDef.setNodes(folder1, file1, file2, file3); try { transferService.transfer(TRANSFER_TARGET_NAME, transferDef, mockedCallback); fail("Transfer expected to throw an exception, but it didn't."); } catch(TransferFailureException ex) { List expectedEvents = new ArrayList(); TransferEventImpl event; event = new TransferEventEnterState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEndState(); event.setTransferState(TransferState.START); expectedEvents.add(event); event = new TransferEventEnterState(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventReport(); event.setTransferState(TransferState.ERROR); expectedEvents.add(event); event = new TransferEventError(); event.setTransferState(TransferState.ERROR); ((TransferEventError)event).setException((Exception)ex.getCause()); expectedEvents.add(event); verifyCallback(expectedEvents); } } private void verifyCallback(List expectedEvents) { ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(TransferEvent.class); verify(mockedCallback, atLeastOnce()).processEvent(eventCaptor.capture()); List capturedEvents = eventCaptor.getAllValues(); assertEquals(expectedEvents.size(), capturedEvents.size()); int count = capturedEvents.size(); for (int index = 0; index < count; ++index) { TransferEvent expectedEvent = expectedEvents.get(index); TransferEvent capturedEvent = capturedEvents.get(index); assertEquals("Event " + index, expectedEvent.getClass(), capturedEvent.getClass()); assertEquals("Event " + index, expectedEvent.getTransferState(), capturedEvent.getTransferState()); if (TransferEventError.class.isAssignableFrom(expectedEvent.getClass())) { assertEquals(((TransferEventError)expectedEvent).getException(), ((TransferEventError)capturedEvent).getException()); } } } private void configureBasicMockTransmitter(TransferProgress[] statuses) { doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { OutputStream os = (OutputStream)invocation.getArguments()[2]; Writer writer = new OutputStreamWriter(os); XMLTransferRequsiteWriter requisiteWriter = new XMLTransferRequsiteWriter(writer); requisiteWriter.startTransferRequsite(); requisiteWriter.missingContent(file1, ContentModel.PROP_CONTENT, TransferCommons.URLToPartName(file1ContentUrl)); requisiteWriter.missingContent(file2, ContentModel.PROP_CONTENT, TransferCommons.URLToPartName(file2ContentUrl)); requisiteWriter.missingContent(file3, ContentModel.PROP_CONTENT, TransferCommons.URLToPartName(file3ContentUrl)); requisiteWriter.endTransferRequsite(); writer.flush(); writer.close(); return null; } }).when(mockedTransferTransmitter).sendManifest(any(Transfer.class), any(File.class), any(OutputStream.class)); doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { OutputStream os = (OutputStream)invocation.getArguments()[1]; Writer writer = new OutputStreamWriter(os); XMLTransferDestinationReportWriter reportWriter = new XMLTransferDestinationReportWriter(); reportWriter.startTransferReport("UTF-8", writer); reportWriter.writeComment("This is a comment"); reportWriter.writeChangeState("COMMITTING"); reportWriter.writeCreated(file1, file1, folder1, new Path()); reportWriter.writeDeleted(file3, file3, new Path()); reportWriter.writeMoved(file2, file2, new Path(), folder1, new Path()); reportWriter.endTransferReport(); return null; } }).when(mockedTransferTransmitter).getTransferReport(any(Transfer.class), any(OutputStream.class)); if (statuses != null) { if (statuses.length > 1) { when(mockedTransferTransmitter.getStatus(transfer)). thenReturn(statuses[0], Arrays.copyOfRange(statuses, 1, statuses.length)); } else if (statuses.length == 1) { when(mockedTransferTransmitter.getStatus(transfer)). thenReturn(statuses[0]); } } } private TransferTarget createTransferTarget(String name) { TransferTarget target; try { target = transferService.getTransferTarget(name); } catch(TransferException ex) { String title = "title"; String description = "description"; String endpointProtocol = "http"; String endpointHost = "host"; int endpointPort = 8080; String endpointPath = "/alfresco/service/api/transfer"; String username = "user"; char[] password = "password".toCharArray(); /** * Now go ahead and create our first transfer target */ target = transferService.createAndSaveTransferTarget(name, title, description, endpointProtocol, endpointHost, endpointPort, endpointPath, username, password); } return target; } }