class JCacheFactory implements CacheFactory {

    public Cache createCache(Map environment) throws CacheException {


        CacheLoader cacheLoader = null;
        Ehcache cache = null;
        try {
            String name = PropertyUtil.extractAndLogProperty("name", environment);

            String maxElementsInMemoryString = PropertyUtil.extractAndLogProperty("maxElementsInMemory", environment);
            int maxElementsInMemory = Integer.parseInt(maxElementsInMemoryString);

            String memoryStoreEvictionPolicyString = PropertyUtil.extractAndLogProperty("memoryStoreEvictionPolicy", environment);
            MemoryStoreEvictionPolicy memoryStoreEvictionPolicy =
                    MemoryStoreEvictionPolicy.fromString(memoryStoreEvictionPolicyString);

            String overflowToDiskString = PropertyUtil.extractAndLogProperty("overflowToDisk", environment);
            boolean overflowToDisk = PropertyUtil.parseBoolean(overflowToDiskString);

            String eternalString = PropertyUtil.extractAndLogProperty("eternal", environment);
            boolean eternal = PropertyUtil.parseBoolean(eternalString);

            String timeToLiveSecondsString = PropertyUtil.extractAndLogProperty("timeToLiveSeconds", environment);
            long timeToLiveSeconds = Long.parseLong(timeToLiveSecondsString);

            String timeToIdleSecondsString = PropertyUtil.extractAndLogProperty("timeToIdleSeconds", environment);
            long timeToIdleSeconds = Long.parseLong(timeToIdleSecondsString);

            String diskPersistentString = PropertyUtil.extractAndLogProperty("diskPersistentSeconds", environment);
            boolean diskPersistent = PropertyUtil.parseBoolean(diskPersistentString);

            long diskExpiryThreadIntervalSeconds = 0;
            String diskExpiryThreadIntervalSecondsString =
                    PropertyUtil.extractAndLogProperty("diskExpiryThreadIntervalSeconds", environment);
            if (diskExpiryThreadIntervalSecondsString != null) {
                diskExpiryThreadIntervalSeconds = Long.parseLong(diskExpiryThreadIntervalSecondsString);
            }

            int maxElementsOnDisk = 0;
            String maxElementsOnDiskString =
                    PropertyUtil.extractAndLogProperty("maxElementsOnDisk", environment);
            if (maxElementsOnDiskString != null) {
                maxElementsOnDisk = Integer.parseInt(maxElementsOnDiskString);
            }

            cacheLoader = null;
            String cacheLoaderFactoryClassName =
                    PropertyUtil.extractAndLogProperty("cacheLoaderFactoryClassName", environment);
            if (cacheLoaderFactoryClassName == null) {
                LOG.fine("cacheLoaderFactoryClassName not configured. Skipping...");
            } else {
                JCacheLoaderFactory factory = (JCacheLoaderFactory) ClassLoaderUtil.createNewInstance(cacheLoaderFactoryClassName);

                Properties properties = new Properties();
                for (Object key : environment.keySet()) {
                    properties.put(key, environment.get(key));

                }

                cacheLoader = factory.createCacheLoader(properties);
            }

            cache = new net.sf.ehcache.Cache(name, maxElementsInMemory, memoryStoreEvictionPolicy,
                        overflowToDisk, null, eternal,
                        timeToLiveSeconds, timeToIdleSeconds, diskPersistent, diskExpiryThreadIntervalSeconds,
                        null, null, maxElementsOnDisk);

            net.sf.ehcache.CacheManager.getInstance().addCache(cache);
        } catch (net.sf.ehcache.CacheException e) {
            throw new CacheException(e.getMessage(), e);
        }

        return new JCache(cache, cacheLoader);

    }

}