/** * 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.workflow.handler.distribution; import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; import org.opencastproject.distribution.api.DistributionException; import org.opencastproject.distribution.api.DownloadDistributionService; import org.opencastproject.job.api.Job; import org.opencastproject.mediapackage.Attachment; import org.opencastproject.mediapackage.Catalog; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.Publication; import org.opencastproject.mediapackage.Track; import org.opencastproject.workflow.api.AbstractWorkflowOperationHandler; import org.opencastproject.workflow.api.WorkflowOperationException; import com.entwinemedia.fn.Fn; import com.entwinemedia.fn.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Abstract base class of ConfigurablePublishWorkflerOperationHandler and ConfigurableRectractWorkflowOperationHandler. * * Both the ConfigurablePublishWorkflowOperationHandler and ConfigurableRetractWorkflowOperationHanlder are capable of * retracting publications created by the ConfigurablePublishWorkflowOperationHandler. * To avoid code duplication, this commonly used functionaly has been factored out into this class. */ public abstract class ConfigurableWorkflowOperationHandlerBase extends AbstractWorkflowOperationHandler { private static final Logger logger = LoggerFactory.getLogger(ConfigurableWorkflowOperationHandlerBase.class); abstract DownloadDistributionService getDistributionService(); /** * Adds all of the {@link Publication}'s {@link MediaPackageElement}s that would normally have not been in the * {@link MediaPackage}. * * @param publication * The {@link Publication} with the {@link MediaPackageElement}s to add. * @param mp * The {@link MediaPackage} to add the {@link MediaPackageElement}s to. */ private void addPublicationElementsToMediaPackage(Publication publication, MediaPackage mp) { assert ((publication != null) && (mp != null)); for (Attachment attachment : publication.getAttachments()) { mp.add(attachment); } for (Catalog catalog : publication.getCatalogs()) { mp.add(catalog); } for (Track track : publication.getTracks()) { mp.add(track); } } /** * Remove the {@link Publication}'s {@link MediaPackageElement}s from a given channel. * * @param channelId * The channel to remove the {@link MediaPackageElement}s from. * @param publication * The {@link Publication} that is being removed. * @param mp * The {@link MediaPackage} that the {@link Publication} is part of. * @return the number of {@link MediaPackageElement}s that have been retracted * @throws WorkflowOperationException * Thrown if unable to retract the {@link MediaPackageElement}s. */ private int retractPublicationElements(String channelId, Publication publication, MediaPackage mp) throws WorkflowOperationException { assert ((channelId != null) && (publication != null) && (mp != null)); MediaPackage mediapackageWithPublicationElements = (MediaPackage) mp.clone(); // Add the publications to the mediapackage so that we can use the standard retract addPublicationElementsToMediaPackage(publication, mediapackageWithPublicationElements); Set<String> elementIds = new HashSet<String>(); for (Attachment attachment : publication.getAttachments()) { elementIds.add(attachment.getIdentifier()); } for (Catalog catalog : publication.getCatalogs()) { elementIds.add(catalog.getIdentifier()); } for (Track track : publication.getTracks()) { elementIds.add(track.getIdentifier()); } if (elementIds.size() > 0) { logger.info("Retracting {} elements of media package {} from publication channel {}", elementIds.size(), mp, channelId); Job job = null; try { job = getDistributionService().retract(channelId, mediapackageWithPublicationElements, elementIds); } catch (DistributionException e) { logger.error("Error while retracting '{}' elements from channel '{}' of distribution '{}': {}", new Object[] { elementIds.size(), channelId, getDistributionService(), getStackTrace(e) }); throw new WorkflowOperationException("The retraction job did not complete successfully"); } if (!waitForStatus(job).isSuccess()) { throw new WorkflowOperationException("The retraction job did not complete successfully"); } } else { logger.debug("No publication elements were found for retraction"); } return elementIds.size(); } public List<Publication> getPublications(final MediaPackage mp, final String channelId) { assert ((mp != null) && (channelId != null)); final List<Publication> publications = Stream.mk(mp.getPublications()).filter(new Fn<Publication, Boolean>() { @Override public Boolean apply(Publication a) { return channelId.equals(a.getChannel()); } }).toList(); assert (publications != null); return publications; } public void retract(MediaPackage mp, final String channelId) throws WorkflowOperationException { assert ((mp != null) && (channelId != null)); final List<Publication> publications = getPublications(mp, channelId); if (publications.size() > 0) { int retractedElementsCount = 0; for (Publication publication : publications) { retractedElementsCount += retractPublicationElements(channelId, publication, mp); mp.remove(publication); } logger.info("Successfully retracted {} publications and retracted {} elements from publication channel '{}'", new Object[] { publications.size(), retractedElementsCount, channelId }); } else { logger.info("No publications for channel {} found for media package {}", channelId, mp.getIdentifier()); } } }