public static OptimizerStats exec(JProgram program, OptimizerContext optimizerCtx) { Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME); OptimizerStats stats = new SameParameterValueOptimizer(program).execImpl(program, optimizerCtx); optimizerCtx.incOptimizationStep(); optimizeEvent.end("didChange", "" + stats.didChange()); return stats; }
@Override protected boolean doSlowStartup() { tempWorkDir = options.getWorkDir() == null; if (tempWorkDir) { try { options.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc")); } catch (IOException e) { System.err.println("Unable to create hosted mode work directory"); e.printStackTrace(); return false; } } TreeLogger branch = getTopLogger().branch(TreeLogger.TRACE, "Linking modules"); Event slowStartupEvent = SpeedTracerLogger.start(DevModeEventType.SLOW_STARTUP); try { for (ModuleDef module : startupModules.values()) { TreeLogger loadLogger = branch.branch( TreeLogger.DEBUG, "Bootstrap link for command-line module '" + module.getCanonicalName() + "'"); link(loadLogger, module); } } catch (UnableToCompleteException e) { // Already logged. return false; } finally { slowStartupEvent.end(); } return true; }
public static OptimizerStats exec( JProgram program, boolean noSpecialTypes, OptimizerContext optimizerCtx) { Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME); OptimizerStats stats = new Pruner(program, noSpecialTypes).execImpl(optimizerCtx); optimizeEvent.end("didChange", "" + stats.didChange()); return stats; }
public int getNodeCount() { Event countEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "phase", "countNodes"); TreeStatistics treeStats = new TreeStatistics(); treeStats.accept(this); int numNodes = treeStats.getNodeCount(); countEvent.end(); return numNodes; }
/** * Compiles generated source files (unless cached) and adds them to the CompilationState. If the * compiler aborts, logs an error and throws UnableToCompleteException. */ public Collection<CompilationUnit> addGeneratedTypes( TreeLogger logger, Collection<GeneratedUnit> generatedUnits) throws UnableToCompleteException { Event event = SpeedTracerLogger.start(DevModeEventType.CSB_ADD_GENERATED_TYPES); try { return doBuildGeneratedTypes(logger, compilerContext, generatedUnits, this); } finally { event.end(); } }
@Override protected void optimizeJava() { Event draftOptimizeEvent = SpeedTracerLogger.start(CompilerEventType.DRAFT_OPTIMIZE); Finalizer.exec(jprogram); jprogram.typeOracle.recomputeAfterOptimizations(); // Certain libraries depend on dead stripping. DeadCodeElimination.exec(jprogram); jprogram.typeOracle.recomputeAfterOptimizations(); draftOptimizeEvent.end(); }
/** * Compiles the given set of units. The units will be internally modified to reflect the results * of compilation. */ public static List<CompilationUnit> compile(Collection<CompilationUnitBuilder> builders) { Event jdtCompilerEvent = SpeedTracerLogger.start(CompilerEventType.JDT_COMPILER); try { DefaultUnitProcessor processor = new DefaultUnitProcessor(); JdtCompiler compiler = new JdtCompiler(processor); compiler.doCompile(builders); return processor.getResults(); } finally { jdtCompilerEvent.end(); } }
/** * Compiles the given source files and adds them to the CompilationState. See {@link * CompileMoreLater#compile} for details. * * @throws UnableToCompleteException if the compiler aborts (not a normal compile error). */ public static CompilationState buildFrom( TreeLogger logger, CompilerContext compilerContext, Set<Resource> resources, AdditionalTypeProviderDelegate delegate) throws UnableToCompleteException { Event event = SpeedTracerLogger.start(DevModeEventType.CSB_BUILD_FROM_ORACLE); try { return instance.doBuildFrom(logger, compilerContext, resources, delegate); } finally { event.end(); } }
/* * Create a field serializer for a type if it does not have a custom * serializer. */ private void createFieldSerializer(TreeLogger logger, GeneratorContextExt ctx, JType type) { Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_FIELD_SERIALIZER); try { assert (type != null); assert (serializationOracle.isSerializable(type) || deserializationOracle.isSerializable(type)); JParameterizedType parameterizedType = type.isParameterized(); if (parameterizedType != null) { createFieldSerializer(logger, ctx, parameterizedType.getRawType()); return; } /* * Only a JClassType can reach this point in the code. JPrimitives have been * removed because their serialization is built in, interfaces have been * removed because they are not an instantiable type and parameterized types * have been broken down into their raw types. */ assert (type.isClass() != null || type.isArray() != null); if (findCacheableFieldSerializerAndMarkForReuseIfAvailable(ctx, type)) { // skip generation of field serializer return; } JClassType customFieldSerializer = SerializableTypeOracleBuilder.findCustomFieldSerializer(typeOracle, type); FieldSerializerCreator creator = new FieldSerializerCreator( context, serializationOracle, deserializationOracle, (JClassType) type, customFieldSerializer); creator.realize(logger, ctx); } finally { event.end(); } }
protected void generateTypeHandlers( TreeLogger logger, GeneratorContextExt context, SerializableTypeOracle typesSentFromBrowser, SerializableTypeOracle typesSentToBrowser) throws UnableToCompleteException { Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_TYPE_SERIALIZER); TypeSerializerCreator tsc = new TypeSerializerCreator( logger, typesSentFromBrowser, typesSentToBrowser, context, SerializationUtils.getTypeSerializerQualifiedName(serviceIntf), SerializationUtils.getTypeSerializerSimpleName(serviceIntf)); tsc.realize(logger); event.end(); typeStrings = new HashMap<JType, String>(tsc.getTypeStrings()); typeStrings.put(serviceIntf, TypeNameObfuscator.SERVICE_INTERFACE_ID); cachedTypeLastModifiedTimes = tsc.getTypeLastModifiedTimeMap(); }
public boolean run(TreeLogger logger, ModuleDef... modules) throws UnableToCompleteException { boolean tempWorkDir = false; try { if (options.getWorkDir() == null) { options.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc")); tempWorkDir = true; } if (options.isSoycEnabled() && options.getExtraDir() == null) { options.setExtraDir(new File("extras")); } File persistentUnitCacheDir = null; if (options.getWarDir() != null && !options.getWarDir().getName().endsWith(".jar")) { persistentUnitCacheDir = new File(options.getWarDir(), "../"); } CompilationStateBuilder.init(logger, persistentUnitCacheDir); for (ModuleDef module : modules) { String moduleName = module.getCanonicalName(); if (options.isValidateOnly()) { if (!Precompile.validate(logger, options, module, options.getGenDir())) { return false; } } else { long compileStart = System.currentTimeMillis(); TreeLogger branch = logger.branch(TreeLogger.INFO, "Compiling module " + moduleName); // Optimize early since permutation compiles will run in process. options.setOptimizePrecompile(true); Precompilation precompilation = Precompile.precompile(branch, options, module, options.getGenDir()); if (precompilation == null) { return false; } Event compilePermutationsEvent = SpeedTracerLogger.start(CompilerEventType.COMPILE_PERMUTATIONS); Permutation[] allPerms = precompilation.getPermutations(); List<FileBackedObject<PermutationResult>> resultFiles = CompilePerms.makeResultFiles(options.getCompilerWorkDir(moduleName), allPerms); CompilePerms.compile( branch, precompilation, allPerms, options.getLocalWorkers(), resultFiles); compilePermutationsEvent.end(); ArtifactSet generatedArtifacts = precompilation.getGeneratedArtifacts(); JJSOptions precompileOptions = precompilation.getUnifiedAst().getOptions(); precompilation = null; // No longer needed, so save the memory Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK); File absPath = new File(options.getWarDir(), module.getName()); absPath = absPath.getAbsoluteFile(); String logMessage = "Linking into " + absPath; if (options.getExtraDir() != null) { File absExtrasPath = new File(options.getExtraDir(), module.getName()); absExtrasPath = absExtrasPath.getAbsoluteFile(); logMessage += "; Writing extras to " + absExtrasPath; } Link.link( logger.branch(TreeLogger.TRACE, logMessage), module, generatedArtifacts, allPerms, resultFiles, options.getWarDir(), options.getDeployDir(), options.getExtraDir(), precompileOptions); linkEvent.end(); long compileDone = System.currentTimeMillis(); long delta = compileDone - compileStart; if (branch.isLoggable(TreeLogger.INFO)) { branch.log( TreeLogger.INFO, "Compilation succeeded -- " + String.format("%.3f", delta / 1000d) + "s"); } } } } catch (IOException e) { logger.log(TreeLogger.ERROR, "Unable to create compiler work directory", e); return false; } finally { if (tempWorkDir) { Util.recursiveDelete(options.getWorkDir(), false); } } return true; }
/** * Creates the client-side proxy class. * * @throws UnableToCompleteException */ public String create(TreeLogger logger, GeneratorContextExt context) throws UnableToCompleteException { TypeOracle typeOracle = context.getTypeOracle(); JClassType serviceAsync = typeOracle.findType(serviceIntf.getQualifiedSourceName() + "Async"); if (serviceAsync == null) { logger.branch( TreeLogger.ERROR, "Could not find an asynchronous version for the service interface " + serviceIntf.getQualifiedSourceName(), null); RemoteServiceAsyncValidator.logValidAsyncInterfaceDeclaration(logger, serviceIntf); throw new UnableToCompleteException(); } SourceWriter srcWriter = getSourceWriter(logger, context, serviceAsync); if (srcWriter == null) { return getProxyQualifiedName(); } // Make sure that the async and synchronous versions of the RemoteService // agree with one another // RemoteServiceAsyncValidator rsav = new RemoteServiceAsyncValidator(logger, typeOracle); Map<JMethod, JMethod> syncMethToAsyncMethMap = rsav.validate(logger, serviceIntf, serviceAsync); final PropertyOracle propertyOracle = context.getPropertyOracle(); // Load the blacklist/whitelist TypeFilter blacklistTypeFilter = new BlacklistTypeFilter(logger, propertyOracle); // Determine the set of serializable types Event event = SpeedTracerLogger.start(CompilerEventType.GENERATOR_RPC_STOB); SerializableTypeOracleBuilder typesSentFromBrowserBuilder = new SerializableTypeOracleBuilder(logger, propertyOracle, context); typesSentFromBrowserBuilder.setTypeFilter(blacklistTypeFilter); SerializableTypeOracleBuilder typesSentToBrowserBuilder = new SerializableTypeOracleBuilder(logger, propertyOracle, context); typesSentToBrowserBuilder.setTypeFilter(blacklistTypeFilter); addRoots(logger, typeOracle, typesSentFromBrowserBuilder, typesSentToBrowserBuilder); try { ConfigurationProperty prop = context .getPropertyOracle() .getConfigurationProperty(TypeSerializerCreator.GWT_ELIDE_TYPE_NAMES_FROM_RPC); elideTypeNames = Boolean.parseBoolean(prop.getValues().get(0)); } catch (BadPropertyValueException e) { logger.log( TreeLogger.ERROR, "Configuration property " + TypeSerializerCreator.GWT_ELIDE_TYPE_NAMES_FROM_RPC + " is not defined. Is RemoteService.gwt.xml inherited?"); throw new UnableToCompleteException(); } // Decide what types to send in each direction. // Log the decisions to a string that will be written later in this method SerializableTypeOracle typesSentFromBrowser; SerializableTypeOracle typesSentToBrowser; String rpcLog; { StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); typesSentFromBrowserBuilder.setLogOutputWriter(writer); typesSentToBrowserBuilder.setLogOutputWriter(writer); writer.write("====================================\n"); writer.write("Types potentially sent from browser:\n"); writer.write("====================================\n\n"); writer.flush(); typesSentFromBrowser = typesSentFromBrowserBuilder.build(logger); writer.write("===================================\n"); writer.write("Types potentially sent from server:\n"); writer.write("===================================\n\n"); writer.flush(); typesSentToBrowser = typesSentToBrowserBuilder.build(logger); writer.close(); rpcLog = stringWriter.toString(); } event.end(); generateTypeHandlers(logger, context, typesSentFromBrowser, typesSentToBrowser); String serializationPolicyStrongName = writeSerializationPolicyFile(logger, context, typesSentFromBrowser, typesSentToBrowser); String remoteServiceInterfaceName = elideTypeNames ? TypeNameObfuscator.SERVICE_INTERFACE_ID : SerializationUtils.getRpcTypeName(serviceIntf); generateProxyFields( srcWriter, typesSentFromBrowser, serializationPolicyStrongName, remoteServiceInterfaceName); generateProxyContructor(srcWriter); generateProxyMethods(srcWriter, typesSentFromBrowser, typeOracle, syncMethToAsyncMethMap); generateStreamWriterOverride(srcWriter); generateCheckRpcTokenTypeOverride(srcWriter, typeOracle, typesSentFromBrowser); srcWriter.commit(logger); if (context.isProdMode() || logger.isLoggable(TreeLogger.DEBUG)) { // Create an artifact explaining STOB's decisions. It will be emitted by // RpcLogLinker context.commitArtifact( logger, new RpcLogArtifact( serviceIntf.getQualifiedSourceName(), serializationPolicyStrongName, rpcLog)); } return getProxyQualifiedName(); }
/** * A callback after the JDT compiler has compiled a .java file and created a matching * CompilationUnitDeclaration. We take this opportunity to create a matching CompilationUnit. */ @Override public void process( CompilationUnitBuilder builder, CompilationUnitDeclaration cud, List<CompiledClass> compiledClasses) { Event event = SpeedTracerLogger.start(DevModeEventType.CSB_PROCESS); try { Map<MethodDeclaration, JsniMethod> jsniMethods = JsniCollector.collectJsniMethods( cud, builder.getSourceMapPath(), builder.getSource(), JsRootScope.INSTANCE, DummyCorrelationFactory.INSTANCE); JSORestrictionsChecker.check(jsoState, cud); // JSNI check + collect dependencies. final Set<String> jsniDeps = new HashSet<String>(); Map<String, Binding> jsniRefs = new HashMap<String, Binding>(); JsniChecker.check( cud, jsoState, jsniMethods, jsniRefs, new JsniChecker.TypeResolver() { @Override public ReferenceBinding resolveType(String sourceOrBinaryName) { ReferenceBinding resolveType = compiler.resolveType(sourceOrBinaryName); if (resolveType != null) { jsniDeps.add(String.valueOf(resolveType.qualifiedSourceName())); } return resolveType; } }); Map<TypeDeclaration, Binding[]> artificialRescues = new HashMap<TypeDeclaration, Binding[]>(); ArtificialRescueChecker.check(cud, builder.isGenerated(), artificialRescues); if (compilerContext.shouldCompileMonolithic()) { // GWT drives JDT in a way that allows missing references in the source to be resolved // to precompiled bytecode on disk (see INameEnvironment). This is done so that // annotations can be supplied in bytecode form only. But since no AST is available for // these types it creates the danger that some functional class (not just an annotation) // gets filled in but is missing AST. This would cause later compiler stages to fail. // // Library compilation needs to ignore this check since it is expected behavior for the // source being compiled in a library to make references to other types which are only // available as bytecode coming out of dependency libraries. // // But if the referenced bytecode did not come from a dependency library but instead was // free floating in the classpath, then there is no guarrantee that AST for it was ever // seen and translated to JS anywhere in the dependency tree. This would be a mistake. // // TODO(stalcup): add a more specific check for library compiles such that binary types // can be referenced but only if they are an Annotation or if the binary type comes from // a dependency library. BinaryTypeReferenceRestrictionsChecker.check(cud); } MethodArgNamesLookup methodArgs = MethodParamCollector.collect(cud, builder.getSourceMapPath()); Interner<String> interner = StringInterner.get(); String packageName = interner.intern(Shared.getPackageName(builder.getTypeName())); List<String> unresolvedQualified = new ArrayList<String>(); List<String> unresolvedSimple = new ArrayList<String>(); for (char[] simpleRef : cud.compilationResult().simpleNameReferences) { unresolvedSimple.add(interner.intern(String.valueOf(simpleRef))); } for (char[][] qualifiedRef : cud.compilationResult().qualifiedReferences) { unresolvedQualified.add(interner.intern(CharOperation.toString(qualifiedRef))); } for (String jsniDep : jsniDeps) { unresolvedQualified.add(interner.intern(jsniDep)); } ArrayList<String> apiRefs = compiler.collectApiRefs(cud); for (int i = 0; i < apiRefs.size(); ++i) { apiRefs.set(i, interner.intern(apiRefs.get(i))); } Dependencies dependencies = new Dependencies(packageName, unresolvedQualified, unresolvedSimple, apiRefs); List<JDeclaredType> types = Collections.emptyList(); if (!cud.compilationResult().hasErrors()) { // Make a GWT AST. types = astBuilder.process( cud, builder.getSourceMapPath(), artificialRescues, jsniMethods, jsniRefs); } for (CompiledClass cc : compiledClasses) { allValidClasses.put(cc.getSourceName(), cc); } builder .setClasses(compiledClasses) .setTypes(types) .setDependencies(dependencies) .setJsniMethods(jsniMethods.values()) .setMethodArgs(methodArgs) .setProblems(cud.compilationResult().getProblems()); buildQueue.add(builder); } finally { event.end(); } }
/** * Compiles the source code in each supplied CompilationUnitBuilder into a CompilationUnit and * reports errors. * * <p>A compilation unit is considered invalid if any of its dependencies (recursively) isn't * being compiled and isn't in allValidClasses, or if it has a signature that doesn't match a * dependency. Valid compilation units will be added to cachedUnits and the unit cache, and * their types will be added to allValidClasses. Invalid compilation units will be removed. * * <p>I/O: serializes the AST of each Java type to DiskCache. (This happens even if the * compilation unit is later dropped.) If we're using the persistent unit cache, each valid unit * will also be serialized to the gwt-unitcache file. (As a result, each AST will be copied * there from the DiskCache.) A new persistent unit cache file will be created each time * compile() is called (if there's at least one valid unit) and the entire cache will be * rewritten to disk every {@link PersistentUnitCache#CACHE_FILE_THRESHOLD} files. * * <p>This function won't report errors in invalid source files unless suppressErrors is false. * Instead, a summary giving the number of invalid files will be logged. * * <p>If the JDT compiler aborts, logs an error and throws UnableToCompleteException. (This * doesn't happen for normal compile errors.) */ Collection<CompilationUnit> compile( TreeLogger logger, CompilerContext compilerContext, Collection<CompilationUnitBuilder> builders, Map<CompilationUnitBuilder, CompilationUnit> cachedUnits, EventType eventType) throws UnableToCompleteException { UnitCache unitCache = compilerContext.getUnitCache(); // Initialize the set of valid classes to the initially cached units. for (CompilationUnit unit : cachedUnits.values()) { for (CompiledClass cc : unit.getCompiledClasses()) { // Map by source name. String sourceName = cc.getSourceName(); allValidClasses.put(sourceName, cc); } } ArrayList<CompilationUnit> resultUnits = new ArrayList<CompilationUnit>(); do { final TreeLogger branch = logger.branch(TreeLogger.TRACE, "Compiling..."); // Compile anything that needs to be compiled. buildQueue = new LinkedBlockingQueue<CompilationUnitBuilder>(); final ArrayList<CompilationUnit> newlyBuiltUnits = new ArrayList<CompilationUnit>(); final CompilationUnitBuilder sentinel = CompilationUnitBuilder.create((GeneratedUnit) null); final Throwable[] workerException = new Throwable[1]; final ProgressLogger progressLogger = new ProgressLogger(branch, TreeLogger.TRACE, builders.size(), 10); Thread buildThread = new Thread() { @Override public void run() { int processedCompilationUnitBuilders = 0; try { do { CompilationUnitBuilder builder = buildQueue.take(); if (!progressLogger.isTimerStarted()) { // Set start time here, after first job has arrived, since it can take a // little // while for the first job to arrive, and this helps with the accuracy of the // estimated times. progressLogger.startTimer(); } if (builder == sentinel) { return; } // Expensive, must serialize GWT AST types to bytes. CompilationUnit unit = builder.build(); newlyBuiltUnits.add(unit); processedCompilationUnitBuilders++; progressLogger.updateProgress(processedCompilationUnitBuilders); } while (true); } catch (Throwable e) { workerException[0] = e; } } }; buildThread.setName("CompilationUnitBuilder"); buildThread.start(); Event jdtCompilerEvent = SpeedTracerLogger.start(eventType); long compilationStartNanos = System.nanoTime(); try { compiler.doCompile(branch, builders); } finally { jdtCompilerEvent.end(); } buildQueue.add(sentinel); try { buildThread.join(); long compilationNanos = System.nanoTime() - compilationStartNanos; // Convert nanos to seconds. double compilationSeconds = compilationNanos / (double) TimeUnit.SECONDS.toNanos(1); branch.log( TreeLogger.TRACE, String.format("Compilation completed in %.02f seconds", compilationSeconds)); if (workerException[0] != null) { throw workerException[0]; } } catch (RuntimeException e) { throw e; } catch (Throwable e) { throw new RuntimeException("Exception processing units", e); } finally { buildQueue = null; } resultUnits.addAll(newlyBuiltUnits); builders.clear(); // Resolve all newly built unit deps against the global classes. for (CompilationUnit unit : newlyBuiltUnits) { unit.getDependencies().resolve(allValidClasses); } /* * Invalidate any cached units with invalid refs. */ Collection<CompilationUnit> invalidatedUnits = new ArrayList<CompilationUnit>(); for (Iterator<Entry<CompilationUnitBuilder, CompilationUnit>> it = cachedUnits.entrySet().iterator(); it.hasNext(); ) { Entry<CompilationUnitBuilder, CompilationUnit> entry = it.next(); CompilationUnit unit = entry.getValue(); boolean isValid = unit.getDependencies().validate(logger, allValidClasses); if (isValid && unit.isError()) { // See if the unit has classes that can't provide a // NameEnvironmentAnswer for (CompiledClass cc : unit.getCompiledClasses()) { try { cc.getNameEnvironmentAnswer(); } catch (ClassFormatException ex) { isValid = false; break; } } } if (!isValid) { if (logger.isLoggable(TreeLogger.TRACE)) { logger.log(TreeLogger.TRACE, "Invalid Unit: " + unit.getTypeName()); } invalidatedUnits.add(unit); builders.add(entry.getKey()); it.remove(); } } if (invalidatedUnits.size() > 0) { if (logger.isLoggable(TreeLogger.TRACE)) { logger.log(TreeLogger.TRACE, "Invalid units found: " + invalidatedUnits.size()); } } // Any units we invalidated must now be removed from the valid classes. for (CompilationUnit unit : invalidatedUnits) { for (CompiledClass cc : unit.getCompiledClasses()) { allValidClasses.remove(cc.getSourceName()); } } } while (builders.size() > 0); for (CompilationUnit unit : resultUnits) { unitCache.add(unit); } // Any remaining cached units are valid now. resultUnits.addAll(cachedUnits.values()); // Done with a pass of the build - tell the cache its OK to cleanup // stale cache files. unitCache.cleanup(logger); // Sort, then report all errors (re-report for cached units). Collections.sort(resultUnits, CompilationUnit.COMPARATOR); logger = logger.branch(TreeLogger.DEBUG, "Validating units:"); int errorCount = 0; for (CompilationUnit unit : resultUnits) { if (CompilationProblemReporter.reportErrors(logger, unit, suppressErrors)) { errorCount++; } } if (suppressErrors && errorCount > 0 && !logger.isLoggable(TreeLogger.TRACE) && logger.isLoggable(TreeLogger.INFO)) { logger.log( TreeLogger.INFO, "Ignored " + errorCount + " unit" + (errorCount > 1 ? "s" : "") + " with compilation errors in first pass.\n" + "Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors."); } return resultUnits; }
public static OptimizerStats exec(JProgram program) { Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "optimizer", NAME); OptimizerStats stats = new MethodInliner(program).execImpl(); optimizeEvent.end("didChange", "" + stats.didChange()); return stats; }
@Override protected int doStartUpServer() { // Create the war directory if it doesn't exist File warDir = options.getWarDir(); if (!warDir.exists() && !warDir.mkdirs()) { getTopLogger().log(TreeLogger.ERROR, "Unable to create war directory " + warDir); return -1; } Event jettyStartupEvent = SpeedTracerLogger.start(DevModeEventType.JETTY_STARTUP); boolean clearCallback = true; try { ui.setCallback(RestartServerEvent.getType(), this); ServletContainerLauncher scl = options.getServletContainerLauncher(); TreeLogger serverLogger = ui.getWebServerLogger(getWebServerName(), scl.getIconBytes()); String sclArgs = options.getServletContainerLauncherArgs(); if (sclArgs != null) { if (!scl.processArguments(serverLogger, sclArgs)) { return -1; } } isHttps = scl.isSecure(); // Tell the UI if the web server is secure if (isHttps) { ui.setWebServerSecure(serverLogger); } /* * TODO: This is a hack to pass the base log level to the SCL. We'll have * to figure out a better way to do this for SCLs in general. */ if (scl instanceof JettyLauncher) { JettyLauncher jetty = (JettyLauncher) scl; jetty.setBaseRequestLogLevel(getBaseLogLevelForUI()); } scl.setBindAddress(bindAddress); if (serverLogger.isLoggable(TreeLogger.TRACE)) { serverLogger.log(TreeLogger.TRACE, "Starting HTTP on port " + getPort(), null); } server = scl.start(serverLogger, getPort(), options.getWarDir()); assert (server != null); clearCallback = false; return server.getPort(); } catch (BindException e) { System.err.println( "Port " + bindAddress + ':' + getPort() + " is already is use; you probably still have another session active"); } catch (Exception e) { System.err.println("Unable to start embedded HTTP server"); e.printStackTrace(); } finally { jettyStartupEvent.end(); if (clearCallback) { // Clear the callback if we failed to start the server ui.setCallback(RestartServerEvent.getType(), null); } } return -1; }