Author: [email protected]
Date: Wed May 27 06:48:54 2009
New Revision: 5475
Added:
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java
Modified:
trunk/user/src/com/google/gwt/resources/Resources.gwt.xml
trunk/user/src/com/google/gwt/resources/client/CssResource.java
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractResourceContext.java
trunk/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
trunk/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java
Log:
Add MHTML / RFC 2557 support to ClientBundle for ie6 user.agent.
Enable data: urls for ie8 user.agent.
Update documentation location in CssResource JavaDoc.
Patch by: bobv
Review by: rjrjr
Modified: trunk/user/src/com/google/gwt/resources/Resources.gwt.xml
==============================================================================
--- trunk/user/src/com/google/gwt/resources/Resources.gwt.xml (original)
+++ trunk/user/src/com/google/gwt/resources/Resources.gwt.xml Wed May 27
06:48:54 2009
@@ -23,7 +23,7 @@
<define-property name="ClientBundle.enableInlining" values="true,false"
/>
<set-property name="ClientBundle.enableInlining" value="true" />
- <!-- Specify the default behavior -->
+ <!-- Specify the default behavior which should work on all browsers -->
<generate-with
class="com.google.gwt.resources.rebind.context.StaticClientBundleGenerator">
@@ -34,6 +34,24 @@
<!-- Last-matches wins, so this will selectively override the previous
rule -->
<generate-with
+
class="com.google.gwt.resources.rebind.context.MhtmlClientBundleGenerator">
+
+ <!-- We have a number of conditions that must be satisfied -->
+ <all>
+ <!-- Is inlining enabled? -->
+ <when-property-is name="ClientBundle.enableInlining" value="true" />
+
+ <!-- Again, it's necessary to specify which types the generator runs
on -->
+ <when-type-assignable
+ class="com.google.gwt.resources.client.ClientBundle" />
+
+ <!-- Do this only with IE6 browsers -->
+ <when-property-is name="user.agent" value="ie6" />
+ </all>
+ </generate-with>
+
+ <!-- Last-matches wins, so this will selectively override the previous
rule -->
+ <generate-with
class="com.google.gwt.resources.rebind.context.InlineClientBundleGenerator">
<!-- We have a number of conditions that must be satisfied -->
@@ -51,6 +69,7 @@
<when-property-is name="user.agent" value="opera" />
<when-property-is name="user.agent" value="gecko" />
<when-property-is name="user.agent" value="gecko1_8" />
+ <when-property-is name="user.agent" value="ie8" />
</any>
</all>
</generate-with>
Modified: trunk/user/src/com/google/gwt/resources/client/CssResource.java
==============================================================================
--- trunk/user/src/com/google/gwt/resources/client/CssResource.java
(original)
+++ trunk/user/src/com/google/gwt/resources/client/CssResource.java Wed May
27 06:48:54 2009
@@ -90,8 +90,7 @@
* </li>
* </ul>
*
- * @see <a
- *
href="http://code.google.com/p/google-web-toolkit-incubator/wiki/CssResource"
+ * @see <a
href="http://code.google.com/p/google-web-toolkit/wiki/CssResource"
* >CssResource design doc</a>
*/
@ResourceGeneratorType(CssResourceGenerator.class)
Modified:
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
==============================================================================
---
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
(original)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractClientBundleGenerator.java
Wed May 27 06:48:54 2009
@@ -170,6 +170,7 @@
FieldsImpl fields = new FieldsImpl();
RequirementsImpl requirements = new RequirementsImpl(
generatorContext.getPropertyOracle());
+ doAddFieldsAndRequirements(logger, generatorContext, fields,
requirements);
/*
* Initialize the ResourceGenerators and prepare them for subsequent
code
@@ -230,6 +231,7 @@
}
finish(logger, resourceContext, generators.keySet());
+ doFinish();
// Return the name of the concrete class
return createdClassName;
@@ -241,7 +243,23 @@
* custom logic in the resource generation pass.
*/
protected abstract AbstractResourceContext createResourceContext(
- TreeLogger logger, GeneratorContext context, JClassType
resourceBundleType);
+ TreeLogger logger, GeneratorContext context, JClassType
resourceBundleType)
+ throws UnableToCompleteException;
+
+ /**
+ * Provides a hook for subtypes to add additional fields or requirements
to
+ * the bundle.
+ */
+ protected void doAddFieldsAndRequirements(TreeLogger logger,
+ GeneratorContext context, ClientBundleFields fields,
+ ClientBundleRequirements requirements) throws
UnableToCompleteException {
+ }
+
+ /**
+ * Provides a hook for finalizing generated resources.
+ */
+ protected void doFinish() throws UnableToCompleteException {
+ }
/**
* Create fields and assignments for a single ResourceGenerator.
Modified:
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractResourceContext.java
==============================================================================
---
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractResourceContext.java
(original)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/AbstractResourceContext.java
Wed May 27 06:48:54 2009
@@ -17,13 +17,32 @@
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 com.google.gwt.resources.ext.ResourceContext;
+import com.google.gwt.resources.ext.ResourceGeneratorUtil;
+
+import java.io.IOException;
+import java.net.URL;
/**
* Defines base methods for ResourceContext implementations.
*/
public abstract class AbstractResourceContext implements ResourceContext {
+ /**
+ * The largest file size that will be inlined. Note that this value is
taken
+ * before any encodings are applied.
+ */
+ protected static final int MAX_INLINE_SIZE = 2 << 15;
+
+ protected static String toBase64(byte[] data) {
+ // This is bad, but I am lazy and don't want to write _another_ encoder
+ sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
+ String base64Contents = enc.encode(data).replaceAll("\\s+", "");
+ return base64Contents;
+ }
+
private final TreeLogger logger;
private final GeneratorContext context;
private final JClassType resourceBundleType;
@@ -36,6 +55,20 @@
this.resourceBundleType = resourceBundleType;
}
+ public String deploy(URL resource, boolean xhrCompatible)
+ throws UnableToCompleteException {
+ String fileName = ResourceGeneratorUtil.baseName(resource);
+ byte[] bytes = Util.readURLAsBytes(resource);
+ try {
+ return deploy(fileName, resource.openConnection().getContentType(),
+ bytes, xhrCompatible);
+ } catch (IOException e) {
+ getLogger().log(TreeLogger.ERROR,
+ "Unable to determine mime type of resource", e);
+ throw new UnableToCompleteException();
+ }
+ }
+
public JClassType getClientBundleType() {
return resourceBundleType;
}
@@ -50,6 +83,10 @@
"Simple source name has not yet been set.");
}
return simpleSourceName;
+ }
+
+ protected GeneratorContext getContext() {
+ return context;
}
protected TreeLogger getLogger() {
Modified:
trunk/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
==============================================================================
---
trunk/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
(original)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/InlineResourceContext.java
Wed May 27 06:48:54 2009
@@ -21,15 +21,6 @@
import com.google.gwt.core.ext.typeinfo.JClassType;
class InlineResourceContext extends StaticResourceContext {
- /**
- * The largest file size that will be inlined. Note that this value is
taken
- * before any encodings are applied.
- */
- // The JLS specifies a maximum size for any string to be 2^16
characters, so
- // we'll leave some padding. Assuming a Base64 encoding, it is true that
- // (2 ^ 15) * 4/3 < 2 ^ 16, so we can safely inline files up to 32k.
- private static final int MAX_INLINE_SIZE = 2 << 15;
-
InlineResourceContext(TreeLogger logger, GeneratorContext context,
JClassType resourceBundleType) {
super(logger, context, resourceBundleType);
@@ -44,9 +35,7 @@
if ((!xhrCompatible) && (data.length < MAX_INLINE_SIZE)) {
logger.log(TreeLogger.DEBUG, "Inlining", null);
- // This is bad, but I am lazy and don't want to write _another_
encoder
- sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
- String base64Contents = enc.encode(data).replaceAll("\\s+", "");
+ String base64Contents = toBase64(data);
return "\"data:" + mimeType + ";base64," + base64Contents + "\"";
} else {
Added:
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java
==============================================================================
--- (empty file)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlClientBundleGenerator.java
Wed May 27 06:48:54 2009
@@ -0,0 +1,85 @@
+/*
+ * 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.core.ext.typeinfo.JType;
+import com.google.gwt.core.ext.typeinfo.TypeOracleException;
+import com.google.gwt.dev.util.Util;
+import com.google.gwt.resources.ext.ClientBundleFields;
+import com.google.gwt.resources.ext.ClientBundleRequirements;
+
+/**
+ * Generates Multipart HTML files.
+ */
+public class MhtmlClientBundleGenerator extends
AbstractClientBundleGenerator {
+
+ private static final String BUNDLE_EXTENSION = ".cache.txt";
+
+ private MhtmlResourceContext resourceContext;
+ private String partialPath;
+
+ @Override
+ protected AbstractResourceContext createResourceContext(TreeLogger
logger,
+ GeneratorContext context, JClassType resourceBundleType) {
+ resourceContext = new MhtmlResourceContext(logger, context,
+ resourceBundleType);
+
+ /*
+ * TODO: figure out how to make the filename stable based on actual
content.
+ */
+ partialPath =
Util.computeStrongName(Util.getBytes(resourceBundleType.getQualifiedSourceName()
+ + System.currentTimeMillis()))
+ + BUNDLE_EXTENSION;
+ resourceContext.setPartialPath(partialPath);
+
+ return resourceContext;
+ }
+
+ @Override
+ protected void doAddFieldsAndRequirements(TreeLogger logger,
+ GeneratorContext generatorContext, ClientBundleFields fields,
+ ClientBundleRequirements requirements) throws
UnableToCompleteException {
+ JType booleanType;
+ JType stringType;
+ try {
+ booleanType = generatorContext.getTypeOracle().parse("boolean");
+ stringType =
generatorContext.getTypeOracle().parse("java.lang.String");
+ } catch (TypeOracleException e) {
+ logger.log(TreeLogger.ERROR, "Expected type not in type oracle", e);
+ throw new UnableToCompleteException();
+ }
+
+ // GWT.getModuleBaseURL().startsWith("https")
+ String isHttpsIdent = fields.define(booleanType, "isHttps",
+ "GWT.getModuleBaseURL().startsWith(\"https\")", true, true);
+ resourceContext.setIsHttpsIdent(isHttpsIdent);
+
+ // "mhtml:" + GWT.getModuleBaseURL() + "partialPath!cid:"
+ String bundleBaseIdent = fields.define(stringType, "bundleBase",
+ "\"mhtml:\" + GWT.getModuleBaseURL() + \"" + partialPath
+ "!cid:\"",
+ true, true);
+ resourceContext.setBundleBaseIdent(bundleBaseIdent);
+ }
+
+ @Override
+ protected void doFinish() throws UnableToCompleteException {
+ resourceContext.finish();
+ }
+}
Added:
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java
==============================================================================
--- (empty file)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/MhtmlResourceContext.java
Wed May 27 06:48:54 2009
@@ -0,0 +1,133 @@
+/*
+ * 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 java.io.OutputStream;
+import java.io.PrintWriter;
+
+/**
+ * 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;
+
+ /**
+ * Output is lazily initialized in the case that all deployed resources
are
+ * large.
+ */
+ private OutputStream out;
+ private String partialPath;
+ private PrintWriter pw;
+
+ MhtmlResourceContext(TreeLogger logger, GeneratorContext context,
+ JClassType resourceBundleType) {
+ super(logger, context, resourceBundleType);
+ }
+
+ @Override
+ public String deploy(String suggestedFileName, String mimeType, byte[]
data,
+ boolean xhrCompatible) throws UnableToCompleteException {
+
+ assert partialPath != null : "partialPath";
+ 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,
+ xhrCompatible);
+
+ /*
+ * ie6 doesn't treat XHRs to mhtml as cross-site, but ie8 does, so
we'll
+ * play it safe here.
+ */
+ if (xhrCompatible || data.length > MAX_INLINE_SIZE) {
+ return staticLocation;
+ }
+
+ if (out == null) {
+ out = getContext().tryCreateResource(getLogger(), partialPath);
+ 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 + ">");
+ pw.println("Content-Type:" + mimeType);
+ pw.println("Content-Transfer-Encoding:base64");
+ pw.println();
+ pw.println(base64);
+ pw.println();
+
+ /*
+ * Return a Java expression:
+ *
+ * isHttps ? (staticLocation) : (bundleBaseIdent + "location")
+ */
+ return isHttpsIdent + " ? (" + staticLocation + ") : (" +
bundleBaseIdent
+ + " + \"" + location + "\")";
+ }
+
+ public void finish() throws UnableToCompleteException {
+ if (out != null) {
+ pw.close();
+ getContext().commitResource(getLogger(), out);
+ }
+ }
+
+ @Override
+ public boolean supportsDataUrls() {
+ return true;
+ }
+
+ void setBundleBaseIdent(String ident) {
+ bundleBaseIdent = ident;
+ }
+
+ void setIsHttpsIdent(String ident) {
+ isHttpsIdent = ident;
+ }
+
+ void setPartialPath(String partialPath) {
+ this.partialPath = partialPath;
+ }
+}
Modified:
trunk/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java
==============================================================================
---
trunk/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java
(original)
+++
trunk/user/src/com/google/gwt/resources/rebind/context/StaticResourceContext.java
Wed May 27 06:48:54 2009
@@ -23,11 +23,9 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dev.util.Util;
-import com.google.gwt.resources.ext.ResourceGeneratorUtil;
import java.io.IOException;
import java.io.OutputStream;
-import java.net.URL;
class StaticResourceContext extends AbstractResourceContext {
/**
@@ -50,8 +48,7 @@
// See if filename obfuscation should be enabled
String enableRenaming = null;
try {
- ConfigurationProperty prop = propertyOracle.getConfigurationProperty(
- ENABLE_RENAMING);
+ ConfigurationProperty prop =
propertyOracle.getConfigurationProperty(ENABLE_RENAMING);
enableRenaming = prop.getValues().get(0);
} catch (BadPropertyValueException e) {
logger.log(TreeLogger.ERROR, "Bad value for " + ENABLE_RENAMING, e);
@@ -103,20 +100,6 @@
// Return a Java expression
return "GWT.getModuleBaseURL() + \"" + outputName + "\"";
- }
-
- public String deploy(URL resource, boolean xhrCompatible)
- throws UnableToCompleteException {
- String fileName = ResourceGeneratorUtil.baseName(resource);
- byte[] bytes = Util.readURLAsBytes(resource);
- try {
- return deploy(fileName, resource.openConnection().getContentType(),
- bytes, xhrCompatible);
- } catch (IOException e) {
- getLogger().log(TreeLogger.ERROR,
- "Unable to determine mime type of resource", e);
- throw new UnableToCompleteException();
- }
}
public boolean supportsDataUrls() {
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---