/* Copyright (c) 2001 - 2011 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver.rest; import org.geoserver.GeoServerConfigurationLock; import org.geoserver.GeoServerConfigurationLock.LockType; import org.restlet.Restlet; import org.restlet.Route; import org.restlet.data.Method; import org.restlet.data.Request; import org.restlet.data.Response; /** * 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 */ public class RestConfigurationLockCallback implements DispatcherCallback { GeoServerConfigurationLock locker; static ThreadLocal<LockType> THREAD_LOCK = new ThreadLocal<GeoServerConfigurationLock.LockType>(); public RestConfigurationLockCallback(GeoServerConfigurationLock locker) { this.locker = locker; } @Override public void init(Request request, Response response) { LockType type = THREAD_LOCK.get(); if (type != null) { throw new RuntimeException("The previous lock was not released: " + type); } } @Override public void dispatched(Request request, Response response, Restlet restlet) { Method m = request.getMethod(); if (restlet instanceof Route) { restlet = ((Route) restlet).getNext(); } if (restlet instanceof BeanDelegatingRestlet) { restlet = ((BeanDelegatingRestlet) restlet).getBean(); } if (restlet != null) { // these are the restlets we have to lock if (restlet.getClass().getPackage().getName().startsWith("org.geoserver.catalog.rest")) { // choose a lok type based on the method LockType type; if ((m == Method.DELETE || m == Method.COPY || m == Method.MKCOL || m == Method.MOVE || m == Method.PROPPATCH || m == Method.POST || m == Method.PUT)) { type = LockType.WRITE; } else { type = LockType.READ; } THREAD_LOCK.set(type); locker.lock(type); } } } @Override public void exception(Request request, Response response, Exception error) { // nothing to see here, move on } @Override public void finished(Request request, Response response) { LockType type = THREAD_LOCK.get(); if (type != null) { THREAD_LOCK.remove(); locker.unlock(type); } } }