Java tutorial
/* * Copyright 2010-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.gemfire.client; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.core.io.Resource; import org.springframework.data.gemfire.RegionLookupFactoryBean; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheListener; import com.gemstone.gemfire.cache.DataPolicy; import com.gemstone.gemfire.cache.GemFireCache; import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.client.ClientCache; import com.gemstone.gemfire.cache.client.ClientRegionFactory; import com.gemstone.gemfire.cache.client.ClientRegionShortcut; import com.gemstone.gemfire.cache.client.Pool; /** * Client extension for GemFire regions. * * @author Costin Leau */ public class ClientRegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements BeanFactoryAware, DisposableBean { private static final Log log = LogFactory.getLog(ClientRegionFactoryBean.class); private boolean destroy = false; private boolean close = true; private Resource snapshot; private CacheListener<K, V> cacheListeners[]; private Interest<K>[] interests; private String poolName; private BeanFactory beanFactory; private ClientRegionShortcut shortcut = null; private DataPolicy dataPolicy; private RegionAttributes<K, V> attributes; private Region<K, V> region; @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); region = getRegion(); postProcess(region); } @Override protected Region<K, V> lookupFallback(GemFireCache cache, String regionName) throws Exception { Assert.isTrue(cache instanceof ClientCache, "Unable to create regions from " + cache); ClientCache c = (ClientCache) cache; // first look at shortcut ClientRegionShortcut s = null; if (shortcut == null) { if (dataPolicy != null) { if (DataPolicy.EMPTY.equals(dataPolicy)) { s = ClientRegionShortcut.PROXY; } else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy)) { s = ClientRegionShortcut.LOCAL_PERSISTENT; } } s = ClientRegionShortcut.LOCAL; } ClientRegionFactory<K, V> factory = c.createClientRegionFactory(s); // map the attributes onto the client if (attributes != null) { CacheListener<K, V>[] listeners = attributes.getCacheListeners(); if (!ObjectUtils.isEmpty(listeners)) { for (CacheListener<K, V> listener : listeners) { factory.addCacheListener(listener); } } factory.setCloningEnabled(attributes.getCloningEnabled()); factory.setConcurrencyLevel(attributes.getConcurrencyLevel()); factory.setCustomEntryIdleTimeout(attributes.getCustomEntryIdleTimeout()); factory.setCustomEntryTimeToLive(attributes.getCustomEntryTimeToLive()); factory.setDiskStoreName(attributes.getDiskStoreName()); factory.setDiskSynchronous(attributes.isDiskSynchronous()); factory.setEntryIdleTimeout(attributes.getEntryIdleTimeout()); factory.setEntryTimeToLive(attributes.getEntryTimeToLive()); factory.setEvictionAttributes(attributes.getEvictionAttributes()); factory.setInitialCapacity(attributes.getInitialCapacity()); factory.setKeyConstraint(attributes.getKeyConstraint()); factory.setLoadFactor(attributes.getLoadFactor()); factory.setPoolName(attributes.getPoolName()); factory.setRegionIdleTimeout(attributes.getRegionIdleTimeout()); factory.setRegionTimeToLive(attributes.getRegionTimeToLive()); factory.setStatisticsEnabled(attributes.getStatisticsEnabled()); factory.setValueConstraint(attributes.getValueConstraint()); } if (!ObjectUtils.isEmpty(cacheListeners)) { for (CacheListener<K, V> listener : cacheListeners) { factory.addCacheListener(listener); } } if (StringUtils.hasText(poolName)) { // try to eagerly initialize the pool name, if defined as a bean if (beanFactory.isTypeMatch(poolName, Pool.class)) { if (log.isDebugEnabled()) { log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it..."); } beanFactory.getBean(poolName, Pool.class); } factory.setPoolName(poolName); } Region<K, V> reg = factory.create(regionName); log.info("Created new cache region [" + regionName + "]"); if (snapshot != null) { reg.loadSnapshot(snapshot.getInputStream()); } return reg; } protected void postProcess(Region<K, V> region) { if (!ObjectUtils.isEmpty(interests)) { for (Interest<K> interest : interests) { if (interest instanceof RegexInterest) { // do the cast since it's safe region.registerInterestRegex((String) interest.getKey(), interest.getPolicy(), interest.isDurable(), interest.isReceiveValues()); } else { region.registerInterest(interest.getKey(), interest.getPolicy(), interest.isDurable(), interest.isReceiveValues()); } } } } public void destroy() throws Exception { Region<K, V> region = getObject(); // unregister interests try { if (region != null && !ObjectUtils.isEmpty(interests)) { for (Interest<K> interest : interests) { if (interest instanceof RegexInterest) { region.unregisterInterestRegex((String) interest.getKey()); } else { region.unregisterInterest(interest.getKey()); } } } // should not really happen since interests are validated at start/registration } catch (UnsupportedOperationException ex) { log.warn("Cannot unregister cache interests", ex); } if (region != null) { if (close) { if (!region.getCache().isClosed()) { try { region.close(); } catch (CacheClosedException cce) { // nothing to see folks, move on. } } } else if (destroy) { region.destroyRegion(); } } region = null; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } /** * Set the interests for this client region. Both key and regex interest are supported. * * @param interests the interests to set */ public void setInterests(Interest<K>[] interests) { this.interests = interests; } /** * @return the interests */ Interest<K>[] getInterests() { return interests; } /** * Sets the pool name used by this client. * * @param poolName */ public void setPoolName(String poolName) { Assert.hasText(poolName, "pool name is required"); this.poolName = poolName; } /** * Sets the pool used by this client. * * @param pool */ public void setPool(Pool pool) { Assert.notNull(pool, "pool cannot be null"); setPoolName(pool.getName()); } /** * Initializes the client using a GemFire {@link ClientRegionShortcut}. * The recommended way for creating clients since it covers all the major scenarios with minimal * configuration. * * @param shortcut */ public void setShortcut(ClientRegionShortcut shortcut) { this.shortcut = shortcut; } /** * Indicates whether the region referred by this factory bean, * will be destroyed on shutdown (default false). * Note: destroy and close are mutually exclusive. Enabling one will automatically disable the other. * * @param destroy whether or not to destroy the region * * @see #setClose(boolean) */ public void setDestroy(boolean destroy) { this.destroy = destroy; if (destroy) { close = false; } } /** * Indicates whether the region referred by this factory bean, * will be closed on shutdown (default true). * Note: destroy and close are mutually exclusive. Enabling one will automatically disable the other. * * @param close whether to close or not the region * @see #setDestroy(boolean) */ public void setClose(boolean close) { this.close = close; if (close) { destroy = false; } } /** * Sets the snapshots used for loading a newly <i>created</i> region. * That is, the snapshot will be used <i>only</i> when a new region is created - if the region * already exists, no loading will be performed. * * @see #setName(String) * @param snapshot the snapshot to set */ public void setSnapshot(Resource snapshot) { this.snapshot = snapshot; } /** * Sets the cache listeners used for the region used by this factory. * Used only when a new region is created.Overrides the settings * specified through {@link #setAttributes(RegionAttributes)}. * * @param cacheListeners the cacheListeners to set on a newly created region */ public void setCacheListeners(CacheListener<K, V>[] cacheListeners) { this.cacheListeners = cacheListeners; } /** * Sets the data policy. Used only when a new region is created. * * @param dataPolicy the region data policy */ public void setDataPolicy(DataPolicy dataPolicy) { this.dataPolicy = dataPolicy; } /** * Sets the region attributes used for the region used by this factory. * Allows maximum control in specifying the region settings. * Used only when a new region is created. * Note that using this method allows for advanced customization of the region - while it provides a lot of flexibility, * note that it's quite easy to create misconfigured regions (especially in a client/server scenario). * * @param attributes the attributes to set on a newly created region */ public void setAttributes(RegionAttributes<K, V> attributes) { this.attributes = attributes; } }