All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.resources.rebind.context.MhtmlResourceContext Maven / Gradle / Ivy

There is a newer version: 2.12.1
Show newest version
/*
 * Copyright 2009 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.resources.rebind.context;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dev.util.Util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * Encodes resources into Multipart HTML files. In order to avoid mixed-content
 * warnings using the mhtml: protocol, this context will include a fallback to
 * static files when the module has been loaded from an https source.
 * 
 * @see "RFC 2557"
 */
public class MhtmlResourceContext extends StaticResourceContext {

  /**
   * The MIME multipart boundary token. This is chosen so that it does not
   * overlap with any possible base64 sequences.
   */
  private static final String BOUNDARY = "_GWT";
  private static final String ID_PREFIX = "r";

  private String bundleBaseIdent;
  private int id = 0;
  private String isHttpsIdent;
  private final Map strongNameToExpressions = new HashMap();

  /**
   * Output is lazily initialized in the case that all deployed resources are
   * large.
   */
  private ByteArrayOutputStream out;
  private String partialPath;
  private PrintWriter pw;

  MhtmlResourceContext(TreeLogger logger, GeneratorContext context,
      JClassType resourceBundleType, ClientBundleContext clientBundleCtx) {
    super(logger, context, resourceBundleType, clientBundleCtx);
  }

  @Override
  public String deploy(String suggestedFileName, String mimeType, byte[] data,
      boolean forceExternal) throws UnableToCompleteException {

    String strongName = Util.computeStrongName(data);
    String toReturn = strongNameToExpressions.get(strongName);
    if (toReturn != null) {
      return toReturn;
    }

    assert isHttpsIdent != null : "isHttpsIdent";
    assert bundleBaseIdent != null : "bundleBaseIdent";

    /*
     * mhtml URLs don't work in HTTPS, so we'll always need the static versions
     * as a fallback.
     */
    String staticLocation = super.deploy(suggestedFileName, mimeType, data,
        forceExternal);

    /*
     * ie6 doesn't treat XHRs to mhtml as cross-site, but ie8 does, so we'll
     * play it safe here.
     */
    if (forceExternal || data.length > MAX_INLINE_SIZE) {
      return staticLocation;
    }

    if (out == null) {
      out = new ByteArrayOutputStream();
      pw = new PrintWriter(out);
      pw.println("Content-Type: multipart/related; boundary=\"" + BOUNDARY
          + "\"");
      pw.println();
    }

    String location = ID_PREFIX + id++;
    String base64 = toBase64(data);

    pw.println("--" + BOUNDARY);
    pw.println("Content-Id:<" + location + ">");
    // CHECKSTYLE_OFF
    pw.println("Content-Type:" + mimeType);
    // CHECKSTYLE_ON
    pw.println("Content-Transfer-Encoding:base64");
    pw.println();
    pw.println(base64);
    pw.println();

    /*
     * Return a Java expression:
     * 
     * isHttps ? (staticLocation) : (bundleBaseIdent + "location")
     */
    toReturn = isHttpsIdent + " ? (" + staticLocation + ") : ("
        + bundleBaseIdent + " + \"" + location + "\")";
    strongNameToExpressions.put(strongName, toReturn);
    return toReturn;
  }

  public void finish() throws UnableToCompleteException {
    if (out != null) {
      TreeLogger logger = getLogger().branch(TreeLogger.DEBUG,
          "Writing container to disk");
      pw.close();

      assert partialPath != null : "partialPath";

      OutputStream realOut = getContext().tryCreateResource(logger, partialPath);
      try {
        realOut.write(out.toByteArray());
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to write container file", e);
      }
      getContext().commitResource(logger, realOut);
    }
  }

  void setBundleBaseIdent(String ident) {
    bundleBaseIdent = ident;
  }

  void setIsHttpsIdent(String ident) {
    isHttpsIdent = ident;
  }

  void setPartialPath(String partialPath) {
    this.partialPath = partialPath;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy