Author: nbelaevski
Date: 2009-07-09 14:24:28 -0400 (Thu, 09 Jul 2009)
New Revision: 14871
Added:
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCache.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCacheFactory.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCache.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCacheFactory.java
framework/trunk/impl/src/main/java/org/richfaces/resource/AbstractResource.java
Removed:
framework/trunk/impl/src/main/java/org/richfaces/resource/BaseResource.java
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceHandlerImpl.java
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceWrapper.java
framework/trunk/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
Modified:
framework/trunk/impl/
framework/trunk/impl/pom.xml
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/CacheManager.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCache.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCache.java
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java
framework/trunk/impl/src/main/java/org/ajax4jsf/io/ByteBuffer.java
framework/trunk/impl/src/main/java/org/ajax4jsf/io/CharBuffer.java
framework/trunk/impl/src/main/java/org/ajax4jsf/io/FastBufferInputStream.java
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/InternetResourceService.java
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java
framework/trunk/impl/src/main/java/org/ajax4jsf/webapp/PollEventsManager.java
framework/trunk/impl/src/main/java/org/richfaces/VersionBean.java
framework/trunk/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java
framework/trunk/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceCodec.java
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource.java
framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource2.java
framework/trunk/impl/src/main/java/org/richfaces/util/Util.java
Log:
Resources:
- new caches added
- resources versioning added
Property changes on: framework/trunk/impl
___________________________________________________________________
Name: svn:ignore
- .project
.checkstyle
target
.metadata
.settings
+ .project
.checkstyle
target
.metadata
.settings
.classpath
Modified: framework/trunk/impl/pom.xml
===================================================================
--- framework/trunk/impl/pom.xml 2009-07-09 18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/pom.xml 2009-07-09 18:24:28 UTC (rev 14871)
@@ -145,6 +145,16 @@
<artifactId>nekohtml</artifactId>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>org.jboss.cache</groupId>
+ <artifactId>jbosscache-core</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ <optional>true</optional>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/CacheManager.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/CacheManager.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/cache/CacheManager.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -38,9 +38,12 @@
private static final Log log = LogFactory.getLog(CacheManager.class);
private static final String FACTORY_PROPERTY_NAME =
"org.ajax4jsf.cache.CacheFactory";
- private static final String DEFAULT_FACTORY_NAME =
"org.ajax4jsf.cache.LRUMapCacheFactory";
public static final String CACHE_MANAGER_FACTORY_CLASS =
"org.ajax4jsf.cache.CACHE_MANAGER_FACTORY_CLASS";
+ private static final String[] DEFAULT_FACTORIES_CHAIN = {
+ "org.ajax4jsf.cache.JBossCacheCacheFactory",
"org.ajax4jsf.cache.EhCacheCacheFactory"
+ };
+
protected static CacheManager instance = new CacheManager();
// REVIEW brian(a)quiotix.com
@@ -62,23 +65,33 @@
caches.put(cacheName, cache);
}
- public CacheFactory getCacheFactory(Map env) throws CacheException {
- String factoryName = findFactory(FACTORY_PROPERTY_NAME, env);
- log.info("Selected [" + factoryName + "] cache factory");
+ public CacheFactory getCacheFactory(Map env) {
+ String[] factories;
+
+ String configuredFactoryName = findFactory(FACTORY_PROPERTY_NAME, env);
+ if (configuredFactoryName != null) {
+ log.info("Configured to use [" + configuredFactoryName + "]
cache factory");
+ factories = new String[] {configuredFactoryName};
+ } else {
+ factories = DEFAULT_FACTORIES_CHAIN;
+ }
+
+ ClassLoader loader = findClassLoader();
+ for (String factoryName : factories) {
+ try {
+ Class<?> spiClass = Class.forName(factoryName, true, loader);
+ CacheFactory cacheFactory =
CacheFactory.class.cast(spiClass.newInstance());
+
+ log.info("Selected [" + factoryName + "]");
+
+ return cacheFactory;
+ } catch (Throwable iae) {
+ //TODO log debug
+ }
+ }
- try {
- ClassLoader cl = findClassLoader();
- Class spiClass = Class.forName(factoryName, true, cl);
- return (CacheFactory) spiClass.newInstance();
- } catch (ClassNotFoundException cnfe) {
- throw new CacheException("Could not find class: '" +
factoryName + "'");
- } catch (ClassCastException cce) {
- throw new CacheException("Class: '" + factoryName + "'
does not implement CacheFactory");
- } catch (InstantiationException ie) {
- throw new CacheException("Could not instantiate: '" +
factoryName + "'");
- } catch (IllegalAccessException iae) {
- throw new CacheException("Could not find public default constructor for:
'" + factoryName + "'");
- }
+ log.info("Selected fallback cache factory");
+ return new LRUMapCacheFactory();
}
private ClassLoader findClassLoader() {
@@ -140,6 +153,6 @@
} catch (IOException ignore) {
}
- return DEFAULT_FACTORY_NAME;
+ return null;
}
}
Added: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCache.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCache.java
(rev 0)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCache.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import net.sf.ehcache.Ehcache;
+import net.sf.ehcache.Element;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+
+public class EhCacheCache implements org.ajax4jsf.cache.Cache {
+
+ private net.sf.ehcache.Ehcache cache;
+
+ public EhCacheCache(Ehcache cache) {
+ super();
+ this.cache = cache;
+ }
+
+ public void start() {
+ cache.initialise();
+ cache.bootstrap();
+ }
+
+ public void stop() {
+ cache.dispose();
+ }
+
+ public Object get(Object key) {
+ Element element = cache.get(key);
+ if (element != null) {
+ return element.getObjectValue();
+ }
+
+ return null;
+ }
+
+ public void put(Object key, Object value, long expired) {
+ Boolean eternal = null;/* use cache defaults */;
+ Integer ttl = null;
+ if (expired != 0) {
+ eternal = Boolean.FALSE;
+ ttl = (int) (expired - System.currentTimeMillis());
+ }
+
+ Element element = new Element(key, value, eternal, null, ttl);
+ cache.putQuiet(element);
+ }
+}
Added: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCacheFactory.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCacheFactory.java
(rev 0)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/EhCacheCacheFactory.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -0,0 +1,26 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class EhCacheCacheFactory implements CacheFactory {
+
+ private static final Log log = LogFactory.getLog(EhCacheCacheFactory.class);
+
+ public Cache createCache(Map<?, ?> env) {
+ log.info("Creating EhCache cache instance");
+
+ net.sf.ehcache.Ehcache cache = new net.sf.ehcache.Cache("org.richfaces",
256, false, true, 0, 0);
+ return new EhCacheCache(cache);
+ }
+
+}
Added: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCache.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCache.java
(rev 0)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCache.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -0,0 +1,87 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.eviction.ExpirationAlgorithmConfig;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class JBossCacheCache implements org.ajax4jsf.cache.Cache {
+
+ private Cache<String, Object> cache;
+
+ private static final String RESOURCE = "resource";
+
+ public JBossCacheCache(Cache<String, Object> cache) {
+ super();
+
+ this.cache = cache;
+ }
+
+ private Fqn<Object> createFqn(Object key) {
+ return Fqn.fromElements(key);
+ }
+
+ public Object get(Object key) {
+ return cache.get(createFqn(key), RESOURCE);
+ }
+
+ public void put(Object key, Object value, long expired) {
+ Map<String,Object> map = new HashMap<String, Object>(3);
+
+ map.put(RESOURCE, value);
+ if (expired != 0) {
+ map.put(ExpirationAlgorithmConfig.EXPIRATION_KEY, expired);
+ }
+
+ cache.put(createFqn(key), map);
+ Transaction transaction = cache.getInvocationContext().getTransaction();
+ try {
+ //TODO: to review
+ if (transaction != null && transaction.getStatus() == Status.STATUS_ACTIVE) {
+ transaction.commit();
+ }
+ } catch (SystemException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalStateException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (RollbackException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (HeuristicMixedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (HeuristicRollbackException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void start() {
+ cache.start();
+ }
+
+ public void stop() {
+ cache.stop();
+ }
+}
Added: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCacheFactory.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCacheFactory.java
(rev 0)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/JBossCacheCacheFactory.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -0,0 +1,30 @@
+/**
+ *
+ */
+package org.ajax4jsf.cache;
+
+import java.util.Map;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class JBossCacheCacheFactory implements CacheFactory {
+
+ private org.jboss.cache.CacheFactory<String, Object> cacheFactory;
+
+ public JBossCacheCacheFactory() {
+ super();
+
+ cacheFactory = new DefaultCacheFactory<String, Object>();
+ }
+
+ public org.ajax4jsf.cache.Cache createCache(Map<?, ?> env) {
+ Cache<String, Object> cache =
cacheFactory.createCache("/jboss-cache.xml");
+ return new JBossCacheCache(cache);
+ }
+
+}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCache.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCache.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCache.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -21,121 +21,177 @@
package org.ajax4jsf.cache;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Date;
+import java.util.PriorityQueue;
import org.ajax4jsf.util.LRUMap;
/**
* @author Nick - mailto:nbelaevski@exadel.com
- * created 01.05.2007
- *
+ * @since 3.1
*/
-public class LRUMapCache extends LRUMap<Object, Object> implements Cache {
+public class LRUMapCache implements Cache {
- /**
- *
- */
- private static final long serialVersionUID = 3236528957956574490L;
- private CacheLoader cacheLoader;
+ private static final class CacheMap extends LRUMap<Object, CacheEntry> {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5422668357346537621L;
- public LRUMapCache(CacheLoader cacheLoader, int initialSize) {
- super(initialSize);
- this.cacheLoader = cacheLoader;
- }
+ public CacheMap() {
+ super();
+ }
- public LRUMapCache(CacheLoader cacheLoader) {
- super();
- this.cacheLoader = cacheLoader;
- }
+ public CacheMap(int capacity) {
+ super(capacity);
+ }
- public void addListener(CacheListener listener) {
- // TODO Auto-generated method stub
+ private PriorityQueue<CacheEntry> expirationQueue = new
PriorityQueue<CacheEntry>();
- }
+ public CacheEntry put(Object key, CacheEntry value) {
+ CacheEntry entry = super.put(key, value);
+ if (entry != null) {
+ expirationQueue.remove(entry);
+ expirationQueue.add(value);
+ } else {
+ expirationQueue.add(value);
+ }
+
+ return entry;
+ }
- public void evict() {
- // TODO Auto-generated method stub
+ public CacheEntry remove(Object key) {
+ CacheEntry entry = super.remove(key);
+ if (entry != null) {
+ expirationQueue.remove(entry);
+ }
+
+ return entry;
+ }
+ public void clear() {
+ super.clear();
+ expirationQueue.clear();
+ }
+
+ public void purge() {
+ CacheEntry queueEntry = null;
+
+ while ((queueEntry = expirationQueue.peek()) != null &&
queueEntry.isExpired()) {
+ super.remove(queueEntry.getKey());
+ expirationQueue.remove();
+ }
+ }
}
- private Map<Object, LRUMapFuture> futures = new HashMap<Object,
LRUMapFuture>();
+ private static final class CacheEntry implements Comparable<CacheEntry> {
- //TODO review
- public Object get(Object key, Object context) throws CacheException {
+ private Object key;
+
+ private Object value;
+
+ private long expired;
- try {
- LRUMapFuture activeFuture = null;
- LRUMapFuture future = null;
+ public CacheEntry(Object key, Object value, long expired) {
+ super();
+
+ this.key = key;
+ this.value = value;
+ this.expired = expired;
+ }
- synchronized (futures) {
- future = (LRUMapFuture) futures.get(key);
- if (future == null) {
- activeFuture = new LRUMapFuture();
- futures.put(key, activeFuture);
- }
+ public Object getKey() {
+ return key;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+ public boolean isExpired() {
+ if (expired != 0) {
+ return System.currentTimeMillis() >= expired;
+ } else {
+ return false;
}
-
- if (future != null) {
- synchronized (future) {
- future.wait();
- return future.getResult();
- }
+ }
+
+ public int compareTo(CacheEntry o) {
+ if (expired > o.expired) {
+ return 1;
+ } else if (expired < o.expired) {
+ return -1;
} else {
- try {
- if (!containsKey(key)) {
- load(key, context);
- }
+ return 0;
+ }
+ }
- Object result = peek(key);
- activeFuture.setResult(result);
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ return result;
+ }
- return result;
- } finally {
- synchronized (futures) {
- this.futures.remove(key);
-
- synchronized (activeFuture) {
- activeFuture.notifyAll();
- }
- }
- }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CacheEntry other = (CacheEntry) obj;
+ if (key == null) {
+ if (other.key != null)
+ return false;
+ } else if (!key.equals(other.key))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (expired != 0) {
+ return key.toString();
+ } else {
+ return key + ": " + new Date(expired);
}
-
- } catch (InterruptedException e) {
- throw new CacheException(e.getMessage(), e);
}
}
+
+ private CacheMap map;
+
+ public LRUMapCache() {
+ this.map = new CacheMap();
+ }
+
+ public LRUMapCache(int capacity) {
+ this.map = new CacheMap(capacity);
+ }
+
+ public synchronized Object get(Object key) {
+ this.map.purge();
- public CacheEntry getCacheEntry(Object key) {
- // TODO Auto-generated method stub
+ CacheEntry entry = this.map.get(key);
+ if (entry != null) {
+ return entry.getValue();
+ }
+
return null;
}
- public synchronized void load(Object key, Object context) throws CacheException {
- put(key, cacheLoader.load(key, context));
- }
+ public synchronized void put(Object key, Object value, long expired) {
+ this.map.purge();
- public synchronized Object peek(Object key) {
- return this.get(key);
+ CacheEntry cacheEntry = new CacheEntry(key, value, expired);
+ this.map.put(key, cacheEntry);
}
- public void removeListener(CacheListener listener) {
- // TODO Auto-generated method stub
-
+ public void start() {
}
+ public void stop() {
+ this.map.clear();
}
-
-class LRUMapFuture {
- private Object result;
-
- public Object getResult() {
- return result;
- }
-
- public void setResult(Object result) {
- this.result = result;
- }
-}
\ No newline at end of file
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/LRUMapCacheFactory.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -38,20 +38,17 @@
public final static String CACHE_SIZE_PARAMETER =
"org.ajax4jsf.cache.LRU_MAP_CACHE_SIZE";
- public Cache createCache(Map env, CacheLoader cacheLoader, CacheConfigurationLoader
cacheConfigurationloader)
- throws CacheException {
-
+ public Cache createCache(Map<?, ?> env) {
log.info("Creating LRUMap cache instance using parameters: " + env);
String size = (String) env.get(CACHE_SIZE_PARAMETER);
if (size == null || size.length() == 0) {
log.info("Creating LRUMap cache instance of default capacity");
- return new LRUMapCache(cacheLoader);
+ return new LRUMapCache();
} else {
int parsedSize = Integer.parseInt(size);
log.info("Creating LRUMap cache instance of " + parsedSize + " items
capacity");
- return new LRUMapCache(cacheLoader, parsedSize);
+ return new LRUMapCache(parsedSize);
}
}
-
}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCache.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCache.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCache.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -21,13 +21,11 @@
package org.ajax4jsf.cache;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
+import com.opensymphony.oscache.base.EntryRefreshPolicy;
import com.opensymphony.oscache.base.NeedsRefreshException;
+import com.opensymphony.oscache.web.filter.ExpiresRefreshPolicy;
+
/**
* @author Nick - mailto:nbelaevski@exadel.com
* created 01.05.2007
@@ -36,179 +34,39 @@
public class OSCacheCache implements Cache {
private com.opensymphony.oscache.base.Cache cache;
- private CacheLoader cacheLoader;
- public OSCacheCache(com.opensymphony.oscache.base.Cache cache,
- CacheLoader cacheLoader) {
+ public OSCacheCache(com.opensymphony.oscache.base.Cache cache) {
super();
this.cache = cache;
- this.cacheLoader = cacheLoader;
}
- /* (non-Javadoc)
- * @see
org.ajax4jsf.resource.cache.Cache#addListener(org.ajax4jsf.resource.cache.CacheListener)
- */
- public void addListener(CacheListener listener) {
- // TODO Auto-generated method stub
+ public Object get(Object key) {
+ String stringKey = (String) key;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#clear()
- */
- public void clear() {
- // TODO Auto-generated method stub
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#containsKey(java.lang.Object)
- */
- public boolean containsKey(Object key) {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#containsValue(java.lang.Object)
- */
- public boolean containsValue(Object value) {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#entrySet()
- */
- public Set<Entry<Object, Object>> entrySet() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#evict()
- */
- public void evict() {
- // TODO Auto-generated method stub
-
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#get(java.lang.Object, java.lang.Object)
- */
- public Object get(Object key, Object context) throws CacheException {
- String keyString = key.toString();
-
try {
- return cache.getFromCache(keyString);
+ return cache.getFromCache(stringKey);
} catch (NeedsRefreshException e) {
- Object object = cacheLoader.load(key, context);
- try {
- cache.putInCache(keyString, object);
- } catch (Exception e1) {
- cache.cancelUpdate(keyString);
- throw new CacheException(e1.getMessage(), e1);
- }
- return object;
+ cache.removeEntry(stringKey);
+ return null;
}
}
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#getCacheEntry(java.lang.Object)
- */
- public CacheEntry getCacheEntry(Object key) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#isEmpty()
- */
- public boolean isEmpty() {
- // TODO Auto-generated method stub
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#keySet()
- */
- public Set<Object> keySet() {
- // TODO Auto-generated method stub
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#load(java.lang.Object, java.lang.Object)
- */
- public void load(Object key, Object context) throws CacheException {
- cacheLoader.load(key, context);
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#peek(java.lang.Object)
- */
- public Object peek(Object key) {
- String keyString = key.toString();
-
- try {
- return cache.getFromCache(keyString);
- } catch (NeedsRefreshException e) {
- cache.cancelUpdate(keyString);
+ public void put(Object key, Object value, long expired) {
+ EntryRefreshPolicy refreshPolicy = null;
+ if (expired != 0) {
+ int ttl = (int) (expired - System.currentTimeMillis());
+ refreshPolicy = new ExpiresRefreshPolicy(ttl);
}
-
- return null;
+
+ cache.putInCache((String) key, value, refreshPolicy);
}
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#put(java.lang.Object, java.lang.Object)
- */
- public Object put(Object key, Object value) {
- cache.putInCache(key.toString(), value);
- return value;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#putAll(java.util.Map)
- */
- public void putAll(Map<? extends Object, ? extends Object> t) {
+ public void start() {
// TODO Auto-generated method stub
-
}
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#remove(java.lang.Object)
- */
- public Object remove(Object key) {
- String keyString = key.toString();
-
- try {
- return this.peek(keyString);
- } finally {
- cache.removeEntry(keyString);
- }
- }
-
- /* (non-Javadoc)
- * @see
org.ajax4jsf.resource.cache.Cache#removeListener(org.ajax4jsf.resource.cache.CacheListener)
- */
- public void removeListener(CacheListener listener) {
+ public void stop() {
// TODO Auto-generated method stub
-
+
}
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#size()
- */
- public int size() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.Cache#values()
- */
- public Collection<Object> values() {
- // TODO Auto-generated method stub
- return null;
- }
-
}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/cache/OSCacheCacheFactory.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -21,9 +21,13 @@
package org.ajax4jsf.cache;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
import java.util.Map;
import java.util.Properties;
+import org.ajax4jsf.resource.util.URLToStreamHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -38,19 +42,59 @@
private static final Log log = LogFactory.getLog(OSCacheCacheFactory.class);
- /* (non-Javadoc)
- * @see org.ajax4jsf.resource.cache.CacheFactory#createCache(java.util.Map,
org.ajax4jsf.resource.cache.CacheLoader)
- */
- public Cache createCache(Map env, CacheLoader cacheLoader, CacheConfigurationLoader
cacheConfigurationloader)
- throws CacheException {
- // Load our implementation properties
- Properties cacheProperties =
cacheConfigurationloader.loadProperties("oscache.properties");
-
cacheProperties.putAll(cacheConfigurationloader.loadProperties("/oscache.properties"));
+ private Properties loadProperties(URL url) throws IOException {
+ Properties properties = new Properties();
+
+ URL resource = OSCacheCache.class.getResource("oscache.properties");
+ if (resource != null) {
+ InputStream stream = URLToStreamHelper.urlToStream(resource);
+ try {
+ properties.load(stream);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+ return properties;
+ }
+
+ private ClassLoader findClassLoader() {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ if (classLoader == null) {
+ classLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ return classLoader;
+ }
+
+ public Cache createCache(Map<?, ?> env) {
+ Properties cacheProperties = new Properties();
+ try {
+ cacheProperties.putAll(loadProperties(OSCacheCache.class.getResource("oscache.properties")));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ cacheProperties.putAll(loadProperties(findClassLoader().getResource("oscache.properties")));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
cacheProperties.putAll(env);
log.info("Creating OSCache cache instance using parameters: " +
cacheProperties);
GeneralCacheAdministrator cacheAdministrator = new
GeneralCacheAdministrator(cacheProperties);
- return new OSCacheCache(cacheAdministrator.getCache(), cacheLoader);
+ return new OSCacheCache(cacheAdministrator.getCache());
}
}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/io/ByteBuffer.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/io/ByteBuffer.java 2009-07-09 18:18:20
UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/io/ByteBuffer.java 2009-07-09 18:24:28
UTC (rev 14871)
@@ -214,4 +214,6 @@
next = null;
prev = null;
}
+
+ //TODO add compact method
}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/io/CharBuffer.java
===================================================================
--- framework/trunk/impl/src/main/java/org/ajax4jsf/io/CharBuffer.java 2009-07-09 18:18:20
UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/ajax4jsf/io/CharBuffer.java 2009-07-09 18:24:28
UTC (rev 14871)
@@ -217,4 +217,6 @@
next = null;
prev = null;
}
+
+ //TODO add compact method
}
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/io/FastBufferInputStream.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/io/FastBufferInputStream.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/io/FastBufferInputStream.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -52,9 +52,14 @@
* Creates instance of FastBufferInputStream.
* @param stream
*/
+ @Deprecated
public FastBufferInputStream(FastBufferOutputStream stream) {
- this.firstLink = stream.getFirstBuffer();
- current = stream.getFirstBuffer();
+ this(stream.getFirstBuffer());
+ }
+
+ public FastBufferInputStream(ByteBuffer byteBuffer) {
+ this.firstLink = byteBuffer;
+ current = byteBuffer;
index = 0;
mark = 0;
}
Modified:
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/InternetResourceService.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/InternetResourceService.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/InternetResourceService.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -23,7 +23,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Date;
import java.util.Map;
import java.util.Properties;
@@ -41,10 +40,7 @@
import org.ajax4jsf.Messages;
import org.ajax4jsf.cache.Cache;
-import org.ajax4jsf.cache.CacheConfigurationLoader;
-import org.ajax4jsf.cache.CacheException;
import org.ajax4jsf.cache.CacheFactory;
-import org.ajax4jsf.cache.CacheLoader;
import org.ajax4jsf.cache.CacheManager;
import org.ajax4jsf.cache.ServletContextInitMap;
import org.ajax4jsf.resource.util.URLToStreamHelper;
@@ -54,8 +50,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-public class InternetResourceService implements CacheLoader,
- CacheConfigurationLoader {
+public class InternetResourceService {
private static final Log log = LogFactory
.getLog(InternetResourceService.class);
@@ -100,14 +95,10 @@
} else {
// this.cacheAdmin = ServletCacheAdministrator.getInstance(
// servletContext, cacheProperties);
- try {
- CacheManager cacheManager = CacheManager.getInstance();
- Map<String, String> env = new ServletContextInitMap(servletContext);
- CacheFactory cacheFactory = cacheManager.getCacheFactory(env);
- this.cache = cacheFactory.createCache(env, this, this);
- } catch (CacheException e) {
- throw new FacesException(e.getMessage(), e);
- }
+ CacheManager cacheManager = CacheManager.getInstance();
+ Map<String, String> env = new ServletContextInitMap(servletContext);
+ CacheFactory cacheFactory = cacheManager.getCacheFactory(env);
+ this.cache = cacheFactory.createCache(env);
}
// Create Resource-specific Faces Lifecycle instance.
lifecycleClass = servletContext
@@ -184,16 +175,28 @@
.getMessage(Messages.PARSING_IF_MODIFIED_SINCE_WARNING),
e);
}
- String cacheKey = resourceKey;
- CachedResourceContext cachedResourceContext = new CachedResourceContext(
- resourceContext);
-
- CacheContext cacheLoaderContext = new CacheContext(
- cachedResourceContext, resource);
-
+
try {
- CacheContent content = (CacheContent) cache.get(cacheKey,
- cacheLoaderContext);
+ String cacheKey = resourceKey;
+ CachedResourceContext cachedResourceContext = new CachedResourceContext(
+ resourceContext);
+
+ CacheContext cacheLoaderContext = new CacheContext(
+ cachedResourceContext, resource);
+
+ CacheContent content = (CacheContent) cache.get(cacheKey);
+
+ if (content == null) {
+ try {
+ getLifecycle().send(cachedResourceContext, resource);
+ } catch (IOException e) {
+ throw new FacesException(e.getMessage(), e);
+ }
+
+ content = cachedResourceContext.getContent();
+ cache.put(resourceKey, content, resource.getExpired(resourceContext));
+ }
+
if (log.isDebugEnabled()) {
log
.debug(Messages.getMessage(
@@ -209,13 +212,13 @@
response.setDateHeader("Expires", System
.currentTimeMillis()
+ expired);
-// response.addHeader("Cache-control", "max-age="
-// + (expired / 1000L));
+ // response.addHeader("Cache-control", "max-age="
+ // + (expired / 1000L));
if (!request.getMethod().equals("HEAD")) {
content.send(response);
}
content.flush(response);
- } catch (CacheException e) {
+ } catch (Exception e) {
log.error(
Messages.getMessage(Messages.SEND_RESOURCE_ERROR),
e);
@@ -328,21 +331,4 @@
return resourceBuilder;
}
- public Object load(Object key, Object context) throws CacheException {
- CacheContext cacheKey = (CacheContext) context;
- CachedResourceContext resourceContext = cacheKey.getResourceContext();
- try {
- getLifecycle().send(resourceContext, cacheKey.getResource());
- } catch (IOException e) {
- throw new CacheException(e.getMessage(), e);
- }
- // TODO - set refresh interval ?
- // cache.put(cacheKey, resourceContext.getContent());
- return resourceContext.getContent();
- }
-
- public Properties loadProperties(String name) {
- return getProperties(name);
- }
-
}
Modified:
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/resource/ResourceBuilderImpl.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -42,7 +42,7 @@
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.richfaces.resource.LegacyResourceHandlerImpl;
+import org.richfaces.VersionBean;
import org.richfaces.util.Util;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
@@ -266,7 +266,7 @@
public String getUri(InternetResource resource, FacesContext context,
Object storeData) {
- return Util.encodeResourceData(resource.getKey(), storeData);
+ return Util.encodeResourceData(resource.getKey(), storeData,
VersionBean._version.getShortVersion());
}
/**
@@ -315,8 +315,7 @@
// }
public String getFacesResourceURL(FacesContext context, String url, boolean isGlobal) {
- return Util.encodeResourceURL(context,
LegacyResourceHandlerImpl.LEGACY_RESOURCE_IDENTIFIER + url);
- //return getWebXml(context).getFacesResourceURL(context, Url, isGlobal);
+ return getWebXml(context).getFacesResourceURL(context, url, isGlobal);
}
/**
Modified: framework/trunk/impl/src/main/java/org/ajax4jsf/webapp/PollEventsManager.java
===================================================================
---
framework/trunk/impl/src/main/java/org/ajax4jsf/webapp/PollEventsManager.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/ajax4jsf/webapp/PollEventsManager.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -21,65 +21,44 @@
package org.ajax4jsf.webapp;
import java.io.Serializable;
-import java.util.Map;
-import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
-import javax.faces.FacesException;
import javax.servlet.ServletContext;
-import org.ajax4jsf.cache.Cache;
-import org.ajax4jsf.cache.CacheConfigurationLoader;
-import org.ajax4jsf.cache.CacheException;
-import org.ajax4jsf.cache.CacheFactory;
-import org.ajax4jsf.cache.CacheLoader;
-import org.ajax4jsf.cache.CacheManager;
-import org.ajax4jsf.cache.ServletContextInitMap;
-
/**
* @author asmirnov
*
*/
-public class PollEventsManager implements Serializable, CacheLoader,
CacheConfigurationLoader {
+public class PollEventsManager implements Serializable {
- /**
+ /**
*
*/
private static final long serialVersionUID = -6257285396790747665L;
- public static final String EVENTS_MANAGER_KEY=PollEventsManager.class.getName();
+ public static final String EVENTS_MANAGER_KEY = PollEventsManager.class.getName();
- private Cache cache;
-
- public void init(ServletContext servletContext) {
- try {
- CacheManager cacheManager = CacheManager.getInstance();
- Map<String, String> env = new ServletContextInitMap(servletContext);
- CacheFactory cacheFactory = cacheManager.getCacheFactory(env);
- this.cache = cacheFactory.createCache(env, this, this);
+ private ConcurrentMap<String, PushEventsCounter> counters = new
ConcurrentHashMap<String, PushEventsCounter>();
+
+ public void init(ServletContext servletContext) {
servletContext.setAttribute(EVENTS_MANAGER_KEY, this);
- } catch (CacheException e) {
- throw new FacesException(e.getMessage(), e);
}
- }
-
- public PushEventsCounter getListener(String key){
- if(null == cache){
- throw new FacesException("Poll events manager not initialized");
+ public PushEventsCounter getListener(String key){
+ PushEventsCounter counter = counters.get(key);
+ if (counter != null) {
+ return counter;
+ } else {
+ counter = new PushEventsCounter();
+
+ PushEventsCounter oldCounter = counters.putIfAbsent(key, counter);
+ if (oldCounter != null) {
+ return oldCounter;
+ } else {
+ return counter;
+ }
+ }
}
- try {
- return (PushEventsCounter) cache.get(key, null);
- } catch (CacheException e) {
- throw new FacesException("error get push events listener for key
"+key,e);
- }
- }
- public Object load(Object key, Object context) throws CacheException {
- // TODO Auto-generated method stub
- return new PushEventsCounter();
- }
-
- public Properties loadProperties(String name) {
- return new Properties();
- }
}
Modified: framework/trunk/impl/src/main/java/org/richfaces/VersionBean.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/VersionBean.java 2009-07-09 18:18:20
UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/richfaces/VersionBean.java 2009-07-09 18:24:28
UTC (rev 14871)
@@ -64,6 +64,8 @@
public static final String _versionInfo =
"v."+MAJOR_VERSION+"."+MINOR_VERSION+"."+REVISION+SCM_REVISION;
+ public static final String _versionShortInfo =
MAJOR_VERSION+"."+MINOR_VERSION+"."+REVISION;
+
public int getMajor() {
return MAJOR_VERSION;
}
@@ -75,6 +77,11 @@
public String getRevision() {
return REVISION;
}
+
+ public String getShortVersion() {
+ return _versionShortInfo;
+ }
+
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
Added: framework/trunk/impl/src/main/java/org/richfaces/resource/AbstractResource.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/resource/AbstractResource.java
(rev 0)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/AbstractResource.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -0,0 +1,101 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package org.richfaces.resource;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.faces.application.Resource;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+import org.richfaces.util.Util;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public abstract class AbstractResource extends Resource {
+
+ private static final Pattern ETAG_PATTERN =
Pattern.compile("(?:W/)?\"([^\"]+)\"(?:,\\s*)?");
+
+ protected abstract Date getLastModified(FacesContext context);
+
+ protected abstract boolean isCacheable(FacesContext context);
+
+ protected abstract String getEntityTag(FacesContext context);
+
+ private boolean userCopyIsStale(Date lastModified, Date modifiedCondition) {
+ if (lastModified == null || modifiedCondition == null) {
+ return true;
+ }
+
+ // 1000 ms due to round
+ // modification
+ // time to seconds.
+ return (lastModified.getTime() - modifiedCondition.getTime()) > 1000;
+ }
+
+ @Override
+ public boolean userAgentNeedsUpdate(FacesContext context) {
+ if (!isCacheable(context)) {
+ return true;
+ }
+
+ ExternalContext externalContext = context.getExternalContext();
+ Map<String, String> requestHeaderMap = externalContext.getRequestHeaderMap();
+
+ String matchCondition = requestHeaderMap.get("If-None-Match");
+ String modifiedCondition = requestHeaderMap.get("If-Modified-Since");
+
+ if (matchCondition != null) {
+ String resourceEntityTag = getEntityTag(context);
+ if (resourceEntityTag != null) {
+ Matcher matcher = ETAG_PATTERN.matcher(resourceEntityTag);
+ matcher.find();
+ if (matcher.groupCount() > 0) {
+ resourceEntityTag = matcher.group(1);
+ }
+ }
+
+ Matcher eTagMatcher = ETAG_PATTERN.matcher(matchCondition);
+ while (eTagMatcher.find()) {
+ String conditionEntityTag = eTagMatcher.group(1);
+
+ if (conditionEntityTag.equals(resourceEntityTag)) {
+ if (modifiedCondition == null) {
+ return false;
+ } else {
+ return userCopyIsStale(getLastModified(context),
+ Util.parseHttpDate(modifiedCondition));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return userCopyIsStale(getLastModified(context),
Util.parseHttpDate(modifiedCondition));
+ }
+
+}
Deleted: framework/trunk/impl/src/main/java/org/richfaces/resource/BaseResource.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/resource/BaseResource.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/richfaces/resource/BaseResource.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,10 +0,0 @@
-package org.richfaces.resource;
-
-public abstract class BaseResource {
-
- public abstract String getVersion();
-
- public abstract boolean isCryptable();
-
- public abstract String getContentType();
-}
Modified:
framework/trunk/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/CachedResourceImpl.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,10 +1,25 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.richfaces.resource;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -17,25 +32,34 @@
import javax.faces.application.Resource;
import javax.faces.context.FacesContext;
+import org.ajax4jsf.io.ByteBuffer;
+import org.ajax4jsf.io.FastBufferInputStream;
+import org.ajax4jsf.io.FastBufferOutputStream;
import org.richfaces.util.Util;
/**
* @author Nick Belaevski
* @since 4.0
*/
-public class CachedResourceImpl extends ResourceImpl {
+class CachedResourceImpl extends AbstractResource {
+ //TODO use configuration parameter
+ private static final long DEFAULT_EXPIRE = 60 * 1000;
+
private Map<String, String> headers;
- private byte[] content;
+ private ByteBuffer content;
private String entityTag;
private Date lastModified;
+ private long expired = 0;
+
private void initializeFromHeaders() {
this.entityTag = null;
this.lastModified = null;
+ this.expired = 0;
for (Entry<String, String> headerEntry: headers.entrySet()) {
String headerKey = headerEntry.getKey().toLowerCase(Locale.US);
@@ -43,13 +67,26 @@
this.entityTag = headerEntry.getValue();
} else if ("last-modified".equals(headerKey)) {
this.lastModified = Util.parseHttpDate(headerEntry.getValue());
+ } else if ("expires".equals(headerKey)) {
+ Date expiredDate = Util.parseHttpDate(headerEntry.getValue());
+ if (expiredDate != null) {
+ long expirationTime = expiredDate.getTime();
+ long currentTime = System.currentTimeMillis();
+
+ // ttl = expireTime - currentTime
+ // 0.9 * ttl + currentTime
+ this.expired = (long) (0.9 * expirationTime + 0.1 * currentTime);
+ }
}
}
+ if (this.expired == 0) {
+ this.expired = System.currentTimeMillis() + DEFAULT_EXPIRE;
+ }
}
- private byte[] readContent(InputStream is) throws IOException {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
+ private ByteBuffer readContent(InputStream is) throws IOException {
+ FastBufferOutputStream os = new FastBufferOutputStream();
try {
Util.copyStreamContent(is, os);
} finally {
@@ -65,7 +102,7 @@
os.close();
}
- return os.toByteArray();
+ return os.getFirstBuffer();
}
public void initialize(Resource resource) {
@@ -83,7 +120,7 @@
@Override
public InputStream getInputStream() {
- return new ByteArrayInputStream(content);
+ return new FastBufferInputStream(content);
}
@Override
@@ -102,11 +139,6 @@
}
@Override
- public String getContentType(FacesContext context) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public boolean isCacheable(FacesContext context) {
return true;
}
@@ -121,4 +153,7 @@
return lastModified;
}
+ public long getExpired(FacesContext context) {
+ return expired;
+ }
}
Modified:
framework/trunk/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,6 +1,24 @@
/**
- *
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
package org.richfaces.resource;
import org.richfaces.util.Util;
@@ -13,10 +31,6 @@
}
- public String encodeResource(String resourceName, Object resourceData) {
- return Util.encodeResourceData(resourceName, resourceData);
- }
-
public String decodeResourceName(String resourceKey) {
return Util.getResourceName(resourceKey);
}
@@ -29,4 +43,13 @@
return CODEC;
}
+ public String decodeResourceVersion(String resourceKey) {
+ return Util.getResourceVersion(resourceKey);
+ }
+
+ public String encodeResource(String resourceName, Object resourceData,
+ String resourceVersion) {
+ return Util.encodeResourceData(resourceName, resourceData, resourceVersion);
+ }
+
}
\ No newline at end of file
Deleted:
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceHandlerImpl.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceHandlerImpl.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceHandlerImpl.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,280 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2009 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.richfaces.resource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.faces.FacesException;
-import javax.faces.application.Resource;
-import javax.faces.application.ResourceHandler;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.HttpServletResponse;
-
-import org.ajax4jsf.cache.Cache;
-import org.ajax4jsf.cache.CacheConfigurationLoader;
-import org.ajax4jsf.cache.CacheException;
-import org.ajax4jsf.cache.CacheFactory;
-import org.ajax4jsf.cache.CacheLoader;
-import org.ajax4jsf.cache.CacheManager;
-import org.ajax4jsf.resource.CacheContext;
-import org.ajax4jsf.resource.CachedResourceContext;
-import org.ajax4jsf.resource.FacesResourceContext;
-import org.ajax4jsf.resource.InternetResource;
-import org.ajax4jsf.resource.InternetResourceBuilder;
-import org.ajax4jsf.resource.ResourceNotFoundException;
-import org.ajax4jsf.resource.util.URLToStreamHelper;
-import org.ajax4jsf.webapp.BaseFilter;
-import org.ajax4jsf.webapp.CacheContent;
-import org.richfaces.util.Util;
-import org.richfaces.util.RequestStateManager.BooleanRequestStateVariable;
-
-/**
- * @author Nick Belaevski
- * @since 4.0
- */
-public class LegacyResourceHandlerImpl extends ResourceHandler implements CacheLoader,
CacheConfigurationLoader {
-
- public static final String LEGACY_RESOURCE_IDENTIFIER = "/rfResLegacy/";
-
- private ResourceHandler defaultHandler;
-
- private Cache cache;
-
- public LegacyResourceHandlerImpl(ResourceHandler defaultHandler) {
- super();
- this.defaultHandler = defaultHandler;
-
- initializeCache();
- }
-
- private void initializeCache() {
- try {
- CacheManager cacheManager = CacheManager.getInstance();
-
- FacesContext facesContext = FacesContext.getCurrentInstance();
- Map<String, Object> applicationMap =
facesContext.getExternalContext().getApplicationMap();
-
- CacheFactory cacheFactory = cacheManager.getCacheFactory(applicationMap);
- this.cache = cacheFactory.createCache(applicationMap, this, this);
- } catch (CacheException e) {
- throw new FacesException(e.getMessage(), e);
- }
- }
-
- //TODO copied code - move to superclass
- protected String getResourceKey(FacesContext context) {
- String resourceName = Util.decodeResourceURL(context);
- if (resourceName != null) {
- if (resourceName.startsWith(LEGACY_RESOURCE_IDENTIFIER)) {
- return resourceName.substring(LEGACY_RESOURCE_IDENTIFIER.length());
- } else {
- return null;
- }
- } else {
- //TODO log
- return null;
- }
- }
-
- protected boolean isThisHandlerResourceRequest(FacesContext context) {
- Boolean resourceRequest =
BooleanRequestStateVariable.LEGACY_RESOURCE_REQUEST.get(context);
- if (resourceRequest == null) {
- String resourceName = getResourceKey(context);
- //TODO handle exclusions
- resourceRequest = resourceName != null ? Boolean.TRUE : Boolean.FALSE;
- BooleanRequestStateVariable.LEGACY_RESOURCE_REQUEST.set(context, resourceRequest);
- }
-
- return resourceRequest.booleanValue();
- }
-
- public boolean isResourceRequest(FacesContext context) {
- return isThisHandlerResourceRequest(context) ||
defaultHandler.isResourceRequest(context);
- }
-
-
- private Date getIfModifiedSince(ExternalContext externalContext) {
- String ifModifiedSince =
externalContext.getRequestHeaderMap().get("If-Modified-Since");
- return Util.parseHttpDate(ifModifiedSince);
- }
-
- private boolean needsUpdate(Date serverLastModified, Date clientLastModified) {
- if (clientLastModified == null) {
- return true;
- } else {
- // 1000 ms due to round
- // modification
- // time to seconds.
- long serverLastModifiedTime = serverLastModified.getTime() - 1000;
-
- return serverLastModifiedTime > clientLastModified.getTime();
- }
- }
-
- public void handleResourceRequest(FacesContext context) throws IOException {
- if (isThisHandlerResourceRequest(context)) {
- String resourceKey = getResourceKey(context);
- InternetResourceBuilder resourceBuilder = InternetResourceBuilder.getInstance();
-
- InternetResource internetResource = null;// getInternetResource(request);
- try {
- internetResource = resourceBuilder.getResourceForKey(resourceKey);
- Object resourceDataForKey = resourceBuilder.getResourceDataForKey(
- resourceKey);
-
- //TODO release resource context
- ExternalContext externalContext = context.getExternalContext();
- FacesResourceContext resourceContext = new FacesResourceContext(context);
- try {
- resourceContext.setResourceData(resourceDataForKey);
- if (internetResource.isCacheable(resourceContext)) {
- Date clientDate = getIfModifiedSince(externalContext);
- Date serverDate = internetResource.getLastModified(resourceContext);
-
- if (needsUpdate(serverDate, clientDate)) {
- CachedResourceContext cachedResourceContext = new
CachedResourceContext(resourceContext);
- try {
- CacheContext cacheLoaderContext = new CacheContext(cachedResourceContext,
internetResource);
- CacheContent cacheContent = (CacheContent) cache.get(resourceKey,
cacheLoaderContext);
-
- cacheContent.sendHeaders(externalContext);
-
- long expired = internetResource.getExpired(resourceContext);
- if (expired < 0 ) {
- expired = InternetResource.DEFAULT_EXPIRE;
- }
-
- externalContext.setResponseHeader("Expires",
- Util.formatHttpDate(System.currentTimeMillis() + expired));
-// response.addHeader("Cache-control", "max-age="
-// + (expired / 1000L));
-
- //TODO where from to get method?
- //if (request.getMethod().equals("HEAD")) {
- cacheContent.send(externalContext);
- //}
-
- cacheContent.flush(externalContext);
-
- } catch (CacheException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- cachedResourceContext.release();
- }
- } else {
- externalContext.setResponseStatus(HttpServletResponse.SC_NOT_MODIFIED);
- }
- } else {
- internetResource.sendHeaders(resourceContext);
- internetResource.send(resourceContext);
- }
- } finally {
- resourceContext.release();
- }
- } catch (ResourceNotFoundException e) {
- //TODO
- context.getExternalContext().setResponseStatus(HttpServletResponse.SC_NOT_FOUND);
- }
- } else {
- defaultHandler.handleResourceRequest(context);
- }
- }
-
- public Resource createResource(String resourceName, String libraryName,
- String contentType) {
-
- Resource resource = null;
-
- if (libraryName == null || libraryName.length() == 0) {
- InternetResourceBuilder builder = InternetResourceBuilder.getInstance();
- try {
- InternetResource legacyResource = builder.getResource(resourceName);
- resource = new LegacyResourceWrapper(legacyResource);
- } catch (ResourceNotFoundException e) {
- // TODO log
- }
- }
-
- if (resource == null) {
- resource = defaultHandler.createResource(resourceName, libraryName, contentType);
- }
-
- return resource;
- }
-
- public Resource createResource(String resourceName, String libraryName) {
- return createResource(resourceName, libraryName, null);
- }
-
- public Resource createResource(String resourceName) {
- return createResource(resourceName, null, null);
- }
-
- public String getRendererTypeForResourceName(String resourceName) {
- return defaultHandler.getRendererTypeForResourceName(resourceName);
- }
-
- public boolean libraryExists(String libraryName) {
- return defaultHandler.libraryExists(libraryName);
- }
-
- public Object load(Object key, Object context) throws CacheException {
- CacheContext cacheKey = (CacheContext) context;
- CachedResourceContext resourceContext = cacheKey.getResourceContext();
- try {
- InternetResource resource = cacheKey.getResource();
- resource.sendHeaders(resourceContext);
- resource.send(resourceContext);
- } catch (IOException e) {
- throw new CacheException(e.getMessage(), e);
- }
- // TODO - set refresh interval ?
- // cache.put(cacheKey, resourceContext.getContent());
- return resourceContext.getContent();
- }
-
- public Properties loadProperties(String name) {
- Properties properties = new Properties();
- InputStream props =
URLToStreamHelper.urlToStreamSafe(BaseFilter.class.getResource(name));
- if (null != props) {
- try {
- properties.load(props);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- } finally {
- try {
- props.close();
- } catch (IOException e) {
- // Can be ignored
- }
- }
- }
- return properties;
- }
-
-}
Deleted:
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceWrapper.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceWrapper.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/LegacyResourceWrapper.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,87 +0,0 @@
-/**
- * License Agreement.
- *
- * JBoss RichFaces - Ajax4jsf Component Library
- *
- * Copyright (C) 2009 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.richfaces.resource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Map;
-
-import javax.faces.application.Resource;
-import javax.faces.context.FacesContext;
-
-import org.ajax4jsf.resource.InternetResource;
-
-/**
- * @author Nick Belaevski
- * @since 4.0
- */
-class LegacyResourceWrapper extends Resource {
-
- private InternetResource resource;
-
- public LegacyResourceWrapper(InternetResource resource) {
- this.resource = resource;
- }
-
- /* (non-Javadoc)
- * @see javax.faces.application.Resource#getInputStream()
- */
- @Override
- public InputStream getInputStream() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- /* (non-Javadoc)
- * @see javax.faces.application.Resource#getRequestPath()
- */
- @Override
- public String getRequestPath() {
- //TODO pass resource data
- return this.resource.getUri(FacesContext.getCurrentInstance(), null);
- }
-
- /* (non-Javadoc)
- * @see javax.faces.application.Resource#getResponseHeaders()
- */
- @Override
- public Map<String, String> getResponseHeaders() {
- throw new UnsupportedOperationException();
- }
-
- /* (non-Javadoc)
- * @see javax.faces.application.Resource#getURL()
- */
- @Override
- public URL getURL() {
- throw new UnsupportedOperationException();
- }
-
- /* (non-Javadoc)
- * @see
javax.faces.application.Resource#userAgentNeedsUpdate(javax.faces.context.FacesContext)
- */
- @Override
- public boolean userAgentNeedsUpdate(FacesContext context) {
- throw new UnsupportedOperationException();
- }
-
-}
Modified: framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceCodec.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceCodec.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceCodec.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -9,10 +9,11 @@
*/
public interface ResourceCodec {
- public String encodeResource(String resourceName, Object resourceData);
+ public String encodeResource(String resourceName, Object resourceData, String
resourceVersion);
public String decodeResourceName(String resourceKey);
public Object decodeResourceData(String resourceKey);
+ public String decodeResourceVersion(String resourceKey);
}
Modified:
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -37,6 +37,9 @@
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
+import org.ajax4jsf.cache.Cache;
+import org.ajax4jsf.cache.CacheFactory;
+import org.ajax4jsf.cache.CacheManager;
import org.richfaces.util.Util;
import org.richfaces.util.RequestStateManager.BooleanRequestStateVariable;
@@ -50,10 +53,23 @@
private ResourceHandler defaultHandler;
+ private Cache cache;
+
public ResourceHandlerImpl(ResourceHandler defaultHandler) {
this.defaultHandler = defaultHandler;
+
+ initializeCache();
}
+ private void initializeCache() {
+ CacheManager cacheManager = CacheManager.getInstance();
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ Map<?, ?> envMap = facesContext.getExternalContext().getInitParameterMap();
+
+ CacheFactory cacheFactory = cacheManager.getCacheFactory(envMap);
+ this.cache = cacheFactory.createCache(envMap);
+ }
+
private static final String RESOURCE_CODEC_ATTRIBUTE_NAME =
ResourceHandlerImpl.class.getName() + ":ResourceCodec";
@@ -125,26 +141,63 @@
return;
}
- ResourceCodec resourceCodec = ResourceHandlerImpl.getResourceCodec(context);
- String resourceName = resourceCodec.decodeResourceName(resourceKey);
- if (resourceName == null) {
- sendNotFound(context);
- return;
- }
-
- Resource resource = createHandlerDepenendentResource(resourceName, null, null);
+ Resource resource = (Resource) cache.get(resourceKey);
if (resource == null) {
- sendNotFound(context);
- return;
+ ResourceCodec resourceCodec = ResourceHandlerImpl.getResourceCodec(context);
+ String resourceName = resourceCodec.decodeResourceName(resourceKey);
+ if (resourceName == null) {
+ sendNotFound(context);
+ return;
+ }
+
+ resource = createHandlerDependentResource(resourceName, null, null);
+ if (resource == null) {
+ sendNotFound(context);
+ return;
+ }
+
+ if (resource instanceof VersionedResource) {
+ VersionedResource versionedResource = (VersionedResource) resource;
+ String version = versionedResource.getVersion();
+ String requestedVersion = resourceCodec.decodeResourceVersion(resourceKey);
+ if (version != null && requestedVersion != null &&
+ !version.equals(requestedVersion)) {
+
+ sendNotFound(context);
+ return;
+ }
+ }
+
+ if (resource instanceof StateHolder) {
+ StateHolder stateHolder = (StateHolder) resource;
+ stateHolder.restoreState(context, resourceCodec.decodeResourceData(resourceKey));
+ } else {
+ //TODO log
+ }
+
+ if (resource instanceof ResourceImpl) {
+ ResourceImpl resourceImpl = (ResourceImpl) resource;
+
+ if (resourceImpl.isCacheable(context)) {
+ //TODO - we could move this part of code to ConcurrentMap so that
+ //only single thread does resource put
+ CachedResourceImpl cachedResource = new CachedResourceImpl();
+ cachedResource.initialize(resource);
+
+ //someone may provided this resource for us
+ //while we were reading it, check once again
+ resource = (Resource) cache.get(resourceKey);
+ if (resource == null) {
+ cache.put(resourceKey, cachedResource,
+ cachedResource.getExpired(context));
+ resource = cachedResource;
+ }
+ }
+ }
}
ExternalContext externalContext = context.getExternalContext();
- if (resource instanceof StateHolder) {
- StateHolder stateHolder = (StateHolder) resource;
- stateHolder.restoreState(context, resourceCodec.decodeResourceData(resourceKey));
- }
-
if (resource.userAgentNeedsUpdate(context)) {
Map<String, String> headers = resource.getResponseHeaders();
for (Entry<String, String> headerEntry : headers.entrySet()) {
@@ -165,6 +218,7 @@
}
}
+ //TODO setup output buffer size according to configuration parameter
InputStream is = resource.getInputStream();
OutputStream os = externalContext.getResponseOutputStream();
@@ -190,7 +244,7 @@
}
}
- protected Resource createHandlerDepenendentResource(String resourceName, String
libraryName,
+ protected Resource createHandlerDependentResource(String resourceName, String
libraryName,
String contentType) {
Resource resource = null;
@@ -226,7 +280,7 @@
public Resource createResource(String resourceName, String libraryName,
String contentType) {
- Resource resource = createHandlerDepenendentResource(resourceName, libraryName,
contentType);
+ Resource resource = createHandlerDependentResource(resourceName, libraryName,
contentType);
if (resource == null) {
resource = defaultHandler.createResource(resourceName, libraryName, contentType);
}
Modified: framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceImpl.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/richfaces/resource/ResourceImpl.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -30,13 +30,9 @@
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import javax.faces.FacesException;
-import javax.faces.application.Resource;
import javax.faces.component.StateHolder;
-import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.ajax4jsf.resource.InternetResource;
@@ -47,7 +43,7 @@
* @author Nick Belaevski
* @since 4.0
*/
-public abstract class ResourceImpl extends Resource {
+public abstract class ResourceImpl extends AbstractResource implements VersionedResource
{
public static final String URL_PROTOCOL = "jsfResource";
@@ -141,14 +137,23 @@
@Override
public abstract InputStream getInputStream();
- public String getVersion() {
- return null;
+ public abstract String getVersion();
+
+ protected String escapeVersionString(String version) {
+ if (version != null) {
+ return version.replaceAll("[\\W]", "_");
+ }
+
+ return version;
}
@Override
public String getRequestPath() {
FacesContext context = FacesContext.getCurrentInstance();
+ ResourceCodec resourceCodec = ResourceHandlerImpl.getResourceCodec(context);
+
+ String resourceName = getResourceName();
Object resourceData = null;
if (this instanceof StateHolder) {
StateHolder stateHolder = (StateHolder) this;
@@ -156,19 +161,14 @@
resourceData = stateHolder.saveState(context);
}
}
+
+ String resourceVersion = getVersion();
- ResourceCodec resourceCodec = ResourceHandlerImpl.getResourceCodec(context);
String resourceUri = ResourceHandlerImpl.RICHFACES_RESOURCE_IDENTIFIER +
- resourceCodec.encodeResource(getResourceName(), resourceData);
+ resourceCodec.encodeResource(resourceName, resourceData, resourceVersion);
- String url = Util.encodeResourceURL(context, resourceUri);
-
- String version = getVersion();
- if (version != null && version.length() > 0) {
- url += "?v=" + version;
- }
-
- return url;
+ resourceUri = Util.encodeResourceURL(context, resourceUri);
+ return resourceUri;
}
private boolean isResourceRequest() {
@@ -277,53 +277,4 @@
throw new FacesException(e.getLocalizedMessage(), e);
}
}
-
- private static final Pattern ETAG_PATTERN =
Pattern.compile("(?:W/)?\"([^\"]+)\"(?:,\\s*)?");
-
- private boolean userCopyIsStale(Date lastModified, Date modifiedCondition) {
- if (lastModified == null || modifiedCondition == null) {
- return true;
- }
-
- // 1000 ms due to round
- // modification
- // time to seconds.
- return (lastModified.getTime() - modifiedCondition.getTime()) > 1000;
- }
-
- @Override
- public boolean userAgentNeedsUpdate(FacesContext context) {
- if (!isCacheable(context)) {
- return true;
- }
-
- ExternalContext externalContext = context.getExternalContext();
- Map<String, String> requestHeaderMap = externalContext.getRequestHeaderMap();
-
- String matchCondition = requestHeaderMap.get("If-None-Match");
- String modifiedCondition = requestHeaderMap.get("If-Modified-Since");
-
- String resourceEntityTag = getEntityTag(context);
-
- if (matchCondition != null) {
- Matcher eTagMatcher = ETAG_PATTERN.matcher(matchCondition);
- while (eTagMatcher.find()) {
- String conditionEntityTag = eTagMatcher.group(1);
-
- if (conditionEntityTag.equals(resourceEntityTag)) {
- if (modifiedCondition == null) {
- return false;
- } else {
- return userCopyIsStale(getLastModified(context),
- Util.parseHttpDate(modifiedCondition));
- }
- }
- }
-
- return true;
- }
-
- return userCopyIsStale(getLastModified(context),
Util.parseHttpDate(modifiedCondition));
- }
-
}
Modified: framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource.java 2009-07-09
18:18:20 UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,3 +1,24 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
package org.richfaces.resource;
import java.io.ByteArrayInputStream;
Modified: framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource2.java
===================================================================
---
framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource2.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/main/java/org/richfaces/resource/TestResource2.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,3 +1,24 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
package org.richfaces.resource;
import java.awt.Color;
@@ -11,6 +32,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Date;
import javax.faces.component.StateHolder;
import javax.faces.context.FacesContext;
@@ -18,6 +40,7 @@
import org.ajax4jsf.util.HtmlColor;
import org.ajax4jsf.util.Zipper2;
+import org.richfaces.VersionBean;
import org.richfaces.skin.Skin;
import org.richfaces.skin.SkinFactory;
@@ -37,7 +60,7 @@
return "image/png";
}
- private Dimension dimension = new Dimension(200, 150);
+ private Dimension dimension = new Dimension(20, 150);
@Override
public InputStream getInputStream() {
@@ -87,4 +110,19 @@
public String getEntityTag(FacesContext context) {
return Integer.toHexString(color.getRGB() & 0xFFFFFF);
}
+
+ @Override
+ protected long getExpired(FacesContext context) {
+ return 10000;
+ }
+
+ @Override
+ protected Date getLastModified(FacesContext context) {
+ return new Date();
+ }
+
+ @Override
+ public String getVersion() {
+ return escapeVersionString(VersionBean._version.getShortVersion());
+ }
}
Modified: framework/trunk/impl/src/main/java/org/richfaces/util/Util.java
===================================================================
--- framework/trunk/impl/src/main/java/org/richfaces/util/Util.java 2009-07-09 18:18:20
UTC (rev 14870)
+++ framework/trunk/impl/src/main/java/org/richfaces/util/Util.java 2009-07-09 18:24:28
UTC (rev 14871)
@@ -146,10 +146,17 @@
private static final String DATA_SEPARATOR = "/DATA/";
private static final String DATA_BYTES_SEPARATOR = "/DATB/";
+ private static final String VERSION_SEPARATOR = "/VER";
private static final Pattern DATA_SEPARATOR_PATTERN = Pattern
- .compile("/DAT(A|B)/");
+ .compile("/DAT(A|B)/([^/]*)");
+ //index of capturing group denoting data type encoded
+ private static final int DATA_SEPARATOR_TYPE_GROUP_INDEX = 1;
+
+ //index of capturing group denoting version
+ private static final int DATA_SEPARATOR_DATA_GROUP_INDEX = 2;
+
protected static byte[] encrypt(byte[] src) {
try {
Deflater compressor = new Deflater(Deflater.BEST_SPEED);
@@ -182,8 +189,10 @@
}
}
- public static String encodeResourceData(String resourceName, Object storeData) {
- StringBuffer uri = new StringBuffer();//
ResourceServlet.DEFAULT_SERVLET_PATH).append("/");
+ public static String encodeResourceData(String resourceName, Object storeData,
+ String resourceVersion) {
+
+ StringBuffer uri = new StringBuffer();//
ResourceServlet.DEFAULT_SERVLET_PATH).append("/");
uri.append(resourceName);
// append serialized data as Base-64 encoded request string.
if (storeData != null) {
@@ -218,7 +227,11 @@
}
}
- //boolean isGlobal = !resource.isSessionAware();
+ if (resourceVersion != null && resourceVersion.length() != 0) {
+ uri.append(VERSION_SEPARATOR);
+ uri.append(resourceVersion);
+ }
+//boolean isGlobal = !resource.isSessionAware();
// String resourceURL = getFacesResourceURL(context,
// uri.toString(), false /*isGlobal*/);//
context.getApplication().getViewHandler().getResourceURL(context,uri.toString());
@@ -239,12 +252,25 @@
if (matcher.find()) {
int data = matcher.start();
resourceName = resourceName.substring(0, data);
+ } else {
+ int idx = resourceName.indexOf(VERSION_SEPARATOR);
+ if (idx > 0) {
+ resourceName = resourceName.substring(0, idx);
+ }
}
return resourceName;
}
-
+ public static String getResourceVersion(String resourceUri) {
+ int idx = resourceUri.indexOf(VERSION_SEPARATOR);
+ if (idx > 0) {
+ return resourceUri.substring(idx + VERSION_SEPARATOR.length());
+ }
+
+ return null;
+ }
+
public static Object getResourceData(String resourceUri) {
Object data = null;
String dataString = null;
@@ -255,8 +281,7 @@
// Messages.RESTORE_DATA_FROM_RESOURCE_URI_INFO, resourceUri,
// dataString));
// }
- int dataStart = matcher.end();
- dataString = resourceUri.substring(dataStart);
+ dataString = matcher.group(DATA_SEPARATOR_DATA_GROUP_INDEX);
byte[] objectArray = null;
byte[] dataArray;
try {
@@ -265,7 +290,7 @@
} catch (UnsupportedEncodingException e1) {
// default encoding always presented.
}
- if ("B".equals(matcher.group(1))) {
+ if ("B".equals(matcher.group(DATA_SEPARATOR_TYPE_GROUP_INDEX))) {
data = objectArray;
} else {
try {
Deleted:
framework/trunk/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java
===================================================================
---
framework/trunk/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-07-09
18:18:20 UTC (rev 14870)
+++
framework/trunk/impl/src/test/java/org/ajax4jsf/cache/LRUMapCacheThreadedTest.java 2009-07-09
18:24:28 UTC (rev 14871)
@@ -1,104 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-package org.ajax4jsf.cache;
-
-import java.util.Random;
-
-import junit.framework.TestCase;
-
-/**
- * @author Nick - mailto:nbelaevski@exadel.com
- * created 02.05.2007
- *
- */
-public class LRUMapCacheThreadedTest extends TestCase {
- private CacheLoader cacheLoader = new CacheLoader() {
-
- public Object load(Object key, Object context) throws CacheException {
- try {
- Thread.sleep(new Random().nextInt(100) + 1);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return key;
- }
- };
-
- private static final int COUNT = 500;
- private static final int PASS_COUNT = 2;
-
-
- public void testCache() throws Exception {
- long millis = System.currentTimeMillis();
-
- for (int k = 0; k < PASS_COUNT; k++) {
- Cache cache = new LRUMapCache(cacheLoader, COUNT);
- Thread[] threads = new Thread[COUNT];
-
- try {
- for (int i = 0; i < COUNT; i++) {
- try {
- threads[i] = new LRUMapCacheTestThread(cache, new Integer(new
Random().nextInt(10)));
- threads[i].start();
- } catch (OutOfMemoryError e) {
- System.out.println("Out of memory pass:"+k+" thread: "+i);
- throw e;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- for (int i = 0; i < COUNT; i++) {
- threads[i].join();
- }
- }
-
- System.out.println((double) (System.currentTimeMillis() - millis) / PASS_COUNT);
- }
-}
-
-class LRUMapCacheTestThread extends Thread {
- private Cache cache;
- private Integer idx;
-
- public LRUMapCacheTestThread(Cache cache, Integer idx) {
- super();
- this.cache = cache;
- this.idx = idx;
- }
-
- public void run() {
- super.run();
-
- try {
- if (!idx.equals(cache.get(idx, null))) {
- throw new IllegalStateException();
- } else {
- // System.out.println("TestThread.run(): " + idx);
- }
- } catch (CacheException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-}
\ No newline at end of file