blob: e174f682314d80f200e1af2537b6bfb19640b39a [file] [log] [blame]
/*
* 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.
*/
package com.google.gwt.dev.codeserver;
import com.google.gwt.dev.ArgProcessorBase;
import com.google.gwt.dev.util.arg.ArgHandlerSourceLevel;
import com.google.gwt.dev.util.arg.OptionSourceLevel;
import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.util.tools.ArgHandler;
import com.google.gwt.util.tools.ArgHandlerDir;
import com.google.gwt.util.tools.ArgHandlerExtra;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerInt;
import com.google.gwt.util.tools.ArgHandlerString;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
/**
* Defines the command-line options for the {@link CodeServer CodeServer's} main() method.
*
* <p>These flags are EXPERIMENTAL and subject to change.</p>
*/
public class Options {
private boolean noPrecompile = false;
private boolean isCompileTest = false;
private File workDir;
private List<String> moduleNames = new ArrayList<String>();
private boolean allowMissingSourceDir = false;
private final List<File> sourcePath = new ArrayList<File>();
private String bindAddress = "127.0.0.1";
private String preferredHost = "localhost";
private int port = 9876;
private RecompileListener recompileListener = RecompileListener.NONE;
// Use the same default as the GWT compiler.
private SourceLevel sourceLevel = SourceLevel.DEFAULT_SOURCE_LEVEL;
private boolean strictResources = false;
/**
* Sets each option to the appropriate value, based on command-line arguments.
* If there is an error, prints error messages and/or usage to System.err.
* @return true if the arguments were parsed successfully.
*/
public boolean parseArgs(String[] args) {
boolean ok = new ArgProcessor().processArgs(args);
if (!ok) {
return false;
}
if (isCompileTest && noPrecompile) {
System.err.println("Usage: -noprecompile and -compiletest are incompatible");
return false;
}
if (moduleNames.isEmpty()) {
System.err.println("Usage: at least one module must be supplied");
return false;
}
return true;
}
/**
* A Java application that embeds Super Dev Mode can use this hook to find out
* when compiles start and end.
*/
public void setRecompileListener(RecompileListener recompileListener) {
this.recompileListener = recompileListener;
}
RecompileListener getRecompileListener() {
return recompileListener;
}
/**
* The top level of the directory tree where the code server keeps compiler output.
*/
File getWorkDir() {
return workDir;
}
/**
* The names of the module that will be compiled (along with all its dependencies).
*/
List<String> getModuleNames() {
return moduleNames;
}
/**
* Whether the codeServer should allow missing source directories.
*/
boolean shouldAllowMissingSourceDir() {
return allowMissingSourceDir;
}
/**
* Whether the codeServer should start without precompiling modules.
*/
boolean getNoPrecompile() {
return noPrecompile;
}
/**
* Java source level compatibility,
*/
SourceLevel getSourceLevel() {
return sourceLevel;
}
/**
* If true, just compile the modules, then exit.
*/
boolean isCompileTest() {
return isCompileTest;
}
/**
* The IP address where the code server should listen.
*/
String getBindAddress() {
return bindAddress;
}
/**
* The hostname to put in a URL pointing to the code server.
*/
String getPreferredHost() {
return preferredHost;
}
/**
* The port where the code server will listen for HTTP requests.
*/
int getPort() {
return port;
}
/**
* Whether to implicitly import client and public directories when no explicit imports exist.
*/
boolean enforceStrictResources() {
return strictResources;
}
List<File> getSourcePath() {
return sourcePath;
}
private class ArgProcessor extends ArgProcessorBase {
public ArgProcessor() {
registerHandler(new NoPrecompileFlag());
registerHandler(new CompileTestFlag());
registerHandler(new BindAddressFlag());
registerHandler(new PortFlag());
registerHandler(new WorkDirFlag());
registerHandler(new AllowMissingSourceDirFlag());
registerHandler(new SourceFlag());
registerHandler(new ModuleNameArgument());
registerHandler(new StrictResourcesFlag());
registerHandler(new ArgHandlerSourceLevel(new OptionSourceLevel() {
@Override
public SourceLevel getSourceLevel() {
return sourceLevel;
}
@Override
public void setSourceLevel(SourceLevel sourceLevel) {
Options.this.sourceLevel = sourceLevel;
}
}));
}
@Override
protected String getName() {
return CodeServer.class.getName();
}
}
private class NoPrecompileFlag extends ArgHandlerFlag {
@Override
public String getLabel() {
return "precompile";
}
@Override
public String getPurposeSnippet() {
return "Precompile modules.";
}
@Override
public boolean setFlag(boolean value) {
noPrecompile = !value;
return true;
}
@Override
public boolean getDefaultValue() {
return !noPrecompile;
}
}
private class CompileTestFlag extends ArgHandlerFlag {
@Override
public String getLabel() {
return "compileTest";
}
@Override
public String getPurposeSnippet() {
return "Exits after compiling the modules. The exit code will be 0 if the compile succeeded.";
}
@Override
public boolean setFlag(boolean value) {
isCompileTest = value;
return true;
}
@Override
public boolean getDefaultValue() {
return isCompileTest;
}
}
private class BindAddressFlag extends ArgHandlerString {
@Override
public String getTag() {
return "-bindAddress";
}
@Override
public String[] getTagArgs() {
return new String[] {"address"};
}
@Override
public String getPurpose() {
return "The ip address of the code server. Defaults to 127.0.0.1.";
}
@Override
public boolean setString(String newValue) {
try {
InetAddress bindAddress = InetAddress.getByName(newValue);
if (bindAddress.isAnyLocalAddress()) {
preferredHost = InetAddress.getLocalHost().getHostName();
} else {
preferredHost = newValue;
}
} catch (UnknownHostException e) {
System.err.println("Can't resolve bind address: " + newValue);
return false;
}
// Save the original since there's no way to get it back from an InetAddress.
bindAddress = newValue;
return true;
}
}
private class PortFlag extends ArgHandlerInt {
@Override
public String getTag() {
return "-port";
}
@Override
public String[] getTagArgs() {
return new String[] {"port"};
}
@Override
public String getPurpose() {
return "The port where the code server will run.";
}
@Override
public void setInt(int newValue) {
port = newValue;
}
}
private class WorkDirFlag extends ArgHandlerDir {
@Override
public String getTag() {
return "-workDir";
}
@Override
public String getPurpose() {
return "The root of the directory tree where the code server will"
+ "write compiler output. If not supplied, a temporary directory"
+ "will be used.";
}
@Override
public void setDir(File newValue) {
workDir = newValue;
}
}
private class StrictResourcesFlag extends ArgHandlerFlag {
public StrictResourcesFlag() {
addTagValue("-XstrictResources", true);
}
@Override
public boolean isExperimental() {
return true;
}
@Override
public String getLabel() {
return "enforceStrictResources";
}
@Override
public String getPurposeSnippet() {
return "Avoid adding implicit dependencies on \"client\" and \"public\" for "
+ "modules that don't define any dependencies.";
}
@Override
public boolean setFlag(boolean value) {
strictResources = value;
return true;
}
@Override
public boolean getDefaultValue() {
return false;
}
}
private class AllowMissingSourceDirFlag extends ArgHandlerFlag {
@Override
public String getLabel() {
return "allowMissingSrc";
}
@Override
public String getPurposeSnippet() {
return "Allows -src flags to reference missing directories.";
}
@Override
public boolean setFlag(boolean value) {
allowMissingSourceDir = value;
return true;
}
@Override
public boolean getDefaultValue() {
return allowMissingSourceDir;
}
}
private class SourceFlag extends ArgHandler {
@Override
public String getTag() {
return "-src";
}
@Override
public String[] getTagArgs() {
return new String[]{"dir"};
}
@Override
public String getPurpose() {
return "A directory containing GWT source to be prepended to the classpath for compiling.";
}
@Override
public int handle(String[] args, int startIndex) {
if (startIndex + 1 >= args.length) {
System.err.println(getTag() + " should be followed by the name of a directory");
return -1;
}
File candidate = new File(args[startIndex + 1]);
if (!allowMissingSourceDir && !candidate.isDirectory()) {
System.err.println("not a directory: " + candidate);
return -1;
}
sourcePath.add(candidate);
return 1;
}
}
private class ModuleNameArgument extends ArgHandlerExtra {
@Override
public String[] getTagArgs() {
return new String[] {"module"};
}
@Override
public String getPurpose() {
return "The GWT modules that the code server should compile. (Example: com.example.MyApp)";
}
@Override
public boolean addExtraArg(String arg) {
moduleNames.add(arg);
return true;
}
}
}