1 36 37 package jnlp.sample.servlet; 38 import java.util.HashMap ; 39 import java.util.List ; 40 import java.util.ArrayList ; 41 import java.io.File ; 42 import java.io.BufferedInputStream ; 43 import javax.servlet.ServletContext ; 44 import javax.xml.parsers.*; 45 import org.xml.sax.*; 46 import org.w3c.dom.*; 47 import jnlp.sample.util.VersionString; 48 import jnlp.sample.util.VersionID; 49 50 public class ResourceCatalog { 51 public static final String VERSION_XML_FILENAME = "version.xml"; 52 53 private Logger _log = null; 54 private ServletContext _servletContext = null; 55 56 private HashMap _entries; 57 58 61 static private class PathEntries { 62 63 private List _versionXmlList; 64 private List _directoryList; 65 private List _platformList; 66 67 private long _lastModified; 69 public PathEntries(List versionXmlList, List directoryList, List platformList, long lastModified) { 70 _versionXmlList = versionXmlList; 71 _directoryList = directoryList; 72 _platformList = platformList; 73 _lastModified = lastModified; 74 } 75 76 77 public void setDirectoryList(List dirList) { 78 _directoryList = dirList; 79 } 80 81 public List getVersionXmlList() { return _versionXmlList; } 82 public List getDirectoryList() { return _directoryList; } 83 public List getPlatformList() { return _platformList; } 84 85 public long getLastModified() { return _lastModified; } 86 } 87 88 public ResourceCatalog(ServletContext servletContext, Logger log) { 89 _entries = new HashMap (); 90 _servletContext = servletContext; 91 _log = log; 92 } 93 94 95 public JnlpResource lookupResource(DownloadRequest dreq) throws ErrorResponseException { 96 String path = dreq.getPath(); 98 String name = null; 99 String dir = null; 100 int idx = path.lastIndexOf('/'); 101 if (idx == -1) { 102 name = path; 103 } else { 104 name = path.substring(idx + 1); dir = path.substring(0, idx + 1); } 107 108 PathEntries pentries = (PathEntries)_entries.get(dir); 110 JnlpResource xmlVersionResPath = new JnlpResource(_servletContext, dir + VERSION_XML_FILENAME); 111 if (pentries == null || (xmlVersionResPath.exists() && xmlVersionResPath.getLastModified() > pentries.getLastModified())) { 112 _log.addInformational("servlet.log.scandir", dir); 113 List dirList = scanDirectory(dir, dreq); 114 List versionList = new ArrayList (); 116 List platformList = new ArrayList (); 117 parseVersionXML(versionList, platformList, dir, xmlVersionResPath); 118 pentries = new PathEntries(versionList, dirList, platformList, xmlVersionResPath.getLastModified()); 119 _entries.put(dir, pentries); 120 } 121 122 JnlpResource[] result = new JnlpResource[1]; 124 125 if (dreq.isPlatformRequest()) { 126 int sts = findMatch(pentries.getPlatformList(), name, dreq, result); 127 if (sts != DownloadResponse.STS_00_OK) { 128 throw new ErrorResponseException(DownloadResponse.getJnlpErrorResponse(sts)); 129 } 130 } else { 131 int sts1 = findMatch(pentries.getVersionXmlList(), name, dreq, result); 133 if (sts1 != DownloadResponse.STS_00_OK) { 134 int sts2 = findMatch(pentries.getDirectoryList(), name, dreq, result); 136 if (sts2 != DownloadResponse.STS_00_OK) { 137 138 pentries.setDirectoryList(scanDirectory(dir, dreq)); 141 sts2 = findMatch(pentries.getDirectoryList(), name, dreq, result); 142 if (sts2 != DownloadResponse.STS_00_OK) { 144 throw new ErrorResponseException(DownloadResponse.getJnlpErrorResponse(Math.max(sts1, sts2))); 146 } 147 } 148 } 149 } 150 return result[0]; 151 } 152 153 165 public int findMatch(List list, String name, DownloadRequest dreq, JnlpResource[] result) { 166 if (list == null) return DownloadResponse.ERR_10_NO_RESOURCE; 167 VersionID bestVersionId = null; 169 int error = DownloadResponse.ERR_10_NO_RESOURCE; 170 VersionString vs = new VersionString(dreq.getVersion()); 171 for(int i = 0; i < list.size(); i++) { 173 JnlpResource respath = (JnlpResource)list.get(i); 174 VersionID vid = new VersionID(respath.getVersionId()); 175 int sts = matchEntry(name, vs, dreq, respath, vid); 176 if (sts == DownloadResponse.STS_00_OK) { 177 if (result[0] == null || vid.isGreaterThan(bestVersionId)) { 178 result[0] = respath; 179 bestVersionId = vid; 180 } 181 } else { 182 error = Math.max(error, sts); 183 } 184 } 185 return (result[0] != null) ? DownloadResponse.STS_00_OK : error; 186 } 187 188 public int matchEntry(String name, VersionString vs, DownloadRequest dreq, JnlpResource jnlpres, VersionID vid) { 189 if (!name.equals(jnlpres.getName())) { 190 return DownloadResponse.ERR_10_NO_RESOURCE; 191 } 192 if (!vs.contains(vid)) { 193 return DownloadResponse.ERR_11_NO_VERSION; 194 } 195 if (!prefixMatchLists(jnlpres.getOSList(), dreq.getOS())) { 196 return DownloadResponse.ERR_20_UNSUP_OS; 197 } 198 if (!prefixMatchLists(jnlpres.getArchList(), dreq.getArch())) { 199 return DownloadResponse.ERR_21_UNSUP_ARCH; 200 } 201 if (!prefixMatchLists(jnlpres.getLocaleList(), dreq.getLocale())) { 202 return DownloadResponse.ERR_22_UNSUP_LOCALE; 203 } 204 return DownloadResponse.STS_00_OK; 205 } 206 207 208 private static boolean prefixMatchStringList(String [] prefixList, String target) { 209 if (prefixList == null) return true; 211 if (target == null) return false; 213 for(int i = 0; i < prefixList.length; i++) { 214 if (target.startsWith(prefixList[i])) return true; 215 } 216 return false; 217 } 218 219 222 public boolean prefixMatchLists(String [] prefixes, String [] keys) { 223 if (prefixes == null) return true; 226 if (keys == null) return false; 229 for(int i = 0; i < keys.length; i++) { 231 if (prefixMatchStringList(prefixes, keys[i])) return true; 232 } 233 return false; 234 } 235 236 251 252 253 private String jnlpGetPath(DownloadRequest dreq) { 254 String path = dreq.getPath(); 258 String filename = path.substring(path.lastIndexOf("/") + 1); 259 path = path.substring(0, path.lastIndexOf("/") + 1); 260 String name = filename; 261 String ext = null; 262 263 if (filename.lastIndexOf(".") != -1) { 264 ext = filename.substring(filename.lastIndexOf(".") + 1); 265 266 filename = filename.substring(0, filename.lastIndexOf(".")); 267 268 } 269 if (dreq.getVersion() != null) { 270 filename += "__V" + dreq.getVersion(); 271 } 272 273 String [] temp = dreq.getOS(); 274 275 if (temp != null) { 276 for (int i=0; i<temp.length; i++) { 277 filename += "__O" + temp[i]; 278 } 279 } 280 281 temp = dreq.getArch(); 282 283 if (temp != null) { 284 for (int i=0; i<temp.length; i++) { 285 filename += "__A" + temp[i]; 286 } 287 } 288 temp = dreq.getLocale(); 289 290 if (temp != null) { 291 for (int i=0; i<temp.length; i++) { 292 filename += "__L" + temp[i]; 293 } 294 } 295 296 if (ext != null) { 297 filename += "." + ext; 298 } 299 300 path += filename; 301 302 return path; 303 } 304 305 public List scanDirectory(String dirPath, DownloadRequest dreq) { 306 ArrayList list = new ArrayList (); 307 308 if (_servletContext.getRealPath(dirPath) == null) { 310 String path = jnlpGetPath(dreq); 311 312 String name = dreq.getPath().substring(path.lastIndexOf("/") + 1); 313 314 JnlpResource jnlpres = new JnlpResource(_servletContext, name, dreq.getVersion(), dreq.getOS(), dreq.getArch(), dreq.getLocale(), path, dreq.getVersion()); 315 316 if (jnlpres.getResource() == null) return null; 318 319 list.add(jnlpres); 320 return list; 321 } 322 File dir = new File (_servletContext.getRealPath(dirPath)); 323 _log.addDebug("File directory: " + dir); 324 if (dir.exists() && dir.isDirectory()) { 325 File [] entries = dir.listFiles(); 326 for(int i = 0; i < entries.length; i++) { 327 JnlpResource jnlpres = parseFileEntry(dirPath, entries[i].getName()); 328 if (jnlpres != null) { 329 if (_log.isDebugLevel()) { 330 _log.addDebug("Read file resource: " + jnlpres); 331 } 332 list.add(jnlpres); 333 } 334 } 335 } 336 return list; 337 } 338 339 private JnlpResource parseFileEntry(String dir, String filename) { 340 int idx = filename .indexOf("__"); 341 if (idx == -1) return null; 342 343 String name = filename.substring(0, idx); 345 String rest = filename.substring(idx); 346 347 idx = rest.lastIndexOf('.'); 349 String extension = ""; 350 if (idx != -1 ) { 351 extension = rest.substring(idx); 352 rest = rest .substring(0, idx); 353 } 354 355 String versionId = null; 357 ArrayList osList = new ArrayList (); 358 ArrayList archList = new ArrayList (); 359 ArrayList localeList = new ArrayList (); 360 while(rest.length() > 0) { 361 362 if (!rest.startsWith("__")) return null; 363 rest = rest.substring(2); 364 char option = rest.charAt(0); 366 idx = rest.indexOf("__"); 367 String arg = null; 368 if (idx == -1) { 369 arg = rest.substring(1); 370 rest = ""; 371 } else { 372 arg = rest.substring(1, idx); 373 rest = rest.substring(idx); 374 } 375 switch(option) { 376 case 'V': versionId = arg; break; 377 case 'O': osList.add(arg); break; 378 case 'A': archList.add(arg); break; 379 case 'L': localeList.add(arg); break; 380 default: return null; } 382 } 383 384 return new JnlpResource(_servletContext, 385 name + extension, 386 versionId, 387 listToStrings(osList), 388 listToStrings(archList), 389 listToStrings(localeList), 390 dir + filename, 391 versionId); 392 } 393 394 private String [] listToStrings(List list) { 395 if (list.size() == 0) return null; 396 return (String [])list.toArray(new String [list.size()]); 397 } 398 399 private void parseVersionXML(final List versionList, final List platformList, 401 final String dir, final JnlpResource versionRes) { 402 if (!versionRes.exists()) return; 403 404 XMLNode root = null; 406 try { 407 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 408 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 409 Document doc = docBuilder.parse(new BufferedInputStream (versionRes.getResource().openStream())); 410 doc.getDocumentElement().normalize(); 411 412 root = XMLParsing.convert(doc.getDocumentElement()); 417 } catch (SAXParseException err) { 418 _log.addWarning("servlet.log.warning.xml.parsing", 419 versionRes.getPath(), 420 Integer.toString(err.getLineNumber()), 421 err.getMessage()); 422 return; 423 } catch (Throwable t) { 424 _log.addWarning("servlet.log.warning.xml.reading", versionRes.getPath(), t); 425 return; 426 } 427 428 if (!root.getName().equals("jnlp-versions")) { 430 _log.addWarning("servlet.log.warning.xml.missing-jnlp", versionRes.getPath()); 431 return; 432 } 433 434 XMLParsing.visitElements(root, "<resource>", new XMLParsing.ElementVisitor() { 436 public void visitElement(XMLNode node) { 437 XMLNode pattern = XMLParsing.findElementPath(node, "<pattern>"); 438 if (pattern == null) { 439 _log.addWarning("servlet.log.warning.xml.missing-pattern", versionRes.getPath()); 440 } else { 441 String name = XMLParsing.getElementContent(pattern , "<name>", ""); 443 String versionId = XMLParsing.getElementContent(pattern , "<version-id>"); 444 String [] os = XMLParsing.getMultiElementContent(pattern, "<os>"); 445 String [] arch = XMLParsing.getMultiElementContent(pattern, "<arch>"); 446 String [] locale = XMLParsing.getMultiElementContent(pattern, "<locale>"); 447 String file = XMLParsing.getElementContent(node, "<file>"); 449 if (versionId == null || file == null) { 450 _log.addWarning("servlet.log.warning.xml.missing-elems", versionRes.getPath()); 451 } else { 452 JnlpResource res = new JnlpResource(_servletContext, 453 name, 454 versionId, 455 os, 456 arch, 457 locale, 458 dir + file, 459 versionId); 460 if (res.exists()) { 461 versionList.add(res); 462 if (_log.isDebugLevel()) { 463 _log.addDebug("Read resource: " + res); 464 } 465 } else { 466 _log.addWarning("servlet.log.warning.missing-file", file, versionRes.getPath()); 467 } 468 } 469 } 470 } 471 }); 472 473 XMLParsing.visitElements(root, "<platform>", new XMLParsing.ElementVisitor() { 475 public void visitElement(XMLNode node) { 476 XMLNode pattern = XMLParsing.findElementPath(node, "<pattern>"); 477 if (pattern == null) { 478 _log.addWarning("servlet.log.warning.xml.missing-pattern", versionRes.getPath()); 479 } else { 480 String name = XMLParsing.getElementContent(pattern , "<name>", ""); 482 String versionId = XMLParsing.getElementContent(pattern , "<version-id>"); 483 String [] os = XMLParsing.getMultiElementContent(pattern, "<os>"); 484 String [] arch = XMLParsing.getMultiElementContent(pattern, "<arch>"); 485 String [] locale = XMLParsing.getMultiElementContent(pattern, "<locale>"); 486 String file = XMLParsing.getElementContent(node, "<file>"); 488 String productId = XMLParsing.getElementContent(node, "<product-version-id>"); 489 490 if (versionId == null || file == null || productId == null) { 491 _log.addWarning("servlet.log.warning.xml.missing-elems2", versionRes.getPath()); 492 } else { 493 JnlpResource res = new JnlpResource(_servletContext, 494 name, 495 versionId, 496 os, 497 arch, 498 locale, 499 dir + file, 500 productId); 501 if (res.exists()) { 502 platformList.add(res); 503 if (_log.isDebugLevel()) { 504 _log.addDebug("Read platform resource: " + res); 505 } 506 } else { 507 _log.addWarning("servlet.log.warning.missing-file", file, versionRes.getPath()); 508 } 509 } 510 } 511 } 512 }); 513 } 514 } 515 516 517 | Popular Tags |