When you create an application with GWT and Gear (http://code.google.com/p/gwt-google-apis/), a manifest has to be created to manage offline content.
Depending the targeted browser (Safari, IE, Gecko1.8, Gecko, Opera) GWT generates specifics files for html and javascript.
To minimize the manifest management (and the downloading process) a dedicated manifest has to be created for each browser.
A solution is to use a ServletFilter. This filter will automaticaly return the manifest regarding user's browser.
The filter configuration manages manifest version and resources to be included in the manifest (.css, .html, .gif...).
This filter will only be trigged when the manifest file is requested by Gears.
I hope this solution can help..
Don' t hesitate to post any comments or modifications.
package com.alu.gwt.server;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GearManifestFilter implements Filter {
public static final String EXTENSIONS = "extensions";
public static final String MANIFEST_VERSION = "manifestVersion";
public static final String OPERA_PATTERN = "'opera'],";
public static final String SAFARI_PATTERN = "'safari'],";
public static final String GECKO1_8_PATTERN = "'gecko1_8'],";
public static final String GECKO_PATTERN = "'gecko'],";
public static final String IE6_PATTERN = "'ie6'],";
public static final String OPERA = "opera";
public static final String SAFARI = "safari";
public static final String GECKO1_8 = "gecko1_8";
public static final String GECKO = "gecko";
public static final String IE6 = "ie6";
protected String _operaCacheFilename;
protected String _safariCacheFilename;
protected String _gecko1_8CacheFilename;
protected String _geckoCacheFilename;
protected String _ie6CacheFilename;
protected String _extensions;
protected String _manifestVersion = "1.0";
protected Map _manifestMap = new HashMap();
public static class GearRegexpFilenameFilter implements FilenameFilter {
private String _regexpFilter;
private Pattern _regexpPattern;
GearRegexpFilenameFilter(String regexpFilter) {
_regexpFilter = regexpFilter;
_regexpPattern = Pattern.compile(_regexpFilter);
}
public boolean accept(File dir, String name) {
if ((name.indexOf(".cache.") == -1) &&
(name.indexOf("-xs.nocache.") == -1)) {
Matcher matcher = _regexpPattern.matcher(name);
return matcher.find();
} else
return false;
}
}
public static class GearResourcesExplorer {
List _result = new ArrayList();
public GearResourcesExplorer() {
}
public List list(File directory, FilenameFilter filter,
boolean recursive, boolean root) {
if (recursive) {
File[] dirs = directory.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.isDirectory())
return true;
return false;
}
});
for (int i=0; i < dirs.length; i++)
list(dirs[i], filter, recursive, false);
}
String[] res = directory.list(filter);
for (int i = 0; i < res.length; i++) {
if (root) {
_result.add(res[i]);
} else {
_result.add(directory.getName() + File.separator + res[i]);
}
}
return _result;
}
}
public GearManifestFilter() {
}
public void init(FilterConfig filterConfig) {
_extensions = filterConfig.getInitParameter(EXTENSIONS);
_manifestVersion = filterConfig.getInitParameter(MANIFEST_VERSION);
System.out.println("Extensions: " + _extensions);
String realPath = filterConfig.getServletContext().getRealPath("/");
System.out.println("Path:" + realPath);
File dir = new File(realPath);
List resourceFilenames = new GearResourcesExplorer().list(dir, new GearRegexpFilenameFilter(_extensions), true, true);
for (int i = 0; i < resourceFilenames.size(); i++) {
System.out.println("File: " + resourceFilenames.get(i));
}
FilenameFilter noCacheFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
if (name.endsWith(".nocache.js") &&
!name.endsWith("-xs.nocache.js"))
return true;
return false;
}
};
String[] noCacheFilenames = dir.list(noCacheFilter);
if (noCacheFilenames.length != 1) {
System.out.println("Error !!");
} else {
getResourcesAccordingUserAgent(realPath + noCacheFilenames[0]);
}
_manifestMap.put(SAFARI,
createManifest(_safariCacheFilename, _manifestVersion,
resourceFilenames));
_manifestMap.put(GECKO,
createManifest(_geckoCacheFilename, _manifestVersion,
resourceFilenames));
_manifestMap.put(GECKO1_8,
createManifest(_gecko1_8CacheFilename, _manifestVersion,
resourceFilenames));
_manifestMap.put(OPERA,
createManifest(_operaCacheFilename, _manifestVersion,
resourceFilenames));
_manifestMap.put(IE6,
createManifest(_ie6CacheFilename, _manifestVersion,
resourceFilenames));
}
protected void getResourcesAccordingUserAgent(String noCacheFilename) {
System.out.println(noCacheFilename);
BufferedReader in = null;
StringBuffer buffer = new StringBuffer();
try {
in = new BufferedReader(new FileReader(noCacheFilename));
String currentLine;
while ((currentLine = in.readLine()) != null) {
buffer.append(currentLine);
}
in.close();
} catch (IOException e) {
System.out.println("Error");
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
_operaCacheFilename = getFilename(buffer, OPERA_PATTERN);
_geckoCacheFilename = getFilename(buffer, GECKO_PATTERN);
_gecko1_8CacheFilename = getFilename(buffer, GECKO1_8_PATTERN);
_safariCacheFilename = getFilename(buffer, SAFARI_PATTERN);
_ie6CacheFilename = getFilename(buffer, IE6_PATTERN);
System.out.println("OperaFilename: " + _operaCacheFilename);
System.out.println("GeckoFilename: " + _geckoCacheFilename);
System.out.println("Gecko1_8Filename: " + _gecko1_8CacheFilename);
System.out.println("SafariFilename: " + _safariCacheFilename);
System.out.println("IE6Filename: " + _ie6CacheFilename);
}
protected String getFilename(StringBuffer noCacheStringBuffer,
String agentPattern) {
String noCacheString = noCacheStringBuffer.toString();
int beginIndex =
noCacheString.indexOf(agentPattern) + agentPattern.length() + 1;
int endIndex = noCacheString.indexOf("'", beginIndex);
String filename = noCacheString.substring(beginIndex, endIndex);
return filename;
}
protected String createManifest(String userAgentHash, String version,
List resourceFilenames) {
StringBuffer manifestBuffer = new StringBuffer("{\n");
manifestBuffer.append("\"betaManifestVersion\": 1,\n");
manifestBuffer.append("\"version\": \"");
manifestBuffer.append(version);
manifestBuffer.append("\",\n");
manifestBuffer.append("\"entries\": [\n");
manifestBuffer.append("{ \"url\": \"");
manifestBuffer.append(userAgentHash + ".cache.js\"");
manifestBuffer.append("},\n");
manifestBuffer.append("{ \"url\": \"");
manifestBuffer.append(userAgentHash + ".cache.html\"");
manifestBuffer.append("},\n");
for (int i = 0; i < resourceFilenames.size() - 1; i++) {
manifestBuffer.append("{ \"url\": \"");
manifestBuffer.append(resourceFilenames.get(i));
manifestBuffer.append("\"},\n");
}
manifestBuffer.append("{ \"url\": \"");
manifestBuffer.append(resourceFilenames.get(resourceFilenames.size() - 1));
manifestBuffer.append("\"}\n");
manifestBuffer.append("]\n");
manifestBuffer.append("}\n");
System.out.println("Manifest: " + manifestBuffer.toString());
return manifestBuffer.toString();
}
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException,
ServletException {
HttpServletRequest request = ((HttpServletRequest)servletRequest);
String userAgentString = request.getHeader("user-agent");
System.out.println("UserAgent: " + userAgentString);
String userAgent = getUserAgent(userAgentString);
ServletOutputStream out = servletResponse.getOutputStream();
HttpServletResponse response = (HttpServletResponse)servletResponse;
response.setContentType("application/jsonrequest");
out.println((String)_manifestMap.get(userAgent));
}
protected String getUserAgent(String userAgentString) {
if (userAgentString.indexOf("IE6") != -1 ||
userAgentString.indexOf("MSIE 7") != -1) {
System.out.println("IE6 or more detected");
return IE6;
} else if (userAgentString.indexOf("MOZILLA") != -1) {
System.out.println("MOZILLA detected");
return GECKO;
} else if (userAgentString.indexOf("MOZILLA") != -1) {
System.out.println("MOZILLA detected");
return IE6;
}
return SAFARI;
}
public void destroy() {
}
}
web.xml:
<filter>
<filter-name>gearManifestFilter</filter-name>
<filter-class>com.alu.gwt.server.GearManifestFilter</filter-class>
<init-param>
<description>Resources to be include in manifest</description>
<param-name>extensions</param-name>
<param-value>.htm|.css|.html|.js|.gif|.jpg</param-value>
</init-param>
<init-param>
<description>manifest version</description>
<param-name>manifestVersion</param-name>
<param-value>1.0</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>gearManifestFilter</filter-name>
<url-pattern>/manifest.json</url-pattern>
</filter-mapping>
No comments:
Post a Comment