/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.threadlocals; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Map; /** * A helper class that transfers ThreadLocals that can be referenced as public static fields * * @author Andrea Aime - GeoSolutions */ @SuppressWarnings("unchecked") public class PublicThreadLocalTransfer implements ThreadLocalTransfer { Field field; String key; public PublicThreadLocalTransfer(Class theClass, String threadLocalField) throws SecurityException, NoSuchFieldException { this.field = theClass.getDeclaredField(threadLocalField); if (field == null) { throw new IllegalArgumentException("Failed to locate field " + field + " in class " + theClass.getName()); } else if (!Modifier.isStatic(field.getModifiers())) { throw new IllegalArgumentException("Field " + field + " in class " + theClass.getName() + " was found, but it's not a static variable"); } this.key = theClass.getName() + "#" + field; } @Override public void collect(Map<String, Object> storage) { ThreadLocal threadLocal = getThreadLocal(); if (threadLocal != null) { Object value = threadLocal.get(); storage.put(key, value); } } @Override public void apply(Map<String, Object> storage) { Object value = storage.get(key); ThreadLocal threadLocal = getThreadLocal(); if (threadLocal != null) { threadLocal.set(value); } } ThreadLocal getThreadLocal() { try { return (ThreadLocal) field.get(null); } catch (Exception e) { throw new RuntimeException("Failed to grab thread local " + key + " for transfer into other threads", e); } } @Override public void cleanup() { ThreadLocal threadLocal = getThreadLocal(); if (threadLocal != null) { threadLocal.remove(); } } }