예제 #1
0
  /** Returns a JarDiff for the given request */
  public synchronized DownloadResponse getJarDiffEntry(
      ResourceCatalog catalog, DownloadRequest dreq, JnlpResource res) {
    if (dreq.getCurrentVersionId() == null) return null;

    // check whether the request is from javaws 1.0/1.0.1
    // do not generate minimal jardiff if it is from 1.0/1.0.1
    boolean doJarDiffWorkAround = isJavawsVersion(dreq, "1.0*");

    // First do a lookup to find a match
    JarDiffKey key =
        new JarDiffKey(
            res.getName(),
            dreq.getCurrentVersionId(),
            res.getReturnVersionId(),
            !doJarDiffWorkAround);

    JarDiffEntry entry = (JarDiffEntry) _jarDiffEntries.get(key);
    // If entry is not found, then the querty has not been made.
    if (entry == null) {
      if (_log.isInformationalLevel()) {
        _log.addInformational(
            "servlet.log.info.jardiff.gen",
            res.getName(),
            dreq.getCurrentVersionId(),
            res.getReturnVersionId());
      }
      File f = generateJarDiff(catalog, dreq, res, doJarDiffWorkAround);
      if (f == null) {
        _log.addWarning(
            "servlet.log.warning.jardiff.failed",
            res.getName(),
            dreq.getCurrentVersionId(),
            res.getReturnVersionId());
      }
      // Store entry in table
      entry = new JarDiffEntry(f);
      _jarDiffEntries.put(key, entry);
    }

    // Check for no JarDiff to return
    if (entry.getJarDiffFile() == null) {
      return null;
    } else {
      return DownloadResponse.getFileDownloadResponse(
          entry.getJarDiffFile(),
          _jarDiffMimeType,
          entry.getJarDiffFile().lastModified(),
          res.getReturnVersionId());
    }
  }
