Author: ssmiweve Date: 2009-01-31 20:14:51 +0100 (Sat, 31 Jan 2009) New Revision: 7193
Added: branches/2.18/site-spi/src/main/java/no/sesat/search/site/AbstractSiteKeyedFactory.java Log: http://permalink.gmane.org/gmane.comp.java.sesat.kernel.devel/228 Added: branches/2.18/site-spi/src/main/java/no/sesat/search/site/AbstractSiteKeyedFactory.java =================================================================== --- branches/2.18/site-spi/src/main/java/no/sesat/search/site/AbstractSiteKeyedFactory.java (rev 0) +++ branches/2.18/site-spi/src/main/java/no/sesat/search/site/AbstractSiteKeyedFactory.java 2009-01-31 19:14:51 UTC (rev 7193) @@ -0,0 +1,110 @@ +/* Copyright (2009) Schibsted Søk AS + * This file is part of SESAT. + * + * SESAT is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SESAT is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SESAT. If not, see <http://www.gnu.org/licenses/>. + * + */ + +package no.sesat.search.site; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.apache.log4j.Logger; + +/** Abstract implementation of a SiteKeyedFactory to help with + * the INSTANCES map and locking pattern typically used around it using ReentrantReadWriteLocks. + * + * @version $Id$ + */ +public abstract class AbstractSiteKeyedFactory implements SiteKeyedFactory{ + + // Constants ----------------------------------------------------- + + private static final Logger LOG = Logger.getLogger(AbstractSiteKeyedFactory.class); + + private static final String ERR_DOC_BUILDER_CREATION = " failed to construct new factory instance for "; + + // Attributes ---------------------------------------------------- + + // Static -------------------------------------------------------- + + /** Handles the locking pattern around the INSTANCES map that's done with a ReentrantReadWriteLock. + * @see http://permalink.gmane.org/gmane.comp.java.sesat.kernel.devel/228 + * + * @param <T> the type of SiteKeyedFactory that can be constructed. + * @param site the site this factory will answer to. + * @param instances the map of factories of type T already in existence. + * @param instancesLock the lock used around the instances map + * @param constructor the wrapper around the constructor used to create factories of type T. + * @return the singleton instance of factory of type T related to the given site. + */ + protected static final <T extends AbstractSiteKeyedFactory> T instanceOf( + final Site site, + final Map<Site,T> instances, + final ReentrantReadWriteLock instancesLock, + final FactoryConstructor<T> constructor){ + + try { + instancesLock.readLock().lock(); + if (!instances.containsKey(site)) { + // It is not possible to upgrade a read lock... + instancesLock.readLock().unlock(); + instancesLock.writeLock().lock(); + try { + // ...so check the condition again. + if (!instances.containsKey(site)) { + instances.put(site, constructor.construct()); + } + } catch (SiteKeyedFactoryInstantiationException e) { + LOG.error(constructor + ERR_DOC_BUILDER_CREATION + site, e); + } finally { + // Downgrade to a read lock. + instancesLock.readLock().lock(); + instancesLock.writeLock().unlock(); + } + } + return instances.get(site); + } finally { + // Finally release the read lock. + instancesLock.readLock().unlock(); + } + } + + // Constructors -------------------------------------------------- + + protected AbstractSiteKeyedFactory() { + } + + // Public -------------------------------------------------------- + + // Package protected --------------------------------------------- + + // Protected ----------------------------------------------------- + + // Private ------------------------------------------------------- + + // Inner classes ------------------------------------------------- + + /** Wraps a constructor so that it may be delegated to from the instanceOf method. + * + * @param <T> the type of SiteKeyedFactory that can be constructed. + */ + protected interface FactoryConstructor<T extends AbstractSiteKeyedFactory>{ + /** Wraps a constructor so that it may be delegated to from the instanceOf method. + * + * @return the new SiteKeyedFactory instance + * @throws no.sesat.search.site.SiteKeyedFactoryInstantiationException any failure in construction. + */ + T construct() throws SiteKeyedFactoryInstantiationException; + } +} Property changes on: branches/2.18/site-spi/src/main/java/no/sesat/search/site/AbstractSiteKeyedFactory.java ___________________________________________________________________ Added: svn:keywords + Id _______________________________________________ Kernel-commits mailing list Kernel-commits@sesat.no http://sesat.no/mailman/listinfo/kernel-commits