package zh.solr.se.indexer.solrproxy; import java.util.Hashtable; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.solr.core.CoreContainer; /** * A Factory class that will provide a CoreContainer specific to a given core. * */ public class ProxyCoreContainerFactory { private static ProxyCoreContainerFactory instance = new ProxyCoreContainerFactory(); // Hashtable is synchronized. HashMap is not. private final Map<String, CoreContainer> coreContainerMap = new Hashtable<String, CoreContainer>(); private final Logger logger; /** * Allow nothing to instantiate this class directly. */ private ProxyCoreContainerFactory() { logger = Logger.getLogger("solrproxy"); logger.setLevel(Level.SEVERE); } /** * Get THE instance of this class * * @return THE instance */ public static ProxyCoreContainerFactory getInstance() { return instance; } /** * Fetch a CoreContainer specifically configured for a given core. * * @param coreName * @return * @throws UnsupportedCoreException */ synchronized public CoreContainer getCoreContainer(final String coreName) throws UnsupportedCoreException { logger.log(Level.INFO, "Getting core container '" + coreName + "'"); // check if the instance already exists CoreContainer container = coreContainerMap.get(standardizeCoreName(coreName)); if(container == null) { container = createCoreContainer(coreName); if(container != null) { coreContainerMap.put(coreName, container); } } if(container == null) { logger.log(Level.INFO, "Could not get core container '" + coreName + "'"); } else { logger.log(Level.INFO, "Got core container '" + coreName + "'"); } return container; } /** * Call shutdown() on the specified core and remove it from the map so that * all references to the core will be set to zero and GC can clean it up. * * @param coreName the name of the core * @throws UnsupportedCoreException */ synchronized public void shutdownCoreContainer(String coreName) throws UnsupportedCoreException { logger.log(Level.INFO, "Start shutting down core container '" + coreName + "'"); CoreContainer container = getCoreContainer(coreName); if(container != null) { container.shutdown(); logger.log(Level.INFO, "Core container '" + coreName + "' has been shutdown."); removeContainerFromMap(coreName); } } /** * So that all references to the specific core are set to zero for GC, remove * the core from the map * @param coreName * @throws UnsupportedCoreException */ synchronized private void removeContainerFromMap(String coreName) throws UnsupportedCoreException { logger.log(Level.INFO, "Removing core container '" + coreName + "' from map [size:" + coreContainerMap.size() + "]"); CoreContainer container = getCoreContainer(coreName); if(container == null) { logger.log(Level.SEVERE, "Could not get the core container object '" + coreName + "' from map [size:" + coreContainerMap.size() + "]"); } else { if(coreContainerMap.remove(coreName) == null) { logger.log(Level.INFO, "Remove returned nothing. Could not remove core container '" + coreName + "' from map [size:" + coreContainerMap.size() + "]"); } else { logger.log(Level.INFO, "Removed core container '" + coreName + "' from map [size:" + coreContainerMap.size() + "]"); } } } /** * Here's where the factory part takes place. See if a CoreContainer has * already been instantiated and if so return it. Otherwise, create a new one * and return it. * * @param coreName the name of the core * @return a core container * @throws UnsupportedCoreException */ private CoreContainer createCoreContainer(final String coreName) throws UnsupportedCoreException { final String standardizedCoreName = standardizeCoreName(coreName); CoreContainer coreContainer = null; if(standardizedCoreName.equalsIgnoreCase(SolrConstants.CORE_NAME_CHINESE)) { coreContainer = new ProxyChineseCoreContainer().getContainer(); }else { throw new UnsupportedCoreException(coreName); } return coreContainer; } /** * The core name could come in a "qa" or "core-qa". This method standardizes * the name to begin with "core-" so that the rest of the code can be sure * it's working with a known format. * * @param coreName * @return */ private String standardizeCoreName(String coreName) { if((coreName != null) && !coreName.startsWith("core-")) { coreName = "core-" + coreName.trim().toLowerCase(); } return coreName; } }