/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wps.resource; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.geoserver.ows.DispatcherCallback; import org.geoserver.ows.Request; import org.geoserver.ows.Response; import org.geoserver.platform.Operation; import org.geoserver.platform.Service; import org.geoserver.platform.ServiceException; import org.geotools.util.logging.Logging; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextStoppedEvent; /** * A WPS process has to deal with various temporary resources during the execution, be streamed and * stored inputs, Sextante temporary files, temporary feature types and so on. * * This class manages the lifecycle of these resources, register them here to have their lifecycle * properly managed * * The design is still very rough, I'm making this up as I go. The class will require modifications * to handle asynch process computations as well as resources with a timeout * * @author Andrea Aime - OpenGeo * */ public class WPSResourceManager implements DispatcherCallback, ApplicationListener { private static final Logger LOGGER = Logging.getLogger(WPSResourceManager.class); ConcurrentHashMap<UUID, List<WPSResource>> resourceCache = new ConcurrentHashMap<UUID, List<WPSResource>>(); ThreadLocal<UUID> processId = new ThreadLocal<UUID>(); /** * Create a new unique id for the process. All resources linked to the process should use this * token to register themselves against the manager * * @return */ public UUID getProcessId() { if (processId.get() == null) { processId.set(UUID.randomUUID()); } return processId.get(); } public void addResource(WPSResource resource) { UUID processId = getProcessId(); List<WPSResource> processResources = resourceCache.get(processId); if (processResources == null) { processResources = new ArrayList<WPSResource>(); resourceCache.put(processId, processResources); } processResources.add(resource); } // ----------------------------------------------------------------- // DispatcherCallback methods // ----------------------------------------------------------------- public void finished(Request request) { // if we did not generate any process id, no resources have been added if (processId.get() == null) { return; } // grab the id and unbind the thread local UUID id = processId.get(); processId.remove(); // cleaup cleanProcess(id); resourceCache.remove(id); } /** * Cleans up all the resources associated to a certain id * @param id */ void cleanProcess(UUID id) { // delete all resources associated with the process for (WPSResource resource : resourceCache.get(id)) { try { resource.delete(); } catch (Throwable t) { LOGGER.log(Level.WARNING, "Failed to clean up the WPS resource " + resource.getName(), t); } } } public Request init(Request request) { return null; } public Operation operationDispatched(Request request, Operation operation) { return null; } public Object operationExecuted(Request request, Operation operation, Object result) { return null; } public Response responseDispatched(Request request, Operation operation, Object result, Response response) { return null; } public Service serviceDispatched(Request request, Service service) throws ServiceException { return null; } // ----------------------------------------------------------------- // ApplicationListener methods // ----------------------------------------------------------------- public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextClosedEvent || event instanceof ContextStoppedEvent) { // we are shutting down, remove all temp resources! for (UUID id : resourceCache.keySet()) { cleanProcess(id); } } resourceCache.clear(); } }