1 36 37 package jnlp.sample.servlet; 38 39 import java.util.*; 40 import java.util.regex.*; 41 import java.net.*; 42 import java.io.*; 43 import javax.servlet.*; 44 import javax.servlet.http.*; 45 import javax.xml.parsers.*; 46 import org.xml.sax.*; 47 import javax.xml.transform.*; 48 import javax.xml.transform.dom.DOMSource ; 49 import javax.xml.transform.stream.StreamResult ; 50 import org.w3c.dom.*; 51 52 55 public class JnlpFileHandler { 56 private static final String JNLP_MIME_TYPE = "application/x-java-jnlp-file"; 57 private static final String HEADER_LASTMOD = "Last-Modified"; 58 59 private ServletContext _servletContext; 60 private Logger _log = null; 61 private HashMap _jnlpFiles = null; 62 63 64 public JnlpFileHandler(ServletContext servletContext, Logger log) { 65 _servletContext = servletContext; 66 _log = log; 67 _jnlpFiles = new HashMap(); 68 } 69 70 private static class JnlpFileEntry { 71 DownloadResponse _response; 73 private long _lastModified; 75 76 JnlpFileEntry(DownloadResponse response, long lastmodfied) { 78 _response = response; 79 _lastModified = lastmodfied; 80 } 81 82 public DownloadResponse getResponse() { return _response; } 83 long getLastModified() { return _lastModified; } 84 } 85 86 87 public synchronized DownloadResponse getJnlpFile(JnlpResource jnlpres, DownloadRequest dreq) 88 throws IOException { 89 String path = jnlpres.getPath(); 90 URL resource = jnlpres.getResource(); 91 long lastModified = jnlpres.getLastModified(); 92 93 94 _log.addDebug("lastModified: " + lastModified + " " + new Date(lastModified)); 95 if (lastModified == 0) { 96 _log.addWarning("servlet.log.warning.nolastmodified", path); 97 } 98 99 String reqUrl = HttpUtils.getRequestURL(dreq.getHttpRequest()).toString(); 102 103 JnlpFileEntry jnlpFile = (JnlpFileEntry)_jnlpFiles.get(reqUrl); 105 106 if (jnlpFile != null && jnlpFile.getLastModified() == lastModified) { 107 return jnlpFile.getResponse(); 109 } 110 111 long timeStamp = lastModified; 113 String mimeType = _servletContext.getMimeType(path); 114 if (mimeType == null) mimeType = JNLP_MIME_TYPE; 115 116 StringBuffer jnlpFileTemplate = new StringBuffer (); 117 URLConnection conn = resource.openConnection(); 118 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 119 String line = br.readLine(); 120 if (line != null && line.startsWith("TS:")) { 121 timeStamp = parseTimeStamp(line.substring(3)); 122 _log.addDebug("Timestamp: " + timeStamp + " " + new Date(timeStamp)); 123 if (timeStamp == 0) { 124 _log.addWarning("servlet.log.warning.notimestamp", path); 125 timeStamp = lastModified; 126 } 127 line = br.readLine(); 128 } 129 while(line != null) { 130 jnlpFileTemplate.append(line); 131 line = br.readLine(); 132 } 133 134 String jnlpFileContent = specializeJnlpTemplate(dreq.getHttpRequest(), path, jnlpFileTemplate.toString()); 135 136 byte[] byteContent = jnlpFileContent.getBytes("UTF-8"); 138 139 DownloadResponse resp = DownloadResponse.getFileDownloadResponse(byteContent, 141 mimeType, 142 timeStamp, 143 jnlpres.getReturnVersionId()); 144 jnlpFile = new JnlpFileEntry(resp, lastModified); 145 _jnlpFiles.put(reqUrl, jnlpFile); 146 147 return resp; 148 } 149 150 151 public synchronized DownloadResponse getJnlpFileEx(JnlpResource jnlpres, DownloadRequest dreq) 152 throws IOException { 153 String path = jnlpres.getPath(); 154 URL resource = jnlpres.getResource(); 155 long lastModified = jnlpres.getLastModified(); 156 157 158 _log.addDebug("lastModified: " + lastModified + " " + new Date(lastModified)); 159 if (lastModified == 0) { 160 _log.addWarning("servlet.log.warning.nolastmodified", path); 161 } 162 163 String reqUrl = HttpUtils.getRequestURL(dreq.getHttpRequest()).toString(); 166 if (dreq.getQuery() != null) 168 reqUrl += dreq.getQuery(); 169 170 JnlpFileEntry jnlpFile = (JnlpFileEntry)_jnlpFiles.get(reqUrl); 172 173 if (jnlpFile != null && jnlpFile.getLastModified() == lastModified) { 174 return jnlpFile.getResponse(); 176 } 177 178 long timeStamp = lastModified; 180 String mimeType = _servletContext.getMimeType(path); 181 if (mimeType == null) mimeType = JNLP_MIME_TYPE; 182 183 StringBuffer jnlpFileTemplate = new StringBuffer (); 184 URLConnection conn = resource.openConnection(); 185 BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 186 String line = br.readLine(); 187 if (line != null && line.startsWith("TS:")) { 188 timeStamp = parseTimeStamp(line.substring(3)); 189 _log.addDebug("Timestamp: " + timeStamp + " " + new Date(timeStamp)); 190 if (timeStamp == 0) { 191 _log.addWarning("servlet.log.warning.notimestamp", path); 192 timeStamp = lastModified; 193 } 194 line = br.readLine(); 195 } 196 while(line != null) { 197 jnlpFileTemplate.append(line); 198 line = br.readLine(); 199 } 200 201 String jnlpFileContent = specializeJnlpTemplate(dreq.getHttpRequest(), path, jnlpFileTemplate.toString()); 202 203 206 String query = dreq.getQuery(); 207 String testJRE = dreq.getTestJRE(); 208 _log.addDebug("Double check query string: " + query); 209 if (query != null) { 213 byte [] cb = jnlpFileContent.getBytes("UTF-8"); 214 ByteArrayInputStream bis = new ByteArrayInputStream(cb); 215 try { 216 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 217 DocumentBuilder builder = factory.newDocumentBuilder(); 218 Document document = builder.parse(bis); 219 if (document != null && document.getNodeType() == Node.DOCUMENT_NODE) { 220 boolean modified = false; 221 Element root = document.getDocumentElement(); 222 223 if (root.hasAttribute("href") && query != null) { 224 String href = root.getAttribute("href"); 225 root.setAttribute("href", href + "?" + query); 226 modified = true; 227 } 228 if (testJRE != null) { 230 NodeList j2seNL = root.getElementsByTagName("j2se"); 231 if (j2seNL != null) { 232 Element j2se = (Element) j2seNL.item(0); 233 String ver = j2se.getAttribute("version"); 234 if (ver.length() > 0) { 235 j2se.setAttribute("version", testJRE); 236 modified = true; 237 } 238 } 239 } 240 TransformerFactory tFactory = TransformerFactory.newInstance(); 241 Transformer transformer = tFactory.newTransformer(); 242 DOMSource source = new DOMSource (document); 243 StringWriter sw = new StringWriter(); 244 StreamResult result = new StreamResult (sw); 245 transformer.transform(source, result); 246 jnlpFileContent = sw.toString(); 247 _log.addDebug("Converted jnlpFileContent: " + jnlpFileContent); 248 if (modified) { 250 timeStamp = new java.util.Date ().getTime(); 251 _log.addDebug("Last modified on the fly: " + timeStamp); 252 } 253 } 254 } catch (Exception e) { 255 _log.addDebug(e.toString(), e); 256 } 257 } 258 259 byte[] byteContent = jnlpFileContent.getBytes("UTF-8"); 261 262 DownloadResponse resp = DownloadResponse.getFileDownloadResponse(byteContent, 264 mimeType, 265 timeStamp, 266 jnlpres.getReturnVersionId()); 267 jnlpFile = new JnlpFileEntry(resp, lastModified); 268 _jnlpFiles.put(reqUrl, jnlpFile); 269 270 return resp; 271 } 272 273 278 private String specializeJnlpTemplate(HttpServletRequest request, String respath, String jnlpTemplate) { 279 String urlprefix = getUrlPrefix(request); 280 int idx = respath.lastIndexOf('/'); String name = respath.substring(idx + 1); String codebase = respath.substring(0, idx + 1); jnlpTemplate = substitute(jnlpTemplate, "$$name", name); 284 jnlpTemplate = substitute(jnlpTemplate, "$$hostname", 286 request.getServerName()); 287 jnlpTemplate = substitute(jnlpTemplate, "$$codebase", urlprefix + request.getContextPath() + codebase); 288 jnlpTemplate = substitute(jnlpTemplate, "$$context", urlprefix + request.getContextPath()); 289 jnlpTemplate = substitute(jnlpTemplate, "$$site", urlprefix); 291 return jnlpTemplate; 292 } 293 294 private String getUrlPrefix(HttpServletRequest req) { 296 StringBuffer url = new StringBuffer (); 297 String scheme = req.getScheme(); 298 int port = req.getServerPort(); 299 url.append(scheme); url.append("://"); 301 url.append(req.getServerName()); 302 if ((scheme.equals("http") && port != 80) 303 || (scheme.equals("https") && port != 443)) { 304 url.append(':'); 305 url.append(req.getServerPort()); 306 } 307 return url.toString(); 308 } 309 310 private String substitute(String target, String key, String value) { 311 int start = 0; 312 do { 313 int idx = target.indexOf(key, start); 314 if (idx == -1) return target; 315 target = target.substring(0, idx) + value + target.substring(idx + key.length()); 316 start = idx + value.length(); 317 } while(true); 318 } 319 320 338 private long parseTimeStamp(String timestamp) { 339 int YYYY = 0; 340 int MM = 0; 341 int DD = 0; 342 int hh = 0; 343 int mm = 0; 344 int ss = 0; 345 346 timestamp = timestamp.trim(); 347 try { 348 if (matchPattern("####-##-## ##:##", timestamp)) { 350 YYYY = getIntValue(timestamp, 0, 4); 351 MM = getIntValue(timestamp, 5, 7); 352 DD = getIntValue(timestamp, 8, 10); 353 hh = getIntValue(timestamp, 11, 13); 354 mm = getIntValue(timestamp, 14, 16); 355 timestamp = timestamp.substring(16); 356 if (matchPattern(":##", timestamp)) { 357 ss = getIntValue(timestamp, 1, 3); 358 timestamp = timestamp.substring(3); 359 } 360 } else if (matchPattern("############", timestamp)) { 361 YYYY = getIntValue(timestamp, 0, 4); 362 MM = getIntValue(timestamp, 4, 6); 363 DD = getIntValue(timestamp, 6, 8); 364 hh = getIntValue(timestamp, 8, 10); 365 mm = getIntValue(timestamp, 10, 12); 366 timestamp = timestamp.substring(12); 367 if (matchPattern("##", timestamp)) { 368 ss = getIntValue(timestamp, 0, 2); 369 timestamp = timestamp.substring(2); 370 } 371 } else { 372 return 0; 374 } 375 } catch(NumberFormatException e) { 376 return 0; 378 } 379 380 String timezone = null; 381 timestamp = timestamp.trim(); 383 if (timestamp.equalsIgnoreCase("Z")) { 384 timezone ="GMT"; 385 } else if (timestamp.startsWith("+") || timestamp.startsWith("-")) { 386 timezone = "GMT" + timestamp; 387 } 388 389 if (timezone == null) { 390 Calendar cal = Calendar.getInstance(); 392 cal.set(YYYY, MM - 1, DD, hh, mm, ss); 393 return cal.getTime().getTime(); 394 } else { 395 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timezone)); 397 cal.set(YYYY, MM - 1, DD, hh, mm, ss); 398 return cal.getTime().getTime(); 399 } 400 } 401 402 private int getIntValue(String key, int start, int end) { 403 return Integer.parseInt(key.substring(start, end)); 404 } 405 406 private boolean matchPattern(String pattern, String key) { 407 if (key.length() < pattern.length()) return false; 409 for(int i = 0; i < pattern.length(); i++) { 410 char format = pattern.charAt(i); 411 char ch = key.charAt(i); 412 if (!((format == '#' && Character.isDigit(ch)) || (format == ch))) { 413 return false; 414 } 415 } 416 return true; 417 } 418 } 419 420 421 | Popular Tags |