1 36 37 package jnlp.sample.servlet; 38 import java.io.*; 39 import java.util.*; 40 import jnlp.sample.jardiff.*; 41 import javax.servlet.*; 42 import javax.servlet.http.*; 43 import jnlp.sample.util.VersionString; 44 import java.net.URL ; 45 49 public class JarDiffHandler { 50 private static final int BUF_SIZE = 32 * 1024; 52 53 private static final String JARDIFF_MIMETYPE = "application/x-java-archive-diff"; 55 56 57 private HashMap _jarDiffEntries = null; 58 59 60 private static Logger _log = null; 61 private ServletContext _servletContext = null; 62 private String _jarDiffMimeType = null; 63 64 65 private static class JarDiffKey implements Comparable { 66 private String _name; private String _fromVersionId; private String _toVersionId; private boolean _minimal; 71 72 public JarDiffKey(String name, String fromVersionId, String toVersionId, boolean minimal) { 73 _name = name; 74 _fromVersionId = fromVersionId; 75 _toVersionId = toVersionId; 76 _minimal = minimal; 77 } 78 79 public String getName() { return _name; } 81 public String getFromVersionId() { return _fromVersionId; } 82 public String getToVersionId() { return _toVersionId; } 83 public boolean isMinimal() { return _minimal; } 84 85 87 public int compareTo(Object o) { 88 if (!(o instanceof JarDiffKey)) return -1; 90 JarDiffKey other = (JarDiffKey)o; 91 92 int n = _name.compareTo(other.getName()); 93 if (n != 0) return n; 94 95 n = _fromVersionId.compareTo(other.getFromVersionId()); 96 if (n != 0) return n; 97 98 if (_minimal != other.isMinimal()) return -1; 99 100 return _toVersionId.compareTo(other.getToVersionId()); 101 } 102 103 public boolean equals(Object o) { 104 return compareTo(o) == 0; 105 } 106 107 public int hashCode() { 108 return _name.hashCode() + 109 _fromVersionId.hashCode() + 110 _toVersionId.hashCode(); 111 } 112 } 113 114 static private class JarDiffEntry { 115 private File _jardiffFile; 117 public JarDiffEntry(File jarDiffFile) { 118 _jardiffFile = jarDiffFile; 119 } 120 121 public File getJarDiffFile() { return _jardiffFile; } 122 } 123 124 125 public JarDiffHandler(ServletContext servletContext, Logger log) { 126 _jarDiffEntries = new HashMap(); 127 _servletContext = servletContext; 128 _log = log; 129 130 _jarDiffMimeType = _servletContext.getMimeType("xyz.jardiff"); 131 if (_jarDiffMimeType == null) _jarDiffMimeType = JARDIFF_MIMETYPE; 132 } 133 134 135 public synchronized DownloadResponse getJarDiffEntry(ResourceCatalog catalog, DownloadRequest dreq, JnlpResource res) { 136 if (dreq.getCurrentVersionId() == null) return null; 137 138 boolean doJarDiffWorkAround = isJavawsVersion(dreq, "1.0*"); 141 142 JarDiffKey key = new JarDiffKey(res.getName(), 144 dreq.getCurrentVersionId(), 145 res.getReturnVersionId(), 146 !doJarDiffWorkAround); 147 148 149 JarDiffEntry entry = (JarDiffEntry)_jarDiffEntries.get(key); 150 if (entry == null) { 152 if (_log.isInformationalLevel()) { 153 _log.addInformational("servlet.log.info.jardiff.gen", 154 res.getName(), 155 dreq.getCurrentVersionId(), 156 res.getReturnVersionId()); 157 } 158 File f = generateJarDiff(catalog, dreq, res, doJarDiffWorkAround); 159 if (f == null) { 160 _log.addWarning("servlet.log.warning.jardiff.failed", 161 res.getName(), 162 dreq.getCurrentVersionId(), 163 res.getReturnVersionId()); 164 } 165 entry = new JarDiffEntry(f); 167 _jarDiffEntries.put(key, entry); 168 } 169 170 171 172 if (entry.getJarDiffFile() == null) { 174 return null; 175 } else { 176 return DownloadResponse.getFileDownloadResponse(entry.getJarDiffFile(), 177 _jarDiffMimeType, 178 entry.getJarDiffFile().lastModified(), 179 res.getReturnVersionId()); 180 } 181 } 182 183 184 public static boolean isJavawsVersion(DownloadRequest dreq, String version) { 185 String javawsAgent = "javaws"; 186 String jwsVer = dreq.getHttpRequest().getHeader("User-Agent"); 187 188 189 if (!jwsVer.startsWith("javaws-")) { 191 StringTokenizer st = new StringTokenizer(jwsVer); 194 while (st.hasMoreTokens()) { 195 String verString = st.nextToken(); 196 int index = verString.indexOf(javawsAgent); 197 if (index != -1) { 198 verString = verString.substring(index + javawsAgent.length() + 1); 199 return VersionString.contains(version, verString); 200 } 201 } 202 return false; 203 } 204 205 int startIndex = jwsVer.indexOf("-"); 207 208 if (startIndex == -1) { 209 return false; 210 } 211 212 int endIndex = jwsVer.indexOf("/"); 213 214 if (endIndex == -1 || endIndex < startIndex) { 215 return false; 216 } 217 218 String verId = jwsVer.substring(startIndex + 1, endIndex); 219 220 221 return VersionString.contains(version, verId); 223 224 } 225 226 227 private boolean download(URL target, File file) { 228 229 _log.addDebug("JarDiffHandler: Doing download"); 230 231 boolean ret = true; 232 boolean delete = false; 233 BufferedInputStream in = null; 235 BufferedOutputStream out = null; 236 try { 237 in = new BufferedInputStream(target.openStream()); 238 out = new BufferedOutputStream(new FileOutputStream(file)); 239 int read = 0; 240 int totalRead = 0; 241 byte[] buf = new byte[BUF_SIZE]; 242 while ((read = in.read(buf)) != -1) { 243 out.write(buf, 0, read); 244 totalRead += read; 245 } 246 247 _log.addDebug("total read: " + totalRead); 248 _log.addDebug("Wrote URL " + target.toString() + " to file " + file); 249 250 } catch(IOException ioe) { 251 252 _log.addDebug("Got exception while downloading resource: " + ioe); 253 254 ret = false; 255 256 if (file != null) delete = true; 257 258 } finally { 259 260 try { 261 in.close(); 262 in = null; 263 } catch (IOException ioe) { 264 _log.addDebug("Got exception while downloading resource: " + ioe); 265 } 266 267 try { 268 out.close(); 269 out = null; 270 } catch (IOException ioe) { 271 _log.addDebug("Got exception while downloading resource: " + ioe); 272 } 273 274 if (delete) { 275 file.delete(); 276 } 277 278 } 279 return ret; 280 } 281 282 private String getRealPath(String path) throws IOException{ 286 287 URL fileURL = _servletContext.getResource(path); 288 289 File tempDir = (File)_servletContext.getAttribute("javax.servlet.context.tempdir"); 290 291 if (fileURL != null) { 293 File newFile = File.createTempFile("temp", ".jar", tempDir); 294 if (download(fileURL, newFile)) { 295 String filePath = newFile.getPath(); 296 return filePath; 297 } 298 } 299 return null; 300 } 301 302 303 private File generateJarDiff(ResourceCatalog catalog, DownloadRequest dreq, JnlpResource res, boolean doJarDiffWorkAround) { 304 boolean del_old = false; 305 boolean del_new = false; 306 307 DownloadRequest fromDreq = dreq.getFromDownloadRequest(); 309 try { 310 JnlpResource fromRes = catalog.lookupResource(fromDreq); 311 312 313 String newFilePath = _servletContext.getRealPath(res.getPath()); 314 String oldFilePath = _servletContext.getRealPath(fromRes.getPath()); 315 316 if (newFilePath == null) { 318 newFilePath = getRealPath(res.getPath()); 319 if (newFilePath != null) del_new = true; 320 } 321 322 if (oldFilePath == null) { 323 oldFilePath = getRealPath(fromRes.getPath()); 324 if (oldFilePath != null) del_old = true; 325 } 326 327 if (newFilePath == null || oldFilePath == null) { 328 return null; 329 } 330 331 File tempDir = (File)_servletContext.getAttribute("javax.servlet.context.tempdir"); 333 334 File outputFile = File.createTempFile("jnlp", ".jardiff", tempDir); 336 337 _log.addDebug("Generating Jardiff between " + oldFilePath + " and " + 338 newFilePath + " Store in " + outputFile); 339 340 OutputStream os = new FileOutputStream(outputFile); 342 343 JarDiff.createPatch(oldFilePath, newFilePath, os, !doJarDiffWorkAround); 344 os.close(); 345 346 try { 347 348 if (outputFile.length() >= (new File(newFilePath).length())) { 350 _log.addDebug("JarDiff discarded - since it is bigger"); 351 return null; 352 } 353 354 File newFilePacked = new File(newFilePath + ".pack.gz"); 357 if (newFilePacked.exists()) { 358 _log.addDebug("generated jardiff size: " + outputFile.length()); 359 _log.addDebug("packed requesting file size: " + newFilePacked.length()); 360 if (outputFile.length() >= newFilePacked.length()) { 361 _log.addDebug("JarDiff discarded - packed version of requesting file is smaller"); 362 return null; 363 } 364 } 365 366 _log.addDebug("JarDiff generation succeeded"); 367 return outputFile; 368 369 } finally { 370 if (del_new) { 372 new File(newFilePath).delete(); 373 } 374 375 if (del_old) { 376 new File(oldFilePath).delete(); 377 } 378 } 379 } catch(IOException ioe) { 380 _log.addDebug("Failed to genereate jardiff", ioe); 381 return null; 382 } catch(ErrorResponseException ere) { 383 _log.addDebug("Failed to genereate jardiff", ere); 384 return null; 385 } 386 } 387 } 388 389 | Popular Tags |