Java tutorial
/** * Copyright 2009, 2010 The Regents of the University of California * Licensed 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://www.osedu.org/licenses/ECL-2.0 * * 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; import org.opencastproject.job.api.JobContext; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageElement; import org.opencastproject.mediapackage.MediaPackageElementFlavor; import org.opencastproject.security.api.TrustedHttpClient; import org.opencastproject.security.api.TrustedHttpClientException; import org.opencastproject.serviceregistry.api.ServiceRegistration; import org.opencastproject.serviceregistry.api.ServiceRegistryException; import org.opencastproject.util.UrlSupport; import org.opencastproject.workflow.api.AbstractWorkflowOperationHandler; import org.opencastproject.workflow.api.WorkflowInstance; import org.opencastproject.workflow.api.WorkflowOperationException; import org.opencastproject.workflow.api.WorkflowOperationInstance; import org.opencastproject.workflow.api.WorkflowOperationResult; import org.opencastproject.workflow.api.WorkflowOperationResult.Action; import org.opencastproject.workingfilerepository.api.WorkingFileRepository; import org.opencastproject.workspace.api.Workspace; import org.apache.commons.lang.BooleanUtils; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.methods.HttpDelete; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; /** * Removes all files in the working file repository for mediapackage elements that don't match one of the * "preserve-flavors" configuration value. */ public class CleanupWorkflowOperationHandler extends AbstractWorkflowOperationHandler { /** The logger */ private static final Logger logger = LoggerFactory.getLogger(CleanupWorkflowOperationHandler.class); /** The element flavors to maintain in the original mediapackage. All others will be removed */ public static final String PRESERVE_FLAVOR_PROPERTY = "preserve-flavors"; /** Deleting external URI's config key */ public static final String DELETE_EXTERNAL = "delete-external"; /** The configuration properties */ protected SortedMap<String, String> configurationOptions = null; /** * The workspace to use in retrieving and storing files. */ protected Workspace workspace; /** The http client to use when connecting to remote servers */ protected TrustedHttpClient client = null; /** The default no-arg constructor builds the configuration options set */ public CleanupWorkflowOperationHandler() { configurationOptions = new TreeMap<String, String>(); configurationOptions.put(PRESERVE_FLAVOR_PROPERTY, "The configuration key that specifies the flavors to preserve. If not specified, this operation will not" + "remove any files."); configurationOptions.put(DELETE_EXTERNAL, "Whether to try to delete external working file repository URIs. Default is false."); } /** * Sets the workspace to use. * * @param workspace * the workspace */ public void setWorkspace(Workspace workspace) { this.workspace = workspace; } /** * Sets the trusted http client * * @param client * the trusted http client */ public void setTrustedHttpClient(TrustedHttpClient client) { this.client = client; } /** * {@inheritDoc} * * @see org.opencastproject.workflow.api.AbstractWorkflowOperationHandler#start(org.opencastproject.workflow.api.WorkflowInstance, * JobContext) */ @Override public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException { MediaPackage mediaPackage = workflowInstance.getMediaPackage(); WorkflowOperationInstance currentOperation = workflowInstance.getCurrentOperation(); String flavors = currentOperation.getConfiguration(PRESERVE_FLAVOR_PROPERTY); final List<MediaPackageElementFlavor> flavorsToPreserve = new ArrayList<MediaPackageElementFlavor>(); boolean deleteExternal = BooleanUtils.toBoolean(currentOperation.getConfiguration(DELETE_EXTERNAL)); // If the configuration does not specify flavors, remove them all for (String flavor : asList(flavors)) { flavorsToPreserve.add(MediaPackageElementFlavor.parseFlavor(flavor)); } String baseUrl = workspace.getBaseUri().toString(); // Find all external working file repository base Urls List<String> externalWfrBaseUrls = new ArrayList<String>(); if (deleteExternal) { try { for (ServiceRegistration reg : serviceRegistry .getServiceRegistrationsByType(WorkingFileRepository.SERVICE_TYPE)) { if (baseUrl.startsWith(reg.getHost())) continue; externalWfrBaseUrls.add(UrlSupport.concat(reg.getHost(), reg.getPath())); } } catch (ServiceRegistryException e) { logger.error("Unable to load WFR services from service registry: {}", e.getMessage()); throw new WorkflowOperationException(e); } } // Some URIs are shared by multiple elements. If one of these elements should be deleted but another should not, we // must keep the file. Set<URI> urisToDelete = new HashSet<URI>(); Set<URI> urisToKeep = new HashSet<URI>(); for (MediaPackageElement element : mediaPackage.getElements()) { if (element.getURI() == null) continue; String elementUri = element.getURI().toString(); if (!elementUri.startsWith(baseUrl)) { if (deleteExternal) { String wfrBaseUrl = null; for (String url : externalWfrBaseUrls) { if (element.getURI().toString().startsWith(url)) { wfrBaseUrl = url; break; } } if (wfrBaseUrl == null) continue; HttpDelete delete; if (elementUri.startsWith( UrlSupport.concat(wfrBaseUrl, WorkingFileRepository.MEDIAPACKAGE_PATH_PREFIX))) { String wfrDeleteUrl = elementUri.substring(0, elementUri.lastIndexOf("/")); delete = new HttpDelete(wfrDeleteUrl); } else if (elementUri.startsWith( UrlSupport.concat(wfrBaseUrl, WorkingFileRepository.COLLECTION_PATH_PREFIX))) { delete = new HttpDelete(elementUri); } else { logger.info("Unable to handle URI {}", elementUri); continue; } try { HttpResponse response = client.execute(delete); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_NO_CONTENT || statusCode == HttpStatus.SC_OK) { logger.info("Sucessfully deleted external URI {}", delete.getURI()); } else if (statusCode == HttpStatus.SC_NOT_FOUND) { logger.info("External URI {} has already been deleted", delete.getURI()); } else { logger.info("Unable to delete external URI {}, status code '{}' returned", delete.getURI(), statusCode); } } catch (TrustedHttpClientException e) { logger.warn("Unable to execute DELETE request on external URI {}", delete.getURI()); throw new WorkflowOperationException(e); } } continue; } // remove the element if it doesn't match the flavors to preserve boolean remove = true; for (MediaPackageElementFlavor flavor : flavorsToPreserve) { if (flavor.matches(element.getFlavor())) { remove = false; break; } } if (remove) { urisToDelete.add(element.getURI()); mediaPackage.remove(element); } else { urisToKeep.add(element.getURI()); } } // Remove all of the files to keep from the one to delete urisToDelete.removeAll(urisToKeep); // Now remove the files to delete for (URI uri : urisToDelete) { try { workspace.delete(uri); } catch (Exception e) { logger.warn("Unable to delete {}", uri); } } return createResult(mediaPackage, Action.CONTINUE); } /** * {@inheritDoc} * * @see org.opencastproject.workflow.api.WorkflowOperationHandler#getConfigurationOptions() */ @Override public SortedMap<String, String> getConfigurationOptions() { return configurationOptions; } }