/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.rest.catalog; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.geoserver.GeoServerConfigurationLock; import org.geoserver.GeoServerConfigurationLock.LockType; import org.geoserver.rest.CatalogReloadController; import org.geoserver.rest.DispatcherCallback; import org.geoserver.rest.AbstractGeoServerController; import org.springframework.stereotype.Controller; /** * Protects catalog access from concurrent rest configuration calls. Will lock in write mode every call modifying catalog resources, in read mode all * others catalog resource related calls, no locks will be performed on other rest requests. * * @author Andrea Aime - GeoSolutions */ @Controller public class RestConfigurationLockCallback implements DispatcherCallback { GeoServerConfigurationLock locker; public RestConfigurationLockCallback(GeoServerConfigurationLock locker) { this.locker = locker; } @Override public void init(HttpServletRequest request, HttpServletResponse response) { LockType type = locker.getCurrentLock(); if (type != null) { throw new RuntimeException("The previous lock was not released: " + type); } } @Override public void dispatched(HttpServletRequest request, HttpServletResponse response, Object handler) { Object controller = DispatcherCallback.getControllerBean(handler); if (controller instanceof AbstractCatalogController || controller instanceof AbstractGeoServerController) { if (controller instanceof CatalogReloadController || isWriteMethod(request.getMethod())) { // this requires a full lock, it affects part of GeoTools that are not thread safe locker.lock(LockType.WRITE); } else { locker.lock(LockType.READ); } } } private boolean isWriteMethod(String method) { return "PUT".equalsIgnoreCase(method) || "POST".equalsIgnoreCase(method) || "DELETE".equalsIgnoreCase(method); } @Override public void exception(HttpServletRequest request, HttpServletResponse response, Exception error) { // nothing to see here, move on } @Override public void finished(HttpServletRequest request, HttpServletResponse response) { LockType type = locker.getCurrentLock(); if (type != null) { locker.unlock(); } } }