Author: nbelaevski
Date: 2009-07-01 08:48:44 -0400 (Wed, 01 Jul 2009)
New Revision: 14758
Added:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodec.java
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodecAware.java
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
Removed:
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodec.java
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodecAware.java
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceImpl.java
Modified:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java
Log:
Resources: refactoring
Deleted:
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodec.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodec.java 2009-07-01
12:45:49 UTC (rev 14757)
+++
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodec.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -1,17 +0,0 @@
-/**
- *
- */
-package org.ajax4jsf.resource;
-
-/**
- * @author Nick Belaevski
- * @since 4.0
- */
-public interface ResourceCodec {
-
- public String encodeResource(String resourceName, Object resourceData);
-
- public String decodeResourceName(String resourceKey);
-
- public Object decodeResourceData(String resourceKey);
-}
Deleted:
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodecAware.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodecAware.java 2009-07-01
12:45:49 UTC (rev 14757)
+++
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceCodecAware.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -1,14 +0,0 @@
-/**
- *
- */
-package org.ajax4jsf.resource;
-
-/**
- * @author Nick Belaevski
- * @since 4.0
- */
-public interface ResourceCodecAware {
-
- public void setResourceCodec(ResourceCodec codec);
-
-}
Deleted:
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceImpl.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceImpl.java 2009-07-01
12:45:49 UTC (rev 14757)
+++
branches/jsf2.0/framework/impl/src/main/java/org/ajax4jsf/resource/ResourceImpl.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -1,326 +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.resource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-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.richfaces.resource.ResourceHandlerImpl;
-import org.richfaces.util.Util;
-
-/**
- * @author Nick Belaevski
- * @since 4.0
- */
-public abstract class ResourceImpl extends Resource implements ResourceCodecAware {
-
- public static final String URL_PROTOCOL = "jsfResource";
-
- private boolean cacheable = true;
-
- private Date lastModified = null;
-
- private boolean useLocalLastModified = false;
-
- private ResourceCodec resourceCodec;
-
- /**
- * @param resourceContext current {@link ResourceContext}
- * @return Returns the contentLength.
- */
- protected int getContentLength(FacesContext context) {
- return -1;
- }
-
- /**
- * @param resourceContext current {@link ResourceContext}
- * @return Returns the expired.
- */
- protected long getExpired(FacesContext context) {
- return 0;
- }
-
- /**
- * @param resourceContext current {@link ResourceContext}
- * @return Returns the lastModified.
- */
- protected Date getLastModified(FacesContext context) {
- if (lastModified == null && !useLocalLastModified) {
- useLocalLastModified = true;
-
- Class<? extends ResourceImpl> thisClass = getClass();
- ClassLoader classLoader = thisClass.getClassLoader();
- if (classLoader == null) {
- classLoader = ClassLoader.getSystemClassLoader();
- }
-
- if (classLoader != null) {
- URL classResource = classLoader.getResource(thisClass.getName().replace('.',
'/') + ".class");
- URLConnection connection;
- try {
- connection = classResource.openConnection();
- long classLastModifiedDate = connection.getLastModified();
- if (classLastModifiedDate > 0) {
- lastModified = new Date(classLastModifiedDate);
- }
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
-
- return lastModified;
- }
-
- /**
- * @param resourceContext current {@link ResourceContext}
- * @return Returns the cacheable.
- */
- public boolean isCacheable(FacesContext context) {
- return cacheable;
- }
-
- /**
- * @param resourceContext current {@link ResourceContext}
- * @return Returns the mimeType.
- */
- public abstract String getContentType(FacesContext context);
-
- public String getEntityTag(FacesContext context) {
- int contentLength = getContentLength(context);
- Date lastModified = getLastModified(context);
-
- if (contentLength != -1 && lastModified != null) {
- return contentLength + "-" + lastModified.getTime();
- } else {
- return null;
- }
- }
-
- @Override
- public abstract InputStream getInputStream();
-
- public String getVersion() {
- return null;
- }
-
- @Override
- public String getRequestPath() {
- FacesContext context = FacesContext.getCurrentInstance();
-
- Object resourceData = null;
- if (this instanceof StateHolder) {
- StateHolder stateHolder = (StateHolder) this;
- if (!stateHolder.isTransient()) {
- resourceData = stateHolder.saveState(context);
- }
- }
-
- String resourceUri = ResourceHandlerImpl.RICHFACES_RESOURCE_IDENTIFIER +
- resourceCodec.encodeResource(getResourceName(), resourceData);
-
- String url = Util.encodeResourceURL(context, resourceUri);
-
- String version = getVersion();
- if (version != null && version.length() > 0) {
- url += "?v=" + version;
- }
-
- return url;
- }
-
- private boolean isResourceRequest() {
- FacesContext facesContext = FacesContext.getCurrentInstance();
- return
(facesContext.getApplication().getResourceHandler().isResourceRequest(facesContext));
- }
-
- @Override
- public Map<String, String> getResponseHeaders() {
- Map<String, String> headers = new HashMap<String, String>();
- FacesContext facesContext = FacesContext.getCurrentInstance();
-
- if (isResourceRequest()) {
- int contentLength = getContentLength(facesContext);
- if (contentLength != -1) {
- headers.put("Content-Length", String.valueOf(contentLength));
- }
-
- String contentType = getContentType();
- if (contentType != null) {
- //TODO add content-encoding?
- headers.put("Content-Type", contentType);
- }
-
- Date lastModified = getLastModified(facesContext);
- if (lastModified != null) {
- headers.put("Last-Modified", Util.formatHttpDate(lastModified));
- }
-
- boolean cacheable = isCacheable(facesContext);
-
- if (cacheable) {
- long expires = getExpired(facesContext);
- if (expires <= 0) {
- expires = InternetResource.DEFAULT_EXPIRE;
- }
-
- String entityTag = getEntityTag(facesContext);
- if (entityTag != null) {
- headers.put("ETag", "W/\"" + entityTag +
"\"");
- }
-
- headers.put("Expires", Util.formatHttpDate(expires +
System.currentTimeMillis()));
- headers.put("Cache-Control", "max-age=" + expires / 1000L);
- } else {
- headers.put("Expires", "0");
- headers.put("Cache-Control", "max-age=0, no-store, no-cache");
- headers.put("Pragma", "no-cache");
- }
- }
-
- return headers;
- }
-
- @Override
- public URL getURL() {
- // TODO Auto-generated method stub
- try {
- return new URL(URL_PROTOCOL, null, -1, getResourceName(), new URLStreamHandler() {
-
- @Override
- protected URLConnection openConnection(URL u) throws IOException {
- final FacesContext facesContext = FacesContext.getCurrentInstance();
-
- return new URLConnection(u) {
-
- @Override
- public void connect() throws IOException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public int getContentLength() {
- return ResourceImpl.this.getContentLength(facesContext);
- }
-
- @Override
- public String getContentType() {
- return ResourceImpl.this.getContentType(facesContext);
- }
-
- @Override
- public long getExpiration() {
- return ResourceImpl.this.getExpired(facesContext);
- }
-
- @Override
- public long getLastModified() {
- Date date = ResourceImpl.this.getLastModified(facesContext);
- if (date != null) {
- return date.getTime();
- } else {
- return 0;
- }
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- return ResourceImpl.this.getInputStream();
- }
- };
- }
- });
- } catch (MalformedURLException e) {
- throw new FacesException(e.getLocalizedMessage(), e);
- }
- }
-
- private static final Pattern ETAG_PATTERN =
Pattern.compile("(?:W/)?\"([^\"]+)\"(?:,\\s*)?");
-
- private boolean userCopyIsStale(FacesContext context) {
- Date serverLastModified = getLastModified(context);
- if (serverLastModified == null) {
- return true;
- }
-
- String headerValue =
context.getExternalContext().getRequestHeaderMap().get("If-Modified-Since");
- Date clientLastModified = Util.parseHttpDate(headerValue);
- if (clientLastModified == null) {
- return true;
- }
-
- // 1000 ms due to round
- // modification
- // time to seconds.
- long serverLastModifiedTime = serverLastModified.getTime() - 1000;
-
- return serverLastModifiedTime > clientLastModified.getTime();
- }
-
- @Override
- public boolean userAgentNeedsUpdate(FacesContext context) {
- if (!isCacheable(context)) {
- return true;
- }
-
- ExternalContext externalContext = context.getExternalContext();
- Map<String, String> requestHeaderMap = externalContext.getRequestHeaderMap();
-
- String ifNoneMatch = requestHeaderMap.get("If-None-Match");
- if (ifNoneMatch != null) {
- Matcher eTagMatcher = ETAG_PATTERN.matcher(ifNoneMatch);
- while (eTagMatcher.find()) {
- String eTag = eTagMatcher.group(1);
-
- if (eTag.equals(getEntityTag(context))) {
- return userCopyIsStale(context);
- }
- }
-
- return true;
- }
-
- return userCopyIsStale(context);
- }
-
- public void setResourceCodec(ResourceCodec codec) {
- this.resourceCodec = codec;
- }
-}
Modified:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java 2009-07-01
12:45:49 UTC (rev 14757)
+++
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/DefaultResourceCodec.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -3,7 +3,6 @@
*/
package org.richfaces.resource;
-import org.ajax4jsf.resource.ResourceCodec;
import org.richfaces.util.Util;
class DefaultResourceCodec implements ResourceCodec {
Added:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodec.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodec.java
(rev 0)
+++
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodec.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -0,0 +1,17 @@
+/**
+ *
+ */
+package org.richfaces.resource;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public interface ResourceCodec {
+
+ public String encodeResource(String resourceName, Object resourceData);
+
+ public String decodeResourceName(String resourceKey);
+
+ public Object decodeResourceData(String resourceKey);
+}
Added:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodecAware.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodecAware.java
(rev 0)
+++
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceCodecAware.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package org.richfaces.resource;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public interface ResourceCodecAware {
+
+ public void setResourceCodec(ResourceCodec codec);
+
+}
Modified:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java
===================================================================
---
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java 2009-07-01
12:45:49 UTC (rev 14757)
+++
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceHandlerImpl.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -35,8 +35,6 @@
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
-import org.ajax4jsf.resource.ResourceCodec;
-import org.ajax4jsf.resource.ResourceCodecAware;
import org.richfaces.util.Util;
import org.richfaces.util.RequestStateManager.BooleanRequestStateVariable;
Added:
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
===================================================================
--- branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java
(rev 0)
+++
branches/jsf2.0/framework/impl/src/main/java/org/richfaces/resource/ResourceImpl.java 2009-07-01
12:48:44 UTC (rev 14758)
@@ -0,0 +1,327 @@
+/**
+ * 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.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+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;
+import org.ajax4jsf.resource.ResourceContext;
+import org.richfaces.util.Util;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public abstract class ResourceImpl extends Resource implements ResourceCodecAware {
+
+ public static final String URL_PROTOCOL = "jsfResource";
+
+ private boolean cacheable = true;
+
+ private Date lastModified = null;
+
+ private boolean useLocalLastModified = false;
+
+ private ResourceCodec resourceCodec;
+
+ /**
+ * @param resourceContext current {@link ResourceContext}
+ * @return Returns the contentLength.
+ */
+ protected int getContentLength(FacesContext context) {
+ return -1;
+ }
+
+ /**
+ * @param resourceContext current {@link ResourceContext}
+ * @return Returns the expired.
+ */
+ protected long getExpired(FacesContext context) {
+ return 0;
+ }
+
+ /**
+ * @param resourceContext current {@link ResourceContext}
+ * @return Returns the lastModified.
+ */
+ protected Date getLastModified(FacesContext context) {
+ if (lastModified == null && !useLocalLastModified) {
+ useLocalLastModified = true;
+
+ Class<? extends ResourceImpl> thisClass = getClass();
+ ClassLoader classLoader = thisClass.getClassLoader();
+ if (classLoader == null) {
+ classLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ if (classLoader != null) {
+ URL classResource = classLoader.getResource(thisClass.getName().replace('.',
'/') + ".class");
+ URLConnection connection;
+ try {
+ connection = classResource.openConnection();
+ long classLastModifiedDate = connection.getLastModified();
+ if (classLastModifiedDate > 0) {
+ lastModified = new Date(classLastModifiedDate);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ return lastModified;
+ }
+
+ /**
+ * @param resourceContext current {@link ResourceContext}
+ * @return Returns the cacheable.
+ */
+ public boolean isCacheable(FacesContext context) {
+ return cacheable;
+ }
+
+ /**
+ * @param resourceContext current {@link ResourceContext}
+ * @return Returns the mimeType.
+ */
+ public abstract String getContentType(FacesContext context);
+
+ public String getEntityTag(FacesContext context) {
+ int contentLength = getContentLength(context);
+ Date lastModified = getLastModified(context);
+
+ if (contentLength != -1 && lastModified != null) {
+ return contentLength + "-" + lastModified.getTime();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public abstract InputStream getInputStream();
+
+ public String getVersion() {
+ return null;
+ }
+
+ @Override
+ public String getRequestPath() {
+ FacesContext context = FacesContext.getCurrentInstance();
+
+ Object resourceData = null;
+ if (this instanceof StateHolder) {
+ StateHolder stateHolder = (StateHolder) this;
+ if (!stateHolder.isTransient()) {
+ resourceData = stateHolder.saveState(context);
+ }
+ }
+
+ String resourceUri = ResourceHandlerImpl.RICHFACES_RESOURCE_IDENTIFIER +
+ resourceCodec.encodeResource(getResourceName(), resourceData);
+
+ String url = Util.encodeResourceURL(context, resourceUri);
+
+ String version = getVersion();
+ if (version != null && version.length() > 0) {
+ url += "?v=" + version;
+ }
+
+ return url;
+ }
+
+ private boolean isResourceRequest() {
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ return
(facesContext.getApplication().getResourceHandler().isResourceRequest(facesContext));
+ }
+
+ @Override
+ public Map<String, String> getResponseHeaders() {
+ Map<String, String> headers = new HashMap<String, String>();
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ if (isResourceRequest()) {
+ int contentLength = getContentLength(facesContext);
+ if (contentLength != -1) {
+ headers.put("Content-Length", String.valueOf(contentLength));
+ }
+
+ String contentType = getContentType();
+ if (contentType != null) {
+ //TODO add content-encoding?
+ headers.put("Content-Type", contentType);
+ }
+
+ Date lastModified = getLastModified(facesContext);
+ if (lastModified != null) {
+ headers.put("Last-Modified", Util.formatHttpDate(lastModified));
+ }
+
+ boolean cacheable = isCacheable(facesContext);
+
+ if (cacheable) {
+ long expires = getExpired(facesContext);
+ if (expires <= 0) {
+ expires = InternetResource.DEFAULT_EXPIRE;
+ }
+
+ String entityTag = getEntityTag(facesContext);
+ if (entityTag != null) {
+ headers.put("ETag", "W/\"" + entityTag +
"\"");
+ }
+
+ headers.put("Expires", Util.formatHttpDate(expires +
System.currentTimeMillis()));
+ headers.put("Cache-Control", "max-age=" + expires / 1000L);
+ } else {
+ headers.put("Expires", "0");
+ headers.put("Cache-Control", "max-age=0, no-store, no-cache");
+ headers.put("Pragma", "no-cache");
+ }
+ }
+
+ return headers;
+ }
+
+ @Override
+ public URL getURL() {
+ // TODO Auto-generated method stub
+ try {
+ return new URL(URL_PROTOCOL, null, -1, getResourceName(), new URLStreamHandler() {
+
+ @Override
+ protected URLConnection openConnection(URL u) throws IOException {
+ final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+ return new URLConnection(u) {
+
+ @Override
+ public void connect() throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getContentLength() {
+ return ResourceImpl.this.getContentLength(facesContext);
+ }
+
+ @Override
+ public String getContentType() {
+ return ResourceImpl.this.getContentType(facesContext);
+ }
+
+ @Override
+ public long getExpiration() {
+ return ResourceImpl.this.getExpired(facesContext);
+ }
+
+ @Override
+ public long getLastModified() {
+ Date date = ResourceImpl.this.getLastModified(facesContext);
+ if (date != null) {
+ return date.getTime();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return ResourceImpl.this.getInputStream();
+ }
+ };
+ }
+ });
+ } catch (MalformedURLException e) {
+ throw new FacesException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ private static final Pattern ETAG_PATTERN =
Pattern.compile("(?:W/)?\"([^\"]+)\"(?:,\\s*)?");
+
+ private boolean userCopyIsStale(FacesContext context) {
+ Date serverLastModified = getLastModified(context);
+ if (serverLastModified == null) {
+ return true;
+ }
+
+ String headerValue =
context.getExternalContext().getRequestHeaderMap().get("If-Modified-Since");
+ Date clientLastModified = Util.parseHttpDate(headerValue);
+ if (clientLastModified == null) {
+ return true;
+ }
+
+ // 1000 ms due to round
+ // modification
+ // time to seconds.
+ long serverLastModifiedTime = serverLastModified.getTime() - 1000;
+
+ return serverLastModifiedTime > clientLastModified.getTime();
+ }
+
+ @Override
+ public boolean userAgentNeedsUpdate(FacesContext context) {
+ if (!isCacheable(context)) {
+ return true;
+ }
+
+ ExternalContext externalContext = context.getExternalContext();
+ Map<String, String> requestHeaderMap = externalContext.getRequestHeaderMap();
+
+ String ifNoneMatch = requestHeaderMap.get("If-None-Match");
+ if (ifNoneMatch != null) {
+ Matcher eTagMatcher = ETAG_PATTERN.matcher(ifNoneMatch);
+ while (eTagMatcher.find()) {
+ String eTag = eTagMatcher.group(1);
+
+ if (eTag.equals(getEntityTag(context))) {
+ return userCopyIsStale(context);
+ }
+ }
+
+ return true;
+ }
+
+ return userCopyIsStale(context);
+ }
+
+ public void setResourceCodec(ResourceCodec codec) {
+ this.resourceCodec = codec;
+ }
+}