Java tutorial
/* * Smart GWT (GWT for SmartClient) * Copyright 2014 and beyond, Isomorphic Software, Inc. * * Smart GWT is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3 * is published by the Free Software Foundation. Smart GWT is also * available under typical commercial license terms - see * http://smartclient.com/license * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package com.smartgwt.linker; 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.ArtifactSet; import com.google.gwt.core.ext.linker.Artifact; import com.google.gwt.core.ext.linker.Shardable; import com.google.gwt.core.ext.linker.EmittedArtifact; import com.google.gwt.core.ext.linker.LinkerOrder; import com.google.gwt.core.ext.linker.ScriptReference; import com.google.gwt.dev.About; import com.google.gwt.dev.cfg.ModuleDef; import com.google.gwt.dev.cfg.ModuleDefLoader; import com.google.gwt.core.linker.CrossSiteIframeLinker; import java.lang.reflect.Method; import java.util.Set; @Shardable @LinkerOrder(LinkerOrder.Order.POST) public class SmartGwtScriptInjector extends AbstractLinker { private static Class XSI_LINKER_CLASS = CrossSiteIframeLinker.class; private static Class MODULE_DEF_LOADER_CLASS = ModuleDefLoader.class; private static String COMPILER_CONTEXT = "com.google.gwt.dev.CompilerContext"; // check whether we need to add a section to manually load the module's script tags private boolean forceScriptLoad(TreeLogger logger, String moduleName, Float gwtVersion) { try { ModuleDef module; Method getModuleDef; // ModuleDefLoader.loadFromClassPath has two possible signatures if (gwtVersion < 2.6f) { getModuleDef = MODULE_DEF_LOADER_CLASS.getDeclaredMethod("loadFromClassPath", new Class[] { TreeLogger.class, String.class }); module = (ModuleDef) getModuleDef.invoke(null, logger, moduleName); } else { Class compilerContextClass = Class.forName(COMPILER_CONTEXT); getModuleDef = MODULE_DEF_LOADER_CLASS.getDeclaredMethod("loadFromClassPath", new Class[] { TreeLogger.class, compilerContextClass, String.class }); module = (ModuleDef) getModuleDef.invoke(null, logger, null, moduleName); } // now use the module to check whether primary linker ist he CrossSiteIframeLinker if (module != null) return XSI_LINKER_CLASS.equals(module.getActivePrimaryLinker()); logger.log(TreeLogger.WARN, "Can't find module reference - not injecting scripts."); } catch (Throwable t) { logger.log(TreeLogger.ERROR, "Encountered an exception while trying to " + "resolve the ModuleDef for " + moduleName, t); } return false; } private static String XSI_LINKER_MODULE_BASE = "__moduleBase"; private static String LOADED_SCRIPTS = "__gwt_scriptsLoaded"; private static String SCRIPT_ANNOUNCE = " Invoking Linker SmartGwtScriptInjector\n" + " Augmenting module.nocache.js to manually load the following script tags:"; private String getScriptLoadJS(Set<ScriptReference> scriptsToLoad, LinkerContext context) { String moduleName = context.getModuleName(); System.out.println(SCRIPT_ANNOUNCE.replaceFirst("module", moduleName)); String result = "\nif (!window." + LOADED_SCRIPTS + ") " + "window." + LOADED_SCRIPTS + " = {};\n"; for (ScriptReference script : scriptsToLoad) { String src = script.getSrc(); result += "if (!" + LOADED_SCRIPTS + "['" + src + "']) {\n " + LOADED_SCRIPTS + "['" + src + "'] = true;\n " + "document.write('<script language=\"javascript\" src=\"'+" + moduleName + "." + XSI_LINKER_MODULE_BASE + "+'" + src + "\"></script>');\n" + "}\n"; System.out.println(src); } result += "\n"; return context.isOutputCompact() ? result.replaceAll("\n\\s*", "") : result; } public String getDescription() { return "ScriptInjector"; } public ArtifactSet link(TreeLogger logger, LinkerContext context, ArtifactSet artifacts, boolean permutation) throws UnableToCompleteException { Float gwtVersion = Float.parseFloat(About.getGwtVersionNum().replaceFirst("([0-9]+\\.[0-9]+).*", "$1")); String moduleName = context.getModuleName(); // do nothing if the primary linker already handles script injection automatically if (permutation || gwtVersion < 2.5f || !forceScriptLoad(logger, moduleName, gwtVersion)) { return artifacts; } // if there are no script tags present, then there's nothing to do Set<ScriptReference> scripts = artifacts.find(ScriptReference.class); if (scripts.size() == 0) return artifacts; // script tags are present, and manual load required; emit script loading ArtifactSet toReturn = new ArtifactSet(artifacts); Set<EmittedArtifact> emittedArtifacts = artifacts.find(EmittedArtifact.class); for (EmittedArtifact emittedArtifact : emittedArtifacts) { String partialPath = emittedArtifact.getPartialPath(); if (!partialPath.endsWith(".nocache.js")) continue; toReturn.remove(emittedArtifact); // add code at the end of the <moduleName>.nocache.js file to load the scripts String contents = SmartGwtLinkerUtils.getContents(emittedArtifact, logger); contents += getScriptLoadJS(scripts, context); StringBuffer sb = new StringBuffer(contents); toReturn.add(emitString(logger, sb.toString(), partialPath)); break; } return toReturn; } }