public void begin(String namespace, String name, Attributes attributes) throws Exception { String className = attributes.getValue("type"); if (className != null) { ModuleConfig mc = (ModuleConfig) digester.peek(); mc.setActionForwardClass(className); } }
@Override protected void doGet(HttpExchange exchange, QueryData data, Config config) throws IOException { Compilation compilation = getCompilation(exchange, data, config); if (compilation == null) { return; } if (!compilation.usesModules()) { HttpUtil.writeErrorMessageResponse(exchange, "This configuration does not use modules"); return; } // Get the size of each module. ModuleConfig moduleConfig = config.getModuleConfig(); Map<String, List<String>> invertedDependencyTree = moduleConfig.getInvertedDependencyTree(); Function<String, String> moduleNameToUri = moduleConfig.createModuleNameToUriFunction(); ImmutableMap.Builder<String, Pair<Integer, Integer>> builder = ImmutableMap.builder(); final boolean isDebugMode = false; for (String module : invertedDependencyTree.keySet()) { // The file size is in bytes, assuming UTF-8 input. String compiledCode = compilation.getCodeForModule(module, isDebugMode, moduleNameToUri); int uncompressedSize = compiledCode.getBytes(Charsets.UTF_8).length; int gzippedSize = GzipUtil.getGzipSize(compiledCode); builder.put(module, Pair.of(uncompressedSize, gzippedSize)); } Map<String, Pair<Integer, Integer>> moduleSizes = builder.build(); // Construct the SVG. SetMultimap<Integer, String> moduleDepths = calculateModuleDepths(moduleConfig.getRootModule(), invertedDependencyTree); Map<String, List<JsInput>> moduleToInputs; try { moduleToInputs = moduleConfig.partitionInputsIntoModules(config.getManifest()); } catch (CompilationException e) { throw new RuntimeException(e); } Pair<String, Dimension> svg = generateSvg( config.getId(), moduleDepths, invertedDependencyTree, moduleSizes, moduleToInputs); // Populate Soy template. Dimension svgDimension = svg.getSecond(); SoyMapData mapData = new SoyMapData( ImmutableMap.<String, Object>builder() .put("configId", config.getId()) .put("svg", svg.getFirst()) .put("svgWidth", svgDimension.width) .put("svgHeight", svgDimension.height) .build()); String xhtml = TOFU.newRenderer("org.plovr.modules").setData(mapData).render(); // Write the response. Headers responseHeaders = exchange.getResponseHeaders(); responseHeaders.set("Content-Type", "text/xml"); exchange.sendResponseHeaders(200, xhtml.length()); Writer responseBody = new OutputStreamWriter(exchange.getResponseBody()); responseBody.write(xhtml); responseBody.close(); }
public boolean raisesWarning() { if (!calculated) getPercentages(); for (int i = 0; i < lowerQuartile.length; i++) { if (lowerQuartile[i] < ModuleConfig.getParam("quality_base_lower", "warn") || medians[i] < ModuleConfig.getParam("quality_base_median", "warn")) { return true; } } return false; }
/** * Creates the JSON needed to define the PLOVR_MODULE_INFO variable. * * @param moduleConfig */ static JsonObject createModuleInfo(ModuleConfig moduleConfig) { JsonObject obj = new JsonObject(); for (String moduleName : moduleConfig.getModuleNames()) { JsonArray modulesThatMustBeLoadedFirst = new JsonArray(); for (String module : moduleConfig.getModuleInfo(moduleName).getDeps()) { modulesThatMustBeLoadedFirst.add(new JsonPrimitive(module)); } obj.add(moduleName, modulesThatMustBeLoadedFirst); } return obj; }
@Override protected void doGet(HttpExchange exchange, QueryData data, Config config) throws IOException { Compilation compilation = getCompilation(exchange, data, config); if (compilation == null) { return; } String configId = config.getId(); List<JsInput> inputs; if (compilation.usesModules()) { ModuleConfig moduleConfig = config.getModuleConfig(); Map<String, List<JsInput>> moduleToInputs; try { moduleToInputs = moduleConfig.partitionInputsIntoModules(config.getManifest()); } catch (CompilationException e) { throw new RuntimeException(e); } String module = data.getParam("module"); inputs = moduleToInputs.get(module); } else { try { inputs = config.getManifest().getInputsInCompilationOrder(); } catch (CompilationException e) { HttpUtil.writeErrorMessageResponse(exchange, e.getMessage()); return; } } // Build up the list of hyperlinks. Function<JsInput, String> converter = InputFileHandler.createInputNameToUriConverter(server, exchange, configId); SoyListData inputData = new SoyListData(); for (JsInput input : inputs) { SoyMapData inputDatum = new SoyMapData(); inputDatum.put("href", converter.apply(input)); inputDatum.put("name", input.getName()); inputData.add(inputDatum); } SoyMapData soyData = new SoyMapData(); soyData.put("inputs", inputData); soyData.put("configId", configId); // Write the response. Headers responseHeaders = exchange.getResponseHeaders(); responseHeaders.set("Content-Type", "text/html"); String html = TOFU.newRenderer("org.plovr.list").setData(soyData).render(); exchange.sendResponseHeaders(200, html.length()); Writer responseBody = new OutputStreamWriter(exchange.getResponseBody()); responseBody.write(html); responseBody.close(); }
public boolean ignoreInReport() { // We don't show this if there is no quality data. if (ModuleConfig.getParam("quality_base", "ignore") > 0 || qualityCounts.length == 0) { return true; } return false; }
/** Creates the JSON needed to define the PLOVR_MODULE_URIS variable. */ static JsonObject createModuleUris( ModuleConfig moduleConfig, Function<String, String> moduleNameToUri) { JsonObject obj = new JsonObject(); for (String moduleName : moduleConfig.getModuleNames()) { obj.addProperty(moduleName, moduleNameToUri.apply(moduleName)); } return obj; }
/** Basic check that shouldn't detect an error. */ public void testCheckCircularInheritance() { FormBeanConfig child = new FormBeanConfig(); child.setName("child"); child.setExtends("baseForm"); FormBeanConfig grandChild = new FormBeanConfig(); grandChild.setName("grandChild"); grandChild.setExtends("child"); config.addFormBeanConfig(child); config.addFormBeanConfig(grandChild); assertTrue( "Circular inheritance shouldn't have been detected", !grandChild.checkCircularInheritance(config)); }
public Object createObject(Attributes attributes) { // Identify the name of the class to instantiate String className = attributes.getValue("className"); if (className == null) { ModuleConfig mc = (ModuleConfig) digester.peek(1); className = mc.getActionForwardClass(); } // Instantiate the new object and return it Object actionForward = null; try { actionForward = RequestUtils.applicationInstance(className); } catch (Exception e) { digester.getLogger().error("ActionForwardFactory.createObject: ", e); } return actionForward; }
/** Test that processExtends() makes sure that a base form's own extension has been processed. */ public void testProcessExtendsBaseFormExtends() throws Exception { CustomFormBeanConfig first = new CustomFormBeanConfig(); first.setName("first"); CustomFormBeanConfig second = new CustomFormBeanConfig(); second.setName("second"); second.setExtends("first"); config.addFormBeanConfig(first); config.addFormBeanConfig(second); // set baseForm to extend second baseForm.setExtends("second"); baseForm.processExtends(config); assertTrue("The first form's processExtends() wasn't called", first.processExtendsCalled); assertTrue("The second form's processExtends() wasn't called", second.processExtendsCalled); }
/** Basic check that SHOULD detect an error. */ public void testCheckCircularInheritanceError() { FormBeanConfig child = new FormBeanConfig(); child.setName("child"); child.setExtends("baseForm"); FormBeanConfig grandChild = new FormBeanConfig(); grandChild.setName("grandChild"); grandChild.setExtends("child"); // establish the circular relationship with base baseForm.setExtends("grandChild"); config.addFormBeanConfig(child); config.addFormBeanConfig(grandChild); assertTrue( "Circular inheritance should've been detected", grandChild.checkCircularInheritance(config)); }
/** Set up instance variables required by this test case. */ public void setUp() { ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory(); config = factoryObject.createModuleConfig(""); // setup the base form baseForm = new FormBeanConfig(); baseForm.setName("baseForm"); baseForm.setType("org.apache.struts.action.DynaActionForm"); // set up id, name, and score FormPropertyConfig property = new FormPropertyConfig(); property.setName("id"); property.setType("java.lang.String"); baseForm.addFormPropertyConfig(property); property = new FormPropertyConfig(); property.setName("name"); property.setType("java.lang.String"); property.setProperty("count", "10"); baseForm.addFormPropertyConfig(property); property = new FormPropertyConfig(); property.setName("score"); property.setType("java.lang.String"); baseForm.addFormPropertyConfig(property); property = new FormPropertyConfig(); property.setName("message"); property.setType("java.lang.String"); baseForm.addFormPropertyConfig(property); // register it to our config config.addFormBeanConfig(baseForm); }
/** * Test a typical form bean configuration extension where various properties should be inherited * from a base form. This method checks all the properties. */ public void testInheritFrom() throws Exception { // give baseForm some arbitrary parameters String baseFormCount = "1"; baseForm.setProperty("count", baseFormCount); // create a basic subform FormBeanConfig subForm = new FormBeanConfig(); String subFormName = "subForm"; subForm.setName(subFormName); subForm.setExtends("baseForm"); // override score FormPropertyConfig property = new FormPropertyConfig(); property.setName("score"); property.setType("java.lang.Integer"); subForm.addFormPropertyConfig(property); // ... and id property = new FormPropertyConfig(); property.setName("id"); property.setType("java.lang.String"); property.setInitial("unknown"); subForm.addFormPropertyConfig(property); // ... and message property = new FormPropertyConfig(); property.setName("message"); property.setType("java.lang.String"); property.setSize(10); subForm.addFormPropertyConfig(property); config.addFormBeanConfig(subForm); subForm.inheritFrom(baseForm); // check that our subForm is still the one in the config assertSame("subForm no longer in ModuleConfig", subForm, config.findFormBeanConfig("subForm")); // check our configured sub form assertNotNull("Form bean type was not inherited", subForm.getType()); assertEquals("Wrong form bean name", subFormName, subForm.getName()); assertEquals("Wrong form bean type", baseForm.getType(), subForm.getType()); assertEquals("Wrong restricted value", baseForm.isRestricted(), subForm.isRestricted()); FormPropertyConfig[] formPropertyConfigs = subForm.findFormPropertyConfigs(); assertEquals("Wrong prop count", 4, formPropertyConfigs.length); // we want to check that the form is EXACTLY as we want it, so // here are some fine grain checks property = subForm.findFormPropertyConfig("name"); FormPropertyConfig original = baseForm.findFormPropertyConfig("name"); assertNotNull("'name' property was not inherited", property); assertEquals("Wrong type for name", original.getType(), property.getType()); assertEquals("Wrong initial value for name", original.getInitial(), property.getInitial()); assertEquals("Wrong size value for name", original.getSize(), property.getSize()); property = subForm.findFormPropertyConfig("id"); original = baseForm.findFormPropertyConfig("id"); assertNotNull("'id' property was not found", property); assertEquals("Wrong type for id", original.getType(), property.getType()); assertEquals("Wrong initial value for id", "unknown", property.getInitial()); assertEquals("Wrong size value for id", original.getSize(), property.getSize()); property = subForm.findFormPropertyConfig("score"); original = baseForm.findFormPropertyConfig("score"); assertNotNull("'score' property was not found", property); assertEquals("Wrong type for score", "java.lang.Integer", property.getType()); assertEquals("Wrong initial value for score", original.getInitial(), property.getInitial()); assertEquals("Wrong size value for score", original.getSize(), property.getSize()); property = subForm.findFormPropertyConfig("message"); original = baseForm.findFormPropertyConfig("message"); assertNotNull("'message' property was not found", property); assertEquals("Wrong type for message", original.getType(), property.getType()); assertEquals("Wrong initial value for message", original.getInitial(), property.getInitial()); assertEquals("Wrong size value for message", 10, property.getSize()); property = subForm.findFormPropertyConfig("name"); original = baseForm.findFormPropertyConfig("name"); assertEquals( "Arbitrary property not found", original.getProperty("count"), property.getProperty("count")); String count = subForm.getProperty("count"); assertEquals("Arbitrary property was not inherited", baseFormCount, count); }
/** * Writes out all of the module files. This method is only applicable when modules are used. This * is expected to be used only with the build command. * * @throws IOException */ public void writeCompiledCodeToFiles( final Function<String, String> moduleNameToUri, String sourceMapPath) throws IOException { if (modules == null) { throw new IllegalStateException("This compilation does not use modules"); } ModuleConfig moduleConfig = config.getModuleConfig(); Map<String, File> moduleToOutputPath = moduleConfig.getModuleToOutputPath(); final Map<String, String> moduleNameToFingerprint = Maps.newHashMap(); final boolean isDebugMode = false; for (JSModule module : modules) { String moduleName = module.getName(); File outputFile = moduleToOutputPath.get(moduleName); com.google.common.io.Files.createParentDirs(outputFile); // Reset the source map if it is not going to be reset later in this // loop // when the source map is written to disk. final boolean resetSourceMap = (sourceMapPath == null); String moduleCode = getCodeForModule(moduleName, isDebugMode, moduleNameToUri, resetSourceMap); // Fingerprint the file, if appropriate. if (config.shouldFingerprintJsFiles()) { String fileName = outputFile.getName(); String fingerprint = Md5Util.hashJs(moduleCode); moduleNameToFingerprint.put(moduleName, fingerprint); fileName = insertFingerprintIntoName(fileName, fingerprint); outputFile = new File(outputFile.getParentFile(), fileName); } Files.write(moduleCode, outputFile); // It turns out that the SourceMap will not be populated until after // the // Compiler's internal representation has been output as source // code, so // it should only be written out to a file after the compiled code // has // been generated. if (sourceMapPath != null) { Writer writer = Streams.createFileWriter(sourceMapPath + "_" + moduleName, config); // This is safe because getCodeForModule() was just called, // which has // the side-effect of calling compiler.toSource(module). SourceMap sourceMap = compiler.getSourceMap(); sourceMap.appendTo(writer, moduleName); sourceMap.reset(); Closeables.close(writer, false); } } if (moduleConfig.excludeModuleInfoFromRootModule()) { File outputFile = moduleConfig.getModuleInfoPath(); com.google.common.io.Files.createParentDirs(outputFile); final Function<String, String> fingerprintedModuleNameToUri = new Function<String, String>() { @Override public String apply(String moduleName) { String uri = moduleNameToUri.apply(moduleName); String fingerprint = moduleNameToFingerprint.get(moduleName); if (fingerprint != null) { uri = insertFingerprintIntoName(uri, fingerprint); } return uri; } }; Writer writer = Streams.createFileWriter(outputFile, config); appendRootModuleInfo(writer, isDebugMode, fingerprintedModuleNameToUri); Closeables.close(writer, false); } }
/** * This method always calls compiler.toSource(module), which means that it can be followed by a * call to compiler.getSourceMap().appendTo(writer, module), though * compiler.getSourceMap().reset() should be called immediately after when that is the case. * * <p>This method is sychronized in order to fix * http://code.google.com/p/plovr/issues/detail?id=31. The problem is that if two modules are * requested at the same time, it is often the case that compiler.toSource(module) is executing * for the second module while the source map is still being modified for the first module, * causing an IllegalStateException. Empirically, synchronizing this method appears to fix things, * though a more provably correct (and minimal) solution should be sought. */ private synchronized String getCodeForModule( String moduleName, boolean isDebugMode, Function<String, String> moduleNameToUri, boolean resetSourceMap) { Preconditions.checkState(hasResult(), "Code has not been compiled yet"); Preconditions.checkState(modules != null, "This compilation does not use modules"); StringBuilder builder = new StringBuilder(); ModuleConfig moduleConfig = config.getModuleConfig(); String rootModule = moduleConfig.getRootModule(); boolean isRootModule = rootModule.equals(moduleName); if (isRootModule) { // For the root module, prepend the following global variables: // // PLOVR_MODULE_INFO // PLOVR_MODULE_URIS // PLOVR_MODULE_USE_DEBUG_MODE // // Because the standard way to read these variables in the // application is: // // moduleLoader.setDebugMode(!!goog.global['PLOVR_MODULE_USE_DEBUG_MODE']); // moduleManager.setLoader(moduleLoader); // moduleManager.setAllModuleInfo(goog.global['PLOVR_MODULE_INFO']); // moduleManager.setModuleUris(goog.global['PLOVR_MODULE_URIS']); // // It is important that the PLOVR variables are guaranteed to be // global, // which (as much as it pains me) is why "var" is omitted. if (!moduleConfig.excludeModuleInfoFromRootModule()) { try { appendRootModuleInfo(builder, isDebugMode, moduleNameToUri); } catch (IOException e) { // This should not occur because data is being appended to // an // in-memory StringBuilder rather than a file. throw new RuntimeException(e); } } } int lineOffset = 0; JSModule module = nameToModule.get(moduleName); StringBuffer prependBuffer = new StringBuffer(); if (isRootModule) { lineOffset++; // one line for the function wrapper for (File prepend : config.getPrependInputs()) { try { String s = Files.toString(prepend); if (s != null) { String[] lines = s.split("\n"); for (String line : lines) { prependBuffer.append(line); prependBuffer.append("\n"); lineOffset++; } } } catch (IOException e) { e.printStackTrace(); } } } compiler.setPrependedLineOffset(lineOffset); String moduleCode = compiler.toSource(module); boolean hasGlobalScopeName = !Strings.isNullOrEmpty(config.getGlobalScopeName()) && config.getCompilationMode() != CompilationMode.WHITESPACE; // Optionally wrap the module in an anonymous function, with the // requisite wrapper to make it work. if (hasGlobalScopeName) { if (isRootModule) { builder.append(prependBuffer.toString()); // Initialize the global scope in the root module. builder.append(config.getGlobalScopeName()); builder.append("={};"); } builder.append("(function("); builder.append(Config.GLOBAL_SCOPE_NAME); // Including a newline makes the offset into the source map easier to calculate. builder.append("){\n"); } builder.append(moduleCode); if (hasGlobalScopeName) { builder.append("})("); builder.append(config.getGlobalScopeName()); builder.append(");"); } if (resetSourceMap) { SourceMap sourceMap = compiler.getSourceMap(); if (sourceMap != null) sourceMap.reset(); } // http://code.google.com/p/closure-library/issues/detail?id=196 // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/ // non-root modules are loaded with eval, give it a sourceURL for better // debugging if (!isRootModule) { builder.append("\n//@ sourceURL=" + moduleNameToUri.apply(moduleName)); } return builder.toString(); }