/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.distribution.download; import org.opencastproject.distribution.api.DistributionService; import org.opencastproject.job.api.Job; import org.opencastproject.job.api.JobBarrier; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageElement; import org.opencastproject.mediapackage.MediaPackageElementParser; import org.opencastproject.mediapackage.MediaPackageParser; import org.opencastproject.security.api.DefaultOrganization; import org.opencastproject.security.api.JaxbRole; import org.opencastproject.security.api.JaxbUser; import org.opencastproject.security.api.Organization; import org.opencastproject.security.api.OrganizationDirectoryService; import org.opencastproject.security.api.SecurityService; import org.opencastproject.security.api.TrustedHttpClient; import org.opencastproject.security.api.User; import org.opencastproject.security.api.UserDirectoryService; import org.opencastproject.security.util.StandAloneTrustedHttpClientImpl; import org.opencastproject.serviceregistry.api.IncidentService; import org.opencastproject.serviceregistry.api.ServiceRegistry; import org.opencastproject.serviceregistry.api.ServiceRegistryInMemoryImpl; import org.opencastproject.util.PathSupport; import org.opencastproject.util.UrlSupport; import org.opencastproject.util.data.Either; import org.opencastproject.util.data.Function; import org.opencastproject.workspace.api.Workspace; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.methods.HttpUriRequest; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.osgi.framework.BundleContext; import org.osgi.service.component.ComponentContext; import java.io.File; import java.net.URI; import java.util.Dictionary; import java.util.Hashtable; import javax.servlet.http.HttpServletResponse; public class DownloadDistributionServiceImplTest { private DownloadDistributionServiceImpl service = null; private MediaPackage mp = null; private File distributionRoot = null; private ServiceRegistry serviceRegistry = null; private DefaultOrganization defaultOrganization; @Before public void setUp() throws Exception { final File mediaPackageRoot = new File(getClass().getResource("/mediapackage.xml").toURI()).getParentFile(); mp = MediaPackageParser.getFromXml(IOUtils.toString(getClass().getResourceAsStream("/mediapackage.xml"), "UTF-8")); distributionRoot = new File(mediaPackageRoot, "static"); service = new DownloadDistributionServiceImpl(); StatusLine statusLine = EasyMock.createNiceMock(StatusLine.class); EasyMock.expect(statusLine.getStatusCode()).andReturn(HttpServletResponse.SC_OK).anyTimes(); EasyMock.replay(statusLine); HttpResponse response = EasyMock.createNiceMock(HttpResponse.class); EasyMock.expect(response.getStatusLine()).andReturn(statusLine).anyTimes(); EasyMock.replay(response); final TrustedHttpClient httpClient = EasyMock.createNiceMock(TrustedHttpClient.class); EasyMock.expect(httpClient.execute((HttpUriRequest) EasyMock.anyObject())).andReturn(response).anyTimes(); EasyMock.expect(httpClient.run((HttpUriRequest) EasyMock.anyObject())) .andAnswer(new IAnswer<Function<Function<HttpResponse, Object>, Either<Exception, Object>>>() { @Override public Function<Function<HttpResponse, Object>, Either<Exception, Object>> answer() throws Throwable { HttpUriRequest req = (HttpUriRequest) EasyMock.getCurrentArguments()[0]; return StandAloneTrustedHttpClientImpl.run(httpClient, req); } }).anyTimes(); EasyMock.replay(httpClient); defaultOrganization = new DefaultOrganization(); User anonymous = new JaxbUser("anonymous", "test", defaultOrganization, new JaxbRole(DefaultOrganization.DEFAULT_ORGANIZATION_ANONYMOUS, defaultOrganization)); UserDirectoryService userDirectoryService = EasyMock.createMock(UserDirectoryService.class); EasyMock.expect(userDirectoryService.loadUser((String) EasyMock.anyObject())).andReturn(anonymous).anyTimes(); EasyMock.replay(userDirectoryService); service.setUserDirectoryService(userDirectoryService); Organization organization = new DefaultOrganization(); OrganizationDirectoryService organizationDirectoryService = EasyMock.createMock(OrganizationDirectoryService.class); EasyMock.expect(organizationDirectoryService.getOrganization((String) EasyMock.anyObject())).andReturn(organization) .anyTimes(); EasyMock.replay(organizationDirectoryService); service.setOrganizationDirectoryService(organizationDirectoryService); SecurityService securityService = EasyMock.createNiceMock(SecurityService.class); EasyMock.expect(securityService.getUser()).andReturn(anonymous).anyTimes(); EasyMock.expect(securityService.getOrganization()).andReturn(organization).anyTimes(); EasyMock.replay(securityService); service.setSecurityService(securityService); serviceRegistry = new ServiceRegistryInMemoryImpl(service, securityService, userDirectoryService, organizationDirectoryService, EasyMock.createNiceMock(IncidentService.class)); service.setServiceRegistry(serviceRegistry); service.setTrustedHttpClient(httpClient); final Workspace workspace = EasyMock.createNiceMock(Workspace.class); service.setWorkspace(workspace); EasyMock.expect(workspace.get((URI) EasyMock.anyObject())).andAnswer(new IAnswer<File>() { @Override public File answer() throws Throwable { final URI uri = (URI) EasyMock.getCurrentArguments()[0]; final String[] pathElems = uri.getPath().split("/"); final String file = pathElems[pathElems.length - 1]; return new File(mediaPackageRoot, file); } }).anyTimes(); EasyMock.replay(workspace); BundleContext bc = EasyMock.createNiceMock(BundleContext.class); EasyMock.expect(bc.getProperty("org.opencastproject.download.directory")).andReturn(distributionRoot.toString()).anyTimes(); EasyMock.expect(bc.getProperty("org.opencastproject.download.url")).andReturn(UrlSupport.DEFAULT_BASE_URL).anyTimes(); ComponentContext cc = EasyMock.createNiceMock(ComponentContext.class); Dictionary<String, Object> p = new Hashtable<String, Object>(); p.put(DistributionService.CONFIG_KEY_STORE_TYPE, "download"); EasyMock.expect(cc.getProperties()).andReturn(p).anyTimes(); EasyMock.expect(cc.getBundleContext()).andReturn(bc).anyTimes(); EasyMock.replay(bc, cc); service.activate(cc); } @After public void tearDown() throws Exception { FileUtils.deleteDirectory(distributionRoot); ((ServiceRegistryInMemoryImpl) serviceRegistry).dispose(); } @Test public void testPartialDistribution() throws Exception { // Distribute only some of the elements in the mediapackage Job job1 = service.distribute("engage-player", mp, "track-1"); Job job2 = service.distribute("engage-player", mp, "catalog-1"); Job job3 = service.distribute("oai-pmh", mp, "catalog-1"); JobBarrier jobBarrier = new JobBarrier(null, serviceRegistry, 500, job1, job2, job3); jobBarrier.waitForJobs(); File mpDir = new File(distributionRoot, PathSupport.path(defaultOrganization.getId(), "engage-player", mp.getIdentifier().compact())); Assert.assertTrue(mpDir.exists()); File mediaDir = new File(mpDir, "track-1"); File metadataDir = new File(mpDir, "catalog-1"); File attachmentsDir = new File(mpDir, "notes"); Assert.assertTrue(mediaDir.exists()); Assert.assertTrue(metadataDir.exists()); Assert.assertFalse(attachmentsDir.exists()); Assert.assertTrue(new File(mediaDir, "media.mov").exists()); // the filenames are changed to reflect the element ID Assert.assertTrue(new File(metadataDir, "dublincore.xml").exists()); Assert.assertFalse(new File(metadataDir, "mpeg7.xml").exists()); Assert.assertFalse(new File(attachmentsDir, "attachment.txt").exists()); } @Test public void testRetractByOriginal() throws Exception { // Distribute the mediapackage and all of its elements Job job1 = service.distribute("engage-player", mp, "track-1"); Job job2 = service.distribute("engage-player", mp, "catalog-1"); Job job3 = service.distribute("engage-player", mp, "catalog-2"); Job job4 = service.distribute("engage-player", mp, "notes"); Job job5 = service.distribute("oai-pmh", mp, "track-1"); JobBarrier jobBarrier = new JobBarrier(null, serviceRegistry, 500, job1, job2, job3, job4, job5); jobBarrier.waitForJobs(); // Add the new elements to the mediapackage mp.add(MediaPackageElementParser.getFromXml(job1.getPayload())); mp.add(MediaPackageElementParser.getFromXml(job2.getPayload())); mp.add(MediaPackageElementParser.getFromXml(job3.getPayload())); mp.add(MediaPackageElementParser.getFromXml(job4.getPayload())); mp.add(MediaPackageElementParser.getFromXml(job5.getPayload())); File mpDir = new File(distributionRoot, PathSupport.path(defaultOrganization.getId(), "engage-player", mp.getIdentifier().compact())); File mediaDir = new File(mpDir, "track-1"); File metadata1Dir = new File(mpDir, "catalog-1"); File metadata2Dir = new File(mpDir, "catalog-2"); File attachmentsDir = new File(mpDir, "notes"); Assert.assertTrue(mediaDir.exists()); Assert.assertTrue(metadata1Dir.exists()); Assert.assertTrue(metadata2Dir.exists()); Assert.assertTrue(attachmentsDir.exists()); Assert.assertTrue(new File(mediaDir, "media.mov").exists()); // the filenames are changed to reflect the element ID Assert.assertTrue(new File(metadata1Dir, "dublincore.xml").exists()); Assert.assertTrue(new File(metadata2Dir, "mpeg7.xml").exists()); Assert.assertTrue(new File(attachmentsDir, "attachment.txt").exists()); // Now retract the mediapackage and ensure that the distributed files have been removed Job job6 = service.retract("engage-player", mp, "track-1"); Job job7 = service.retract("engage-player", mp, "catalog-1"); Job job8 = service.retract("engage-player", mp, "catalog-2"); Job job9 = service.retract("engage-player", mp, "notes"); jobBarrier = new JobBarrier(null, serviceRegistry, 500, job6, job7, job8, job9); jobBarrier.waitForJobs(); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("track-1")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("catalog-1")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("catalog-2")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("notes")).isFile()); Assert.assertTrue(service.getDistributionFile("oai-pmh", mp, mp.getElementById("track-1")).isFile()); } @Test public void testRetractByDistributed() throws Exception { int elementCount = mp.getElements().length; // Distribute the mediapackage and all of its elements Job job1 = service.distribute("engage-player", mp, "track-1"); Job job2 = service.distribute("engage-player", mp, "catalog-1"); Job job3 = service.distribute("engage-player", mp, "catalog-2"); Job job4 = service.distribute("engage-player", mp, "notes"); Job job5 = service.distribute("oai-pmh", mp, "notes"); JobBarrier jobBarrier = new JobBarrier(null, serviceRegistry, 500, job1, job2, job3, job4, job5); jobBarrier.waitForJobs(); // Add the new elements to the mediapackage MediaPackageElement job1Element = MediaPackageElementParser.getFromXml(job1.getPayload()); mp.add(job1Element); MediaPackageElement job2Element = MediaPackageElementParser.getFromXml(job2.getPayload()); mp.add(job2Element); MediaPackageElement job3Element = MediaPackageElementParser.getFromXml(job3.getPayload()); mp.add(job3Element); MediaPackageElement job4Element = MediaPackageElementParser.getFromXml(job4.getPayload()); mp.add(job4Element); MediaPackageElement job5Element = MediaPackageElementParser.getFromXml(job5.getPayload()); mp.add(job5Element); File mpDir = new File(distributionRoot, PathSupport.path(defaultOrganization.getId(), "engage-player", mp.getIdentifier().compact())); File mediaDir = new File(mpDir, "track-1"); File metadata1Dir = new File(mpDir, "catalog-1"); File metadata2Dir = new File(mpDir, "catalog-2"); File attachmentsDir = new File(mpDir, "notes"); Assert.assertTrue(mediaDir.exists()); Assert.assertTrue(metadata1Dir.exists()); Assert.assertTrue(metadata2Dir.exists()); Assert.assertTrue(attachmentsDir.exists()); Assert.assertTrue(new File(mediaDir, "media.mov").exists()); // the filenames are changed to reflect the element ID Assert.assertTrue(new File(metadata1Dir, "dublincore.xml").exists()); Assert.assertTrue(new File(metadata2Dir, "mpeg7.xml").exists()); Assert.assertTrue(new File(attachmentsDir, "attachment.txt").exists()); // Now retract the mediapackage and ensure that the distributed files have been removed Job job6 = service.retract("engage-player", mp, job1Element.getIdentifier()); Job job7 = service.retract("engage-player", mp, job2Element.getIdentifier()); Job job8 = service.retract("engage-player", mp, job3Element.getIdentifier()); Job job9 = service.retract("engage-player", mp, job4Element.getIdentifier()); jobBarrier = new JobBarrier(null, serviceRegistry, 500, job6, job7, job8, job9); jobBarrier.waitForJobs(); // Remove the distributed elements from the mediapackage mp.remove(MediaPackageElementParser.getFromXml(job6.getPayload())); mp.remove(MediaPackageElementParser.getFromXml(job7.getPayload())); mp.remove(MediaPackageElementParser.getFromXml(job8.getPayload())); mp.remove(MediaPackageElementParser.getFromXml(job9.getPayload())); // +1 since the oai-pmh distribution has not been retracted Assert.assertEquals(elementCount + 1, mp.getElements().length); Assert.assertNotNull(mp.getElementById("track-1")); Assert.assertNotNull(mp.getElementById("catalog-1")); Assert.assertNotNull(mp.getElementById("catalog-2")); Assert.assertNotNull(mp.getElementById("notes")); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("track-1")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("catalog-1")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("catalog-2")).isFile()); Assert.assertFalse(service.getDistributionFile("engage-player", mp, mp.getElementById("notes")).isFile()); Assert.assertTrue(service.getDistributionFile("oai-pmh", mp, mp.getElementById("notes")).isFile()); } }