예제 #2
0
  private File generateJarDiff(
      ResourceCatalog catalog,
      DownloadRequest dreq,
      JnlpResource res,
      boolean doJarDiffWorkAround) {
    boolean del_old = false;
    boolean del_new = false;

    // Lookup up file for request version
    DownloadRequest fromDreq = dreq.getFromDownloadRequest();
    try {
      JnlpResource fromRes = catalog.lookupResource(fromDreq);

      /* Get file locations */
      String newFilePath = _servletContext.getRealPath(res.getPath());
      String oldFilePath = _servletContext.getRealPath(fromRes.getPath());

      // fix for 4720897
      if (newFilePath == null) {
        newFilePath = getRealPath(res.getPath());
        if (newFilePath != null) del_new = true;
      }

      if (oldFilePath == null) {
        oldFilePath = getRealPath(fromRes.getPath());
        if (oldFilePath != null) del_old = true;
      }

      if (newFilePath == null || oldFilePath == null) {
        return null;
      }

      // Create temp. file to store JarDiff file in
      File tempDir = (File) _servletContext.getAttribute("javax.servlet.context.tempdir");

      // fix for 4653036: JarDiffHandler() should use javax.servlet.context.tempdir to store the
      // jardiff
      File outputFile = File.createTempFile("jnlp", ".jardiff", tempDir);

      _log.addDebug(
          "Generating Jardiff between "
              + oldFilePath
              + " and "
              + newFilePath
              + " Store in "
              + outputFile);

      // Generate JarDiff
      OutputStream os = new FileOutputStream(outputFile);

      JarDiff.createPatch(oldFilePath, newFilePath, os, !doJarDiffWorkAround);
      os.close();

      try {

        // Check that Jardiff is smaller, or return null
        if (outputFile.length() >= (new File(newFilePath).length())) {
          _log.addDebug("JarDiff discarded - since it is bigger");
          return null;
        }

        // Check that Jardiff is smaller than the packed version of
        // the new file, if the file exists at all
        File newFilePacked = new File(newFilePath + ".pack.gz");
        if (newFilePacked.exists()) {
          _log.addDebug("generated jardiff size: " + outputFile.length());
          _log.addDebug("packed requesting file size: " + newFilePacked.length());
          if (outputFile.length() >= newFilePacked.length()) {
            _log.addDebug("JarDiff discarded - packed version of requesting file is smaller");
            return null;
          }
        }

        _log.addDebug("JarDiff generation succeeded");
        return outputFile;

      } finally {
        // delete the temporarily downloaded file
        if (del_new) {
          new File(newFilePath).delete();
        }

        if (del_old) {
          new File(oldFilePath).delete();
        }
      }
    } catch (IOException ioe) {
      _log.addDebug("Failed to genereate jardiff", ioe);
      return null;
    } catch (ErrorResponseException ere) {
      _log.addDebug("Failed to genereate jardiff", ere);
      return null;
    }
  }
  /* Main method to lookup an entry */
  public synchronized DownloadResponse getJnlpFile(JnlpResource jnlpres, DownloadRequest dreq)
      throws IOException {
    String path = jnlpres.getPath();
    URL resource = jnlpres.getResource();
    long lastModified = jnlpres.getLastModified();

    _log.addDebug("lastModified: " + lastModified + " " + new Date(lastModified));
    if (lastModified == 0) {
      _log.addWarning("servlet.log.warning.nolastmodified", path);
    }

    // fix for 4474854:  use the request URL as key to look up jnlp file
    // in hash map
    String reqUrl = HttpUtils.getRequestURL(dreq.getHttpRequest()).toString();

    // Check if entry already exist in HashMap
    JnlpFileEntry jnlpFile = (JnlpFileEntry) _jnlpFiles.get(reqUrl);

    if (jnlpFile != null && jnlpFile.getLastModified() == lastModified) {
      // Entry found in cache, so return it
      return jnlpFile.getResponse();
    }

    // Read information from WAR file
    long timeStamp = lastModified;
    String mimeType = _servletContext.getMimeType(path);
    if (mimeType == null) mimeType = JNLP_MIME_TYPE;

    StringBuilder jnlpFileTemplate = new StringBuilder();
    URLConnection conn = resource.openConnection();

    final InputStream is = conn.getInputStream();
    final InputStreamReader reader = new InputStreamReader(is);
    char[] chars = new char[1024];
    int read;

    while ((read = reader.read(chars)) != -1) {
      jnlpFileTemplate.append(chars, 0, read);
    }

    try {
      is.close();
    } catch (IOException e) {
      // should never happen and if it does, we're not handling this. It should be save to ignore
    }

    String jnlpFileContent =
        specializeJnlpTemplate(dreq.getHttpRequest(), path, jnlpFileTemplate.toString());

    // Convert to bytes as a UTF-8 encoding
    byte[] byteContent = jnlpFileContent.getBytes("UTF-8");

    // Create entry
    DownloadResponse resp =
        DownloadResponse.getFileDownloadResponse(
            byteContent, mimeType, timeStamp, jnlpres.getReturnVersionId());
    jnlpFile = new JnlpFileEntry(resp, lastModified);
    _jnlpFiles.put(reqUrl, jnlpFile);

    return resp;
  }
  /* Main method to lookup an entry (NEW for JavaWebStart 1.5+) */
  public synchronized DownloadResponse getJnlpFileEx(JnlpResource jnlpres, DownloadRequest dreq)
      throws IOException {
    String path = jnlpres.getPath();
    URL resource = jnlpres.getResource();
    long lastModified = jnlpres.getLastModified();

    _log.addDebug("lastModified: " + lastModified + " " + new Date(lastModified));
    if (lastModified == 0) {
      _log.addWarning("servlet.log.warning.nolastmodified", path);
    }

    // fix for 4474854:  use the request URL as key to look up jnlp file
    // in hash map
    String reqUrl = HttpUtils.getRequestURL(dreq.getHttpRequest()).toString();
    // SQE: To support query string, we changed the hash key from Request URL to (Request URL +
    // query string)
    if (dreq.getQuery() != null) reqUrl += dreq.getQuery();

    // Check if entry already exist in HashMap
    JnlpFileEntry jnlpFile = (JnlpFileEntry) _jnlpFiles.get(reqUrl);

    if (jnlpFile != null && jnlpFile.getLastModified() == lastModified) {
      // Entry found in cache, so return it
      return jnlpFile.getResponse();
    }

    // Read information from WAR file
    long timeStamp = lastModified;
    String mimeType = _servletContext.getMimeType(path);
    if (mimeType == null) mimeType = JNLP_MIME_TYPE;

    StringBuffer jnlpFileTemplate = new StringBuffer();
    URLConnection conn = resource.openConnection();
    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
    String line = br.readLine();
    if (line != null && line.startsWith("TS:")) {
      timeStamp = parseTimeStamp(line.substring(3));
      _log.addDebug("Timestamp: " + timeStamp + " " + new Date(timeStamp));
      if (timeStamp == 0) {
        _log.addWarning("servlet.log.warning.notimestamp", path);
        timeStamp = lastModified;
      }
      line = br.readLine();
    }
    while (line != null) {
      jnlpFileTemplate.append(line);
      line = br.readLine();
    }

    String jnlpFileContent =
        specializeJnlpTemplate(dreq.getHttpRequest(), path, jnlpFileTemplate.toString());

    /* SQE: We need to add query string back to href in jnlp file. We also need to handle JRE requirement for
     * the test. We reconstruct the xml DOM object, modify the value, then regenerate the jnlpFileContent.
     */
    String query = dreq.getQuery();
    String testJRE = dreq.getTestJRE();
    _log.addDebug("Double check query string: " + query);
    // For backward compatibility: Always check if the href value exists.
    // Bug 4939273: We will retain the jnlp template structure and will NOT add href value. Above
    // old
    // approach to always check href value caused some test case not run.

    // NOTE OTC:
    // This section has been rewritten:
    // - Switched from JAX to JDOM, allowing to preserve the formatting of the file
    // - regeneration based on the DOM will only be done if there are any changes to the file
    if (query != null && query.trim().length() > 0) {
      byte[] cb = jnlpFileContent.getBytes("UTF-8");

      try {

        final XMLInputFactory factory = XMLInputFactory.newFactory();
        final XMLEventReader reader = factory.createXMLEventReader(new ByteArrayInputStream(cb));

        final StAXEventBuilder builder = new StAXEventBuilder();
        final org.jdom2.Document document = builder.build(reader);

        boolean modified = false;

        final org.jdom2.Element root = document.getRootElement();

        if (root.getAttribute("href") != null) {
          String href = root.getAttribute("href").getValue();
          root.setAttribute("href", href + "?" + query);
          modified = true;
        }
        // Update version value for j2se tag
        if (testJRE != null) {
          org.jdom2.Element j2se = root.getChild("j2se");
          if (j2se != null) {
            String ver = j2se.getAttribute("version").getValue();
            if (ver.length() > 0) {
              j2se.setAttribute("version", testJRE);
              modified = true;
            }
          }
        }

        if (modified) {
          // we're only regenerating only if there have been any changes.
          final XMLOutputter outputter = new XMLOutputter();
          final StringWriter sw = new StringWriter();
          outputter.output(document, sw);
          jnlpFileContent = sw.toString();
        }

        _log.addDebug("Converted jnlpFileContent: " + jnlpFileContent);
        // Since we modified the file on the fly, we always update the timestamp value with current
        // time
        if (modified) {
          timeStamp = new Date().getTime();
          _log.addDebug("Last modified on the fly:  " + timeStamp);
        }
      } catch (Exception e) {
        _log.addDebug(e.toString(), e);
      }
    }

    // Convert to bytes as a UTF-8 encoding
    byte[] byteContent = jnlpFileContent.getBytes("UTF-8");

    // Create entry
    DownloadResponse resp =
        DownloadResponse.getFileDownloadResponse(
            byteContent, mimeType, timeStamp, jnlpres.getReturnVersionId());
    jnlpFile = new JnlpFileEntry(resp, lastModified);
    _jnlpFiles.put(reqUrl, jnlpFile);

    return resp;
  }