Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.sagarius.offline.linker;
- /*
- * Copyright 2011 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.
- */
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.Date;
- import java.util.Map;
- import java.util.Properties;
- import java.util.SortedMap;
- import java.util.SortedSet;
- import org.apache.commons.io.IOUtils;
- import com.google.gwt.core.ext.LinkerContext;
- import com.google.gwt.core.ext.TreeLogger;
- import com.google.gwt.core.ext.UnableToCompleteException;
- import com.google.gwt.core.ext.linker.AbstractLinker;
- import com.google.gwt.core.ext.linker.Artifact;
- import com.google.gwt.core.ext.linker.ArtifactSet;
- import com.google.gwt.core.ext.linker.CompilationResult;
- import com.google.gwt.core.ext.linker.EmittedArtifact;
- import com.google.gwt.core.ext.linker.LinkerOrder;
- import com.google.gwt.core.ext.linker.LinkerOrder.Order;
- import com.google.gwt.core.ext.linker.SelectionProperty;
- import com.google.gwt.core.ext.linker.Shardable;
- import com.google.gwt.core.ext.linker.impl.SelectionInformation;
- /**
- * AppCacheLinker - linker for public path resources in the Application Cache.
- * <p>
- * To use:
- * <ol>
- * <li>Add {@code manifest="YOURMODULENAME/appcache.nocache.manifest"} to the
- * {@code <html>} tag in your base html file. E.g.,
- * {@code <html manifest="mymodule/appcache.nocache.manifest">}</li>
- * <li>Add a mime-mapping to your web.xml file:
- * <p>
- *
- * <pre>
- * {@code <mime-mapping>
- * <extension>manifest</extension>
- * <mime-type>text/cache-manifest</mime-type>
- * </mime-mapping>
- * }
- * </pre>
- *
- * </li>
- * </ol>
- * <p>
- * On every compile, this linker will regenerate the appcache.nocache.manifest
- * file with files from the public path of your module.
- * <p>
- * To obtain a manifest that contains other files in addition to those generated
- * by this linker, create a class that inherits from this one and overrides
- * {@code otherCachedFiles()}, and use it as a linker instead:
- * <p>
- *
- * <pre>
- * <blockquote>
- * {@code @Shardable}
- * public class MyAppCacheLinker extends AbstractAppCacheLinker {
- * {@code @Override}
- * protected String[] otherCachedFiles() {
- * return new String[] {"/MyApp.html","/MyApp.css"};
- * }
- * }
- * </blockquote>
- * </pre>
- */
- @Shardable
- @LinkerOrder(Order.POST)
- public class SimpleAppCacheLinker extends AbstractLinker {
- private static final String MANIFEST = "appcache.nocache.manifest";
- private static final String MANIFEST_TEMPLATE = "appcache.manifest.template";
- @Override
- public String getDescription() {
- return "AppCacheLinker";
- }
- @Override
- public ArtifactSet link(TreeLogger logger, LinkerContext context,
- ArtifactSet artifacts, boolean onePermutation)
- throws UnableToCompleteException {
- ArtifactSet toReturn = new ArtifactSet(artifacts);
- if (toReturn.find(SelectionInformation.class).isEmpty()) {
- logger.log(TreeLogger.INFO, "DevMode warning: Clobbering "
- + MANIFEST + " to allow debugging. "
- + "Recompile before deploying your app!");
- artifacts = null;
- }
- String permutation = null;
- String locale = "";
- String userAgent = "";
- SelectionProperty selectionProperty = null;
- Properties props = new Properties();
- for (CompilationResult result : artifacts.find(CompilationResult.class)) {
- permutation = result.getStrongName();
- SortedSet<SortedMap<SelectionProperty, String>> propertiesMap = result
- .getPropertyMap();
- for (SortedMap<SelectionProperty, String> sm : propertiesMap) {
- for (Map.Entry<SelectionProperty, String> e : sm.entrySet()) {
- selectionProperty = e.getKey();
- if ("locale".equals(selectionProperty.getName())) {
- locale = e.getValue();
- }
- if ("user.agent".equals(selectionProperty.getName())) {
- userAgent = e.getValue();
- }
- }
- }
- props.setProperty(userAgent + "." + locale, permutation);
- }
- // if (onePermutation) {
- // logger.log(TreeLogger.INFO, "Its one permutation");
- // return toReturn;
- // }
- toReturn.add(emitLandingPageCacheManifest(context, logger, artifacts,
- userAgent));
- return toReturn;
- }
- /**
- * Override this method to force the linker to also include more files in
- * the manifest.
- */
- protected String[] otherCachedFiles() {
- return null;
- }
- /**
- * Creates the cache-manifest resource specific for the landing page.
- *
- * @param context
- * the linker environment
- * @param logger
- * the tree logger to record to
- * @param artifacts
- * {@code null} to generate an empty cache manifest
- */
- private Artifact<?> emitLandingPageCacheManifest(LinkerContext context,
- TreeLogger logger, ArtifactSet artifacts, String userAgent)
- throws UnableToCompleteException {
- StringBuilder publicSourcesSb = new StringBuilder();
- StringBuilder staticResoucesSb = new StringBuilder();
- if (artifacts != null) {
- // Iterate over all emitted artifacts, and collect all cacheable
- // artifacts
- for (@SuppressWarnings("rawtypes")
- Artifact artifact : artifacts) {
- if (artifact instanceof EmittedArtifact) {
- EmittedArtifact ea = (EmittedArtifact) artifact;
- String pathName = ea.getPartialPath();
- if (pathName.endsWith("symbolMap")
- || pathName.endsWith(".xml.gz")
- || pathName.endsWith("rpc.log")
- || pathName.endsWith("gwt.rpc")
- || pathName.endsWith("manifest.txt")
- || pathName.startsWith("rpcPolicyManifest")) {
- // skip these resources
- } else {
- publicSourcesSb.append(pathName + "\n");
- }
- }
- }
- String[] cacheExtraFiles = getCacheExtraFiles();
- for (int i = 0; i < cacheExtraFiles.length; i++) {
- staticResoucesSb.append(cacheExtraFiles[i]);
- staticResoucesSb.append("\n");
- }
- }
- String manifest;
- try {
- manifest = IOUtils.toString(getClass().getResourceAsStream(
- MANIFEST_TEMPLATE));
- // replace the placeholder with the real data
- manifest = manifest.replace("$UNIQUEID$",
- (new Date()).getTime() + "." + Math.random()).toString();
- manifest = manifest.replace("$STATICAPPFILES$",
- staticResoucesSb.toString());
- manifest = manifest.replace("$GENAPPFILES$",
- publicSourcesSb.toString());
- logger.log(
- TreeLogger.INFO,
- "Be sure your landing page's <html> tag declares a manifest:"
- + " <html manifest="
- + context.getModuleFunctionName() + "/" + MANIFEST
- + "\">");
- // return manifest;
- } catch (IOException e) {
- logger.log(TreeLogger.ERROR,
- "Could not read cache manifest template.", e);
- throw new UnableToCompleteException();
- }
- /**
- * Manifest name according to user agent
- */
- String manifestName;
- if (userAgent.isEmpty())
- manifestName = MANIFEST;
- else
- manifestName = userAgent + "_" + MANIFEST;
- logger.log(TreeLogger.INFO, "Generating offline cache manifest "
- + manifestName);
- return emitString(logger, manifest, manifestName);
- }
- /**
- * Obtains the extra files to include in the manifest. Ensures the returned
- * array is not null.
- */
- private String[] getCacheExtraFiles() {
- String[] cacheExtraFiles = otherCachedFiles();
- return cacheExtraFiles == null ? new String[0] : Arrays.copyOf(
- cacheExtraFiles, cacheExtraFiles.length);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement