8035063: Option handling in sjavac needs to be rewritten

Option handling code rewritten. Exclusion / inclusion patterns changed from package to directories.

Reviewed-by: jjg, jfranck
This commit is contained in:
Andreas Lundblad 2014-04-22 16:51:10 +02:00
parent a50db59b59
commit 06f651942c
28 changed files with 2427 additions and 907 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -29,13 +29,14 @@ import java.io.*;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import com.sun.tools.sjavac.options.Options;
/** /**
* The clean properties transform should not be necessary. * The clean properties transform should not be necessary.
* Eventually we will cleanup the property file sources in the OpenJDK instead. * Eventually we will cleanup the property file sources in the OpenJDK instead.
@ -51,7 +52,7 @@ public class CleanProperties implements Transformer
// Any extra information is ignored for clean properties. // Any extra information is ignored for clean properties.
} }
public void setExtra(String[] a) { public void setExtra(Options a) {
// Any extra information is ignored for clean properties. // Any extra information is ignored for clean properties.
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,15 +25,16 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.PrintStream;
import java.net.URI; import java.net.URI;
import java.util.Arrays; import java.util.Arrays;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Map; import java.util.Map;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.server.JavacServer; import com.sun.tools.sjavac.server.JavacServer;
import com.sun.tools.sjavac.server.SysInfo; import com.sun.tools.sjavac.server.SysInfo;
import java.io.PrintStream;
/** /**
* This transform compiles a set of packages containing Java sources. * This transform compiles a set of packages containing Java sources.
@ -54,13 +55,12 @@ public class CompileJavaPackages implements Transformer {
// We hope to improve this in the future. // We hope to improve this in the future.
final static int limitOnConcurrency = 3; final static int limitOnConcurrency = 3;
String serverSettings; Options args;
public void setExtra(String e) { public void setExtra(String e) {
serverSettings = e;
} }
String[] args; public void setExtra(Options a) {
public void setExtra(String[] a) {
args = a; args = a;
} }
@ -82,14 +82,14 @@ public class CompileJavaPackages implements Transformer {
boolean concurrentCompiles = true; boolean concurrentCompiles = true;
// Fetch the id. // Fetch the id.
String id = Util.extractStringOption("id", serverSettings); String id = Util.extractStringOption("id", args.getServerConf());
if (id == null || id.equals("")) { if (id == null || id.equals("")) {
// No explicit id set. Create a random id so that the requests can be // No explicit id set. Create a random id so that the requests can be
// grouped properly in the server. // grouped properly in the server.
id = "id"+(((new Random()).nextLong())&Long.MAX_VALUE); id = "id"+(((new Random()).nextLong())&Long.MAX_VALUE);
} }
// Only keep portfile and sjavac settings.. // Only keep portfile and sjavac settings..
String psServerSettings = Util.cleanSubOptions("--server:", Util.set("portfile","sjavac","background","keepalive"), serverSettings); String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), args.getServerConf());
// Get maximum heap size from the server! // Get maximum heap size from the server!
SysInfo sysinfo = JavacServer.connectGetSysInfo(psServerSettings, out, err); SysInfo sysinfo = JavacServer.connectGetSysInfo(psServerSettings, out, err);
@ -223,7 +223,7 @@ public class CompileJavaPackages implements Transformer {
@Override @Override
public void run() { public void run() {
rn[ii] = JavacServer.useServer(cleanedServerSettings, rn[ii] = JavacServer.useServer(cleanedServerSettings,
Main.removeWrapperArgs(args), args.prepJavacArgs(),
cc.srcs, cc.srcs,
fvisible_sources, fvisible_sources,
fvisible_classes, fvisible_classes,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,8 @@ import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import com.sun.tools.sjavac.options.Options;
/** /**
* Compile properties transform a properties file into a Java source file. * Compile properties transform a properties file into a Java source file.
* Java has built in support for reading properties from either a text file * Java has built in support for reading properties from either a text file
@ -58,7 +60,7 @@ public class CompileProperties implements Transformer
extra = e; extra = e;
} }
public void setExtra(String[] a) { public void setExtra(Options a) {
} }
public boolean transform(Map<String,Set<URI>> pkgSrcs, public boolean transform(Map<String,Set<URI>> pkgSrcs,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,8 @@ import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import com.sun.tools.sjavac.options.Options;
/** /**
* The copy file transform simply copies a matching file from -src to -d . * The copy file transform simply copies a matching file from -src to -d .
* Such files are typically images, xml documents and other data files. * Such files are typically images, xml documents and other data files.
@ -45,7 +47,7 @@ public class CopyFile implements Transformer {
public void setExtra(String e) { public void setExtra(String e) {
} }
public void setExtra(String[] a) { public void setExtra(Options a) {
} }
public boolean transform(Map<String,Set<URI>> pkgSrcs, public boolean transform(Map<String,Set<URI>> pkgSrcs,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.*; import java.io.*;
import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;
@ -37,6 +38,9 @@ import java.text.SimpleDateFormat;
import java.net.URI; import java.net.URI;
import java.util.*; import java.util.*;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation;
/** /**
* The javac state class maintains the previous (prev) and the current (now) * The javac state class maintains the previous (prev) and the current (now)
* build states and everything else that goes into the javac_state file. * build states and everything else that goes into the javac_state file.
@ -117,25 +121,20 @@ public class JavacState
// It can also map from a jar file to the set of visible classes for that jar file. // It can also map from a jar file to the set of visible classes for that jar file.
Map<URI,Set<String>> visibleClasses; Map<URI,Set<String>> visibleClasses;
// Setup two transforms that always exist. // Setup transform that always exist.
private CopyFile copyFiles = new CopyFile();
private CompileJavaPackages compileJavaPackages = new CompileJavaPackages(); private CompileJavaPackages compileJavaPackages = new CompileJavaPackages();
// Where to send stdout and stderr. // Where to send stdout and stderr.
private PrintStream out, err; private PrintStream out, err;
JavacState(String[] args, File bd, File gd, File hd, boolean permitUnidentifiedArtifacts, boolean removeJavacState, JavacState(Options options, boolean removeJavacState, PrintStream o, PrintStream e) {
PrintStream o, PrintStream e) {
out = o; out = o;
err = e; err = e;
numCores = Main.findNumberOption(args, "-j"); numCores = options.getNumCores();
theArgs = ""; theArgs = options.getStateArgsString();
for (String a : removeArgsNotAffectingState(args)) { binDir = Util.pathToFile(options.getDestDir());
theArgs = theArgs+a+" "; gensrcDir = Util.pathToFile(options.getGenSrcDir());
} headerDir = Util.pathToFile(options.getHeaderDir());
binDir = bd;
gensrcDir = gd;
headerDir = hd;
javacStateFilename = binDir.getPath()+File.separator+"javac_state"; javacStateFilename = binDir.getPath()+File.separator+"javac_state";
javacState = new File(javacStateFilename); javacState = new File(javacStateFilename);
if (removeJavacState && javacState.exists()) { if (removeJavacState && javacState.exists()) {
@ -148,7 +147,7 @@ public class JavacState
// We do not want to risk building a broken incremental build. // We do not want to risk building a broken incremental build.
// BUT since the makefiles still copy things straight into the bin_dir et al, // BUT since the makefiles still copy things straight into the bin_dir et al,
// we avoid deleting files here, if the option --permit-unidentified-classes was supplied. // we avoid deleting files here, if the option --permit-unidentified-classes was supplied.
if (!permitUnidentifiedArtifacts) { if (!options.isUnidentifiedArtifactPermitted()) {
deleteContents(binDir); deleteContents(binDir);
deleteContents(gensrcDir); deleteContents(gensrcDir);
deleteContents(headerDir); deleteContents(headerDir);
@ -301,9 +300,8 @@ public class JavacState
/** /**
* Load a javac_state file. * Load a javac_state file.
*/ */
public static JavacState load(String[] args, File binDir, File gensrcDir, File headerDir, public static JavacState load(Options options, PrintStream out, PrintStream err) {
boolean permitUnidentifiedArtifacts, PrintStream out, PrintStream err) { JavacState db = new JavacState(options, false, out, err);
JavacState db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, false, out, err);
Module lastModule = null; Module lastModule = null;
Package lastPackage = null; Package lastPackage = null;
Source lastSource = null; Source lastSource = null;
@ -370,22 +368,22 @@ public class JavacState
noFileFound = true; noFileFound = true;
} catch (IOException e) { } catch (IOException e) {
Log.info("Dropping old javac_state because of errors when reading it."); Log.info("Dropping old javac_state because of errors when reading it.");
db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); db = new JavacState(options, true, out, err);
foundCorrectVerNr = true; foundCorrectVerNr = true;
newCommandLine = false; newCommandLine = false;
syntaxError = false; syntaxError = false;
} }
if (foundCorrectVerNr == false && !noFileFound) { if (foundCorrectVerNr == false && !noFileFound) {
Log.info("Dropping old javac_state since it is of an old version."); Log.info("Dropping old javac_state since it is of an old version.");
db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); db = new JavacState(options, true, out, err);
} else } else
if (newCommandLine == true && !noFileFound) { if (newCommandLine == true && !noFileFound) {
Log.info("Dropping old javac_state since a new command line is used!"); Log.info("Dropping old javac_state since a new command line is used!");
db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); db = new JavacState(options, true, out, err);
} else } else
if (syntaxError == true) { if (syntaxError == true) {
Log.info("Dropping old javac_state since it contains syntax errors."); Log.info("Dropping old javac_state since it contains syntax errors.");
db = new JavacState(args, binDir, gensrcDir, headerDir, permitUnidentifiedArtifacts, true, out, err); db = new JavacState(options, true, out, err);
} }
db.prev.calculateDependents(); db.prev.calculateDependents();
return db; return db;
@ -467,12 +465,6 @@ public class JavacState
return sr; return sr;
} }
/**
* Acquire the copying transform.
*/
public Transformer getCopier() {
return copyFiles;
}
/** /**
* If artifacts have gone missing, force a recompile of the packages * If artifacts have gone missing, force a recompile of the packages
@ -629,7 +621,7 @@ public class JavacState
public void performCopying(File binDir, Map<String,Transformer> suffixRules) { public void performCopying(File binDir, Map<String,Transformer> suffixRules) {
Map<String,Transformer> sr = new HashMap<>(); Map<String,Transformer> sr = new HashMap<>();
for (Map.Entry<String,Transformer> e : suffixRules.entrySet()) { for (Map.Entry<String,Transformer> e : suffixRules.entrySet()) {
if (e.getValue() == copyFiles) { if (e.getValue().getClass().equals(CopyFile.class)) {
sr.put(e.getKey(), e.getValue()); sr.put(e.getKey(), e.getValue());
} }
} }
@ -643,10 +635,11 @@ public class JavacState
public void performTranslation(File gensrcDir, Map<String,Transformer> suffixRules) { public void performTranslation(File gensrcDir, Map<String,Transformer> suffixRules) {
Map<String,Transformer> sr = new HashMap<>(); Map<String,Transformer> sr = new HashMap<>();
for (Map.Entry<String,Transformer> e : suffixRules.entrySet()) { for (Map.Entry<String,Transformer> e : suffixRules.entrySet()) {
if (e.getValue() != copyFiles && Class<?> trClass = e.getValue().getClass();
e.getValue() != compileJavaPackages) { if (trClass == CompileJavaPackages.class || trClass == CopyFile.class)
sr.put(e.getKey(), e.getValue()); continue;
}
sr.put(e.getKey(), e.getValue());
} }
perform(gensrcDir, sr); perform(gensrcDir, sr);
} }
@ -654,14 +647,11 @@ public class JavacState
/** /**
* Compile all the java sources. Return true, if it needs to be called again! * Compile all the java sources. Return true, if it needs to be called again!
*/ */
public boolean performJavaCompilations(File binDir, public boolean performJavaCompilations(Options args,
String serverSettings,
String[] args,
Set<String> recentlyCompiled, Set<String> recentlyCompiled,
boolean[] rcValue) { boolean[] rcValue) {
Map<String,Transformer> suffixRules = new HashMap<>(); Map<String,Transformer> suffixRules = new HashMap<>();
suffixRules.put(".java", compileJavaPackages); suffixRules.put(".java", compileJavaPackages);
compileJavaPackages.setExtra(serverSettings);
compileJavaPackages.setExtra(args); compileJavaPackages.setExtra(args);
rcValue[0] = perform(binDir, suffixRules); rcValue[0] = perform(binDir, suffixRules);
@ -813,7 +803,10 @@ public class JavacState
for (Source s : now.sources().values()) { for (Source s : now.sources().values()) {
// Don't include link only sources when comparing sources to compile // Don't include link only sources when comparing sources to compile
if (!s.isLinkedOnly()) { if (!s.isLinkedOnly()) {
calculatedSources.add(s.file().getPath()); String path = s.file().getPath();
if (mightNeedRewriting)
path = Util.normalizeDriveLetter(path);
calculatedSources.add(path);
} }
} }
// Read in the file and create another set of filenames with full paths. // Read in the file and create another set of filenames with full paths.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -71,17 +71,19 @@ public class Log {
err.println(msg); err.println(msg);
} }
static public void setLogLevel(String l, PrintStream o, PrintStream e) static public void initializeLog(PrintStream o, PrintStream e) {
throws ProblemException {
out = o; out = o;
err = e; err = e;
}
static public void setLogLevel(String l) {
switch (l) { switch (l) {
case "warn": level = WARN; break; case "warn": level = WARN; break;
case "info": level = INFO; break; case "info": level = INFO; break;
case "debug": level = DEBUG; break; case "debug": level = DEBUG; break;
case "trace": level = TRACE; break; case "trace": level = TRACE; break;
default: default:
throw new ProblemException("No such log level \"" + l + "\""); throw new IllegalArgumentException("No such log level \"" + l + "\"");
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,14 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.nio.file.Path;
import java.util.regex.Pattern; import java.nio.file.Files;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation;
import com.sun.tools.sjavac.server.JavacServer; import com.sun.tools.sjavac.server.JavacServer;
/** /**
@ -151,24 +152,8 @@ public class Main {
The resulting classes are written into bin. The resulting classes are written into bin.
*/ */
// This is the final destination for classes and copied files.
private File bin_dir;
// This is where the annotation process will put generated sources.
private File gensrc_dir;
// This is where javac -h puts the generated c-header files.
private File header_dir;
// This file contains the list of sources genereated by the makefile.
// We double check that our calculated list of sources matches this list,
// if not, then we terminate with an error!
private File makefile_source_list;
// The challenging task to manage an incremental build is done by javac_state.
private JavacState javac_state; private JavacState javac_state;
// The suffix rules tells you for example, that .java files should be compiled,
// and .html files should be copied and .properties files be translated.
Map<String,Transformer> suffix_rules;
public static void main(String... args) { public static void main(String... args) {
if (args.length > 0 && args[0].startsWith("--startserver:")) { if (args.length > 0 && args[0].startsWith("--startserver:")) {
if (args.length>1) { if (args.length>1) {
@ -199,118 +184,142 @@ public class Main {
} }
public int go(String[] args, PrintStream out, PrintStream err) { public int go(String[] args, PrintStream out, PrintStream err) {
Log.initializeLog(out, err);
Options options;
try { try {
if (args.length == 0 || findJavaSourceFiles(args) || findAtFile(args) || null==Util.findServerSettings(args)) { options = Options.parseArgs(args);
printHelp(); } catch (IllegalArgumentException e) {
return 0; Log.error(e.getMessage());
} return -1;
}
Log.setLogLevel(findLogLevel(args), out, err); Log.setLogLevel(options.getLogLevel());
String server_settings = Util.findServerSettings(args);
args = verifyImplicitOption(args);
// Find the source root directories, and add the -src option before these, if not there already.
args = addSrcBeforeDirectories(args);
// Check that there is at least one -src supplied.
checkSrcOption(args);
// Check that there is one -d supplied.
bin_dir = findDirectoryOption(args,"-d","output", true, false, true);
gensrc_dir = findDirectoryOption(args,"-s","gensrc", false, false, true);
header_dir = findDirectoryOption(args,"-h","headers", false, false, true);
makefile_source_list = findFileOption(args,"--compare-found-sources","makefile source list", false);
// Load the prev build state database. if (!validateOptions(options))
javac_state = JavacState.load(args, bin_dir, gensrc_dir, header_dir, return -1;
findBooleanOption(args, "--permit-unidentified-artifacts"), out, err);
// Setup the suffix rules from the command line. if (!createIfMissing(options.getDestDir()))
suffix_rules = javac_state.getJavaSuffixRule(); return -1;
findTranslateOptions(args, suffix_rules);
if (suffix_rules.keySet().size() > 1 && gensrc_dir == null) {
Log.error("You have translators but no gensrc dir (-s) specified!");
return -1;
}
findCopyOptions(args, suffix_rules);
// All found modules are put here. Path gensrc = options.getGenSrcDir();
Map<String,Module> modules = new HashMap<>(); if (gensrc != null && !createIfMissing(gensrc))
// We start out in the legacy empty no-name module. return -1;
// As soon as we stumble on a module-info.java file we change to that module.
Module current_module = new Module("", "");
modules.put("", current_module);
// Find all sources, use the suffix rules to know which files are sources. Path hdrdir = options.getHeaderDir();
Map<String,Source> sources = new HashMap<>(); if (hdrdir != null && !createIfMissing(hdrdir))
// Find the files, this will automatically populate the found modules return -1;
// with found packages where the sources are found!
findFiles(args, "-src", suffix_rules.keySet(), sources, modules, current_module, false);
if (sources.isEmpty()) { // Load the prev build state database.
Log.error("Found nothing to compile!"); javac_state = JavacState.load(options, out, err);
return -1;
}
// Create a map of all source files that are available for linking. Both -src and // Setup the suffix rules from the command line.
// -sourcepath point to such files. It is possible to specify multiple Map<String, Transformer> suffixRules = new HashMap<>();
// -sourcepath options to enable different filtering rules. If the
// filters are the same for multiple sourcepaths, they may be concatenated
// using :(;). Before sending the list of sourcepaths to javac, they are
// all concatenated. The list created here is used by the SmartFileWrapper to
// make sure only the correct sources are actually available.
// We might find more modules here as well.
Map<String,Source> sources_to_link_to = new HashMap<>();
findFiles(args, "-src", Util.set(".java"), sources_to_link_to, modules, current_module, true);
findFiles(args, "-sourcepath", Util.set(".java"), sources_to_link_to, modules, current_module, true);
// Rewrite the -src option to make it through to the javac instances.
rewriteOptions(args, "-src", "-sourcepath");
// Find all class files allowable for linking. // Handling of .java-compilation
// And pickup knowledge of all modules found here. suffixRules.putAll(javac_state.getJavaSuffixRule());
// This cannot currently filter classes inside jar files.
// Map<String,Source> classes_to_link_to = new HashMap<String,Source>();
// findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true);
// Find all module sources allowable for linking. // Handling of -copy and -tr
// Map<String,Source> modules_to_link_to = new HashMap<String,Source>(); suffixRules.putAll(options.getTranslationRules());
// findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true);
// Add the set of sources to the build database. // All found modules are put here.
javac_state.now().flattenPackagesSourcesAndArtifacts(modules); Map<String,Module> modules = new HashMap<>();
javac_state.now().checkInternalState("checking sources", false, sources); // We start out in the legacy empty no-name module.
javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to); // As soon as we stumble on a module-info.java file we change to that module.
javac_state.setVisibleSources(sources_to_link_to); Module current_module = new Module("", "");
modules.put("", current_module);
// If there is any change in the source files, taint packages // Find all sources, use the suffix rules to know which files are sources.
// and mark the database in need of saving. Map<String,Source> sources = new HashMap<>();
javac_state.checkSourceStatus(false);
// Find all existing artifacts. Their timestamp will match the last modified timestamps stored // Find the files, this will automatically populate the found modules
// in javac_state, simply because loading of the JavacState will clean out all artifacts // with found packages where the sources are found!
// that do not match the javac_state database. findSourceFiles(options.getSources(),
javac_state.findAllArtifacts(); suffixRules.keySet(),
sources,
modules,
current_module,
options.isDefaultPackagePermitted(),
false);
// Remove unidentified artifacts from the bin, gensrc and header dirs. if (sources.isEmpty()) {
// (Unless we allow them to be there.) Log.error("Found nothing to compile!");
// I.e. artifacts that are not known according to the build database (javac_state). return -1;
// For examples, files that have been manually copied into these dirs. }
// Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
// in javac_state) have already been removed when the javac_state was loaded.
if (!findBooleanOption(args, "--permit-unidentified-artifacts")) {
javac_state.removeUnidentifiedArtifacts();
}
// Go through all sources and taint all packages that miss artifacts.
javac_state.taintPackagesThatMissArtifacts();
// Now clean out all known artifacts belonging to tainted packages. // Create a map of all source files that are available for linking. Both -src and
javac_state.deleteClassArtifactsInTaintedPackages(); // -sourcepath point to such files. It is possible to specify multiple
// Copy files, for example property files, images files, xml files etc etc. // -sourcepath options to enable different filtering rules. If the
javac_state.performCopying(bin_dir, suffix_rules); // filters are the same for multiple sourcepaths, they may be concatenated
// Translate files, for example compile properties or compile idls. // using :(;). Before sending the list of sourcepaths to javac, they are
javac_state.performTranslation(gensrc_dir, suffix_rules); // all concatenated. The list created here is used by the SmartFileWrapper to
// Add any potentially generated java sources to the tobe compiled list. // make sure only the correct sources are actually available.
// (Generated sources must always have a package.) // We might find more modules here as well.
Map<String,Source> generated_sources = new HashMap<>(); Map<String,Source> sources_to_link_to = new HashMap<>();
Source.scanRoot(gensrc_dir, Util.set(".java"), null, null, null, null,
generated_sources, modules, current_module, false, true, false); List<SourceLocation> sourceResolutionLocations = new ArrayList<>();
sourceResolutionLocations.addAll(options.getSources());
sourceResolutionLocations.addAll(options.getSourceSearchPaths());
findSourceFiles(sourceResolutionLocations,
Collections.singleton(".java"),
sources_to_link_to,
modules,
current_module,
options.isDefaultPackagePermitted(),
true);
// Find all class files allowable for linking.
// And pickup knowledge of all modules found here.
// This cannot currently filter classes inside jar files.
// Map<String,Source> classes_to_link_to = new HashMap<String,Source>();
// findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true);
// Find all module sources allowable for linking.
// Map<String,Source> modules_to_link_to = new HashMap<String,Source>();
// findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true);
// Add the set of sources to the build database.
javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
javac_state.now().checkInternalState("checking sources", false, sources);
javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
javac_state.setVisibleSources(sources_to_link_to);
// If there is any change in the source files, taint packages
// and mark the database in need of saving.
javac_state.checkSourceStatus(false);
// Find all existing artifacts. Their timestamp will match the last modified timestamps stored
// in javac_state, simply because loading of the JavacState will clean out all artifacts
// that do not match the javac_state database.
javac_state.findAllArtifacts();
// Remove unidentified artifacts from the bin, gensrc and header dirs.
// (Unless we allow them to be there.)
// I.e. artifacts that are not known according to the build database (javac_state).
// For examples, files that have been manually copied into these dirs.
// Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
// in javac_state) have already been removed when the javac_state was loaded.
if (!options.isUnidentifiedArtifactPermitted()) {
javac_state.removeUnidentifiedArtifacts();
}
// Go through all sources and taint all packages that miss artifacts.
javac_state.taintPackagesThatMissArtifacts();
// Now clean out all known artifacts belonging to tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
// Copy files, for example property files, images files, xml files etc etc.
javac_state.performCopying(Util.pathToFile(options.getDestDir()), suffixRules);
// Translate files, for example compile properties or compile idls.
javac_state.performTranslation(Util.pathToFile(gensrc), suffixRules);
// Add any potentially generated java sources to the tobe compiled list.
// (Generated sources must always have a package.)
Map<String,Source> generated_sources = new HashMap<>();
try {
Source.scanRoot(Util.pathToFile(options.getGenSrcDir()), Util.set(".java"), null, null, null, null,
generated_sources, modules, current_module, false, true, false);
javac_state.now().flattenPackagesSourcesAndArtifacts(modules); javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
// Recheck the the source files and their timestamps again. // Recheck the the source files and their timestamps again.
javac_state.checkSourceStatus(true); javac_state.checkSourceStatus(true);
@ -320,7 +329,7 @@ public class Main {
// right, then incremental builds will fail with subtility. // right, then incremental builds will fail with subtility.
// If any difference is detected, then we will fail hard here. // If any difference is detected, then we will fail hard here.
// This is an important safety net. // This is an important safety net.
javac_state.compareWithMakefileList(makefile_source_list); javac_state.compareWithMakefileList(Util.pathToFile(options.getSourceReferenceList()));
// Do the compilations, repeatedly until no tainted packages exist. // Do the compilations, repeatedly until no tainted packages exist.
boolean again; boolean again;
@ -330,7 +339,7 @@ public class Main {
do { do {
// Clean out artifacts in tainted packages. // Clean out artifacts in tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages(); javac_state.deleteClassArtifactsInTaintedPackages();
again = javac_state.performJavaCompilations(bin_dir, server_settings, args, recently_compiled, rc); again = javac_state.performJavaCompilations(options, recently_compiled, rc);
if (!rc[0]) break; if (!rc[0]) break;
} while (again); } while (again);
// Only update the state if the compile went well. // Only update the state if the compile went well.
@ -351,620 +360,71 @@ public class Main {
} }
} }
/** private static boolean validateOptions(Options options) {
* Are java source files passed on the command line?
*/ String err = null;
private boolean findJavaSourceFiles(String[] args) {
String prev = ""; if (options.getDestDir() == null) {
for (String s : args) { err = "Please specify output directory.";
if (s.endsWith(".java") && !prev.equals("-xf") && !prev.equals("-if")) { } else if (options.isJavaFilesAmongJavacArgs()) {
return true; err = "Sjavac does not handle explicit compilation of single .java files.";
} } else if (options.isAtFilePresent()) {
prev = s; err = "Sjavac does not handle @-files.";
} else if (options.getServerConf() == null) {
err = "No server configuration provided.";
} else if (!options.getImplicitPolicy().equals("none")) {
err = "The only allowed setting for sjavac is -implicit:none";
} else if (options.getSources().isEmpty()) {
err = "You have to specify -src.";
} else if (options.getTranslationRules().size() > 1
&& options.getGenSrcDir() == null) {
err = "You have translators but no gensrc dir (-s) specified!";
} }
return false;
if (err != null)
Log.error(err);
return err == null;
} }
/** private static boolean createIfMissing(Path dir) {
* Is an at file passed on the command line?
*/
private boolean findAtFile(String[] args) {
for (String s : args) {
if (s.startsWith("@")) {
return true;
}
}
return false;
}
/** if (Files.isDirectory(dir))
* Find the log level setting. return true;
*/
private String findLogLevel(String[] args) {
for (String s : args) {
if (s.startsWith("--log=") && s.length()>6) {
return s.substring(6);
}
if (s.equals("-verbose")) {
return "info";
}
}
return "info";
}
/** if (Files.exists(dir)) {
* Remove smart javac wrapper arguments, before feeding Log.error(dir + " is not a directory.");
* the args to the plain javac. return false;
*/
static String[] removeWrapperArgs(String[] args) {
String[] out = new String[args.length];
// The first source path index is remembered
// here. So that all following can be concatenated to it.
int source_path = -1;
// The same for class path.
int class_path = -1;
// And module path.
int module_path = -1;
int j = 0;
for (int i = 0; i<args.length; ++i) {
if (args[i].equals("-src") ||
args[i].equals("-x") ||
args[i].equals("-i") ||
args[i].equals("-xf") ||
args[i].equals("-if") ||
args[i].equals("-copy") ||
args[i].equals("-tr") ||
args[i].equals("-j")) {
// Just skip it and skip following value
i++;
} else if (args[i].startsWith("--server:")) {
// Just skip it.
} else if (args[i].startsWith("--log=")) {
// Just skip it.
} else if (args[i].equals("--permit-unidentified-artifacts")) {
// Just skip it.
} else if (args[i].equals("--permit-sources-without-package")) {
// Just skip it.
} else if (args[i].equals("--compare-found-sources")) {
// Just skip it and skip verify file name
i++;
} else if (args[i].equals("-sourcepath")) {
if (source_path == -1) {
source_path = j;
out[j] = args[i];
out[j+1] = args[i+1];
j+=2;
i++;
} else {
// Skip this and its argument, but
// append argument to found sourcepath.
out[source_path+1] = out[source_path+1]+File.pathSeparatorChar+args[i+1];
i++;
}
} else if (args[i].equals("-classpath") || args[i].equals("-cp")) {
if (class_path == -1) {
class_path = j;
out[j] = args[i];
out[j+1] = args[i+1];
j+=2;
i++;
} else {
// Skip this and its argument, but
// append argument to found sourcepath.
out[class_path+1] = out[class_path+1]+File.pathSeparatorChar+args[i+1];
i++;
}
} else if (args[i].equals("-modulepath")) {
if (module_path == -1) {
module_path = j;
out[j] = args[i];
out[j+1] = args[i+1];
j+=2;
i++;
} else {
// Skip this and its argument, but
// append argument to found sourcepath.
out[module_path+1] = out[module_path+1]+File.pathSeparatorChar+args[i+1];
i++;
}
} else {
// Copy argument.
out[j] = args[i];
j++;
}
} }
String[] ret = new String[j];
System.arraycopy(out, 0, ret, 0, j);
return ret;
}
/**
* Make sure directory exist, create it if not.
*/
private static boolean makeSureExists(File dir) {
// Make sure the dest directories exist.
if (!dir.exists()) {
if (!dir.mkdirs()) {
Log.error("Could not create the directory "+dir.getPath());
return false;
}
}
return true;
}
/**
* Verify that a package pattern is valid.
*/
private static void checkPattern(String s) throws ProblemException {
// Package names like foo.bar.gamma are allowed, and
// package names suffixed with .* like foo.bar.* are
// also allowed.
Pattern p = Pattern.compile("[a-zA-Z_]{1}[a-zA-Z0-9_]*(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*(\\.\\*)?+");
Matcher m = p.matcher(s);
if (!m.matches()) {
throw new ProblemException("The string \""+s+"\" is not a proper package name pattern.");
}
}
/**
* Verify that a translate pattern is valid.
*/
private static void checkTranslatePattern(String s) throws ProblemException {
// .prop=com.sun.tools.javac.smart.CompileProperties
// .idl=com.sun.corba.CompileIdl
// .g3=antlr.CompileGrammar,debug=true
Pattern p = Pattern.compile(
"\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*=[a-z_]{1}[a-z0-9_]*(\\.[a-z_]{1}[a-z0-9_]*)*"+
"(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)(,.*)?");
Matcher m = p.matcher(s);
if (!m.matches()) {
throw new ProblemException("The string \""+s+"\" is not a proper translate pattern.");
}
}
/**
* Verify that a copy pattern is valid.
*/
private static void checkCopyPattern(String s) throws ProblemException {
// .gif
// .html
Pattern p = Pattern.compile(
"\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*");
Matcher m = p.matcher(s);
if (!m.matches()) {
throw new ProblemException("The string \""+s+"\" is not a proper suffix.");
}
}
/**
* Verify that a source file name is valid.
*/
private static void checkFilePattern(String s) throws ProblemException {
// File names like foo/bar/gamma/Bar.java are allowed,
// as well as /bar/jndi.properties as well as,
// */bar/Foo.java
Pattern p = null;
if (File.separatorChar == '\\') {
p = Pattern.compile("\\*?(.+\\\\)*.+");
}
else if (File.separatorChar == '/') {
p = Pattern.compile("\\*?(.+/)*.+");
} else {
throw new ProblemException("This platform uses the unsupported "+File.separatorChar+
" as file separator character. Please add support for it!");
}
Matcher m = p.matcher(s);
if (!m.matches()) {
throw new ProblemException("The string \""+s+"\" is not a proper file name.");
}
}
/**
* Scan the arguments to find an option is used.
*/
private static boolean hasOption(String[] args, String option) {
for (String a : args) {
if (a.equals(option)) return true;
}
return false;
}
/**
* Check if -implicit is supplied, if so check that it is none.
* If -implicit is not supplied, supply -implicit:none
* Only implicit:none is allowed because otherwise the multicore compilations
* and dependency tracking will be tangled up.
*/
private static String[] verifyImplicitOption(String[] args)
throws ProblemException {
boolean foundImplicit = false;
for (String a : args) {
if (a.startsWith("-implicit:")) {
foundImplicit = true;
if (!a.equals("-implicit:none")) {
throw new ProblemException("The only allowed setting for sjavac is -implicit:none, it is also the default.");
}
}
}
if (foundImplicit) {
return args;
}
// -implicit:none not found lets add it.
String[] newargs = new String[args.length+1];
System.arraycopy(args,0, newargs, 0, args.length);
newargs[args.length] = "-implicit:none";
return newargs;
}
/**
* Rewrite a single option into something else.
*/
private static void rewriteOptions(String[] args, String option, String new_option) {
for (int i=0; i<args.length; ++i) {
if (args[i].equals(option)) {
args[i] = new_option;
}
}
}
/**
* Scan the arguments to find an option that specifies a directory.
* Create the directory if necessary.
*/
private static File findDirectoryOption(String[] args, String option, String name, boolean needed, boolean allow_dups, boolean create)
throws ProblemException, ProblemException {
File dir = null;
for (int i = 0; i<args.length; ++i) {
if (args[i].equals(option)) {
if (dir != null) {
throw new ProblemException("You have already specified the "+name+" dir!");
}
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a directory following "+option+".");
}
if (args[i+1].indexOf(File.pathSeparatorChar) != -1) {
throw new ProblemException("You must only specify a single directory for "+option+".");
}
dir = new File(args[i+1]);
if (!dir.exists()) {
if (!create) {
throw new ProblemException("This directory does not exist: "+dir.getPath());
} else
if (!makeSureExists(dir)) {
throw new ProblemException("Cannot create directory "+dir.getPath());
}
}
if (!dir.isDirectory()) {
throw new ProblemException("\""+args[i+1]+"\" is not a directory.");
}
}
}
if (dir == null && needed) {
throw new ProblemException("You have to specify "+option);
}
try { try {
if (dir != null) Files.createDirectories(dir);
return dir.getCanonicalFile();
} catch (IOException e) { } catch (IOException e) {
throw new ProblemException(""+e); Log.error("Could not create directory: " + e.getMessage());
return false;
} }
return null;
}
/**
* Option is followed by path.
*/
private static boolean shouldBeFollowedByPath(String o) {
return o.equals("-s") ||
o.equals("-h") ||
o.equals("-d") ||
o.equals("-sourcepath") ||
o.equals("-classpath") ||
o.equals("-cp") ||
o.equals("-bootclasspath") ||
o.equals("-src");
}
/**
* Add -src before source root directories if not already there.
*/
private static String[] addSrcBeforeDirectories(String[] args) {
List<String> newargs = new ArrayList<>();
for (int i = 0; i<args.length; ++i) {
File dir = new File(args[i]);
if (dir.exists() && dir.isDirectory()) {
if (i == 0 || !shouldBeFollowedByPath(args[i-1])) {
newargs.add("-src");
}
}
newargs.add(args[i]);
}
return newargs.toArray(new String[0]);
}
/**
* Check the -src options.
*/
private static void checkSrcOption(String[] args)
throws ProblemException {
Set<File> dirs = new HashSet<>();
for (int i = 0; i<args.length; ++i) {
if (args[i].equals("-src")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a directory following -src.");
}
StringTokenizer st = new StringTokenizer(args[i+1], File.pathSeparator);
while (st.hasMoreElements()) {
File dir = new File(st.nextToken());
if (!dir.exists()) {
throw new ProblemException("This directory does not exist: "+dir.getPath());
}
if (!dir.isDirectory()) {
throw new ProblemException("\""+dir.getPath()+"\" is not a directory.");
}
if (dirs.contains(dir)) {
throw new ProblemException("The src directory \""+dir.getPath()+"\" is specified more than once!");
}
dirs.add(dir);
}
}
}
if (dirs.isEmpty()) {
throw new ProblemException("You have to specify -src.");
}
}
/**
* Scan the arguments to find an option that specifies a file.
*/
private static File findFileOption(String[] args, String option, String name, boolean needed)
throws ProblemException, ProblemException {
File file = null;
for (int i = 0; i<args.length; ++i) {
if (args[i].equals(option)) {
if (file != null) {
throw new ProblemException("You have already specified the "+name+" file!");
}
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a file following "+option+".");
}
file = new File(args[i+1]);
if (file.isDirectory()) {
throw new ProblemException("\""+args[i+1]+"\" is not a file.");
}
if (!file.exists() && needed) {
throw new ProblemException("The file \""+args[i+1]+"\" does not exist.");
}
}
}
if (file == null && needed) {
throw new ProblemException("You have to specify "+option);
}
return file;
}
/**
* Look for a specific switch, return true if found.
*/
public static boolean findBooleanOption(String[] args, String option) {
for (String arg : args) {
if (arg.equals(option))
return true;
}
return false;
}
/**
* Scan the arguments to find an option that specifies a number.
*/
public static int findNumberOption(String[] args, String option) {
int rc = 0;
for (int i = 0; i<args.length; ++i) {
if (args[i].equals(option)) {
if (args.length > i+1) {
rc = Integer.parseInt(args[i+1]);
}
}
}
return rc;
}
/**
* Scan the arguments to find the option (-tr) that setup translation rules to java source
* from different sources. For example: .properties are translated using CompileProperties
* The found translators are stored as suffix rules.
*/
private static void findTranslateOptions(String[] args, Map<String,Transformer> suffix_rules)
throws ProblemException, ProblemException {
for (int i = 0; i<args.length; ++i) {
if (args[i].equals("-tr")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a translate rule following -tr.");
}
String s = args[i+1];
checkTranslatePattern(s);
int ep = s.indexOf("=");
String suffix = s.substring(0,ep);
String classname = s.substring(ep+1);
if (suffix_rules.get(suffix) != null) {
throw new ProblemException("You have already specified a "+
"rule for the suffix "+suffix);
}
if (s.equals(".class")) {
throw new ProblemException("You cannot have a translator for .class files!");
}
if (s.equals(".java")) {
throw new ProblemException("You cannot have a translator for .java files!");
}
String extra = null;
int exp = classname.indexOf(",");
if (exp != -1) {
extra = classname.substring(exp+1);
classname = classname.substring(0,exp);
}
try {
Class<?> cl = Class.forName(classname);
Transformer t = (Transformer)cl.newInstance();
t.setExtra(extra);
suffix_rules.put(suffix, t);
}
catch (Exception e) {
throw new ProblemException("Cannot use "+classname+" as a translator!");
}
}
}
}
/**
* Scan the arguments to find the option (-copy) that setup copying rules into the bin dir.
* For example: -copy .html
* The found copiers are stored as suffix rules as well. No translation is done, just copying.
*/
private void findCopyOptions(String[] args, Map<String,Transformer> suffix_rules)
throws ProblemException, ProblemException {
for (int i = 0; i<args.length; ++i) {
if (args[i].equals("-copy")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a translate rule following -tr.");
}
String s = args[i+1];
checkCopyPattern(s);
if (suffix_rules.get(s) != null) {
throw new ProblemException("You have already specified a "+
"rule for the suffix "+s);
}
if (s.equals(".class")) {
throw new ProblemException("You cannot have a copy rule for .class files!");
}
if (s.equals(".java")) {
throw new ProblemException("You cannot have a copy rule for .java files!");
}
suffix_rules.put(s, javac_state.getCopier());
}
}
}
/**
* Rewrite a / separated path into \ separated, but only
* if we are running on a platform were File.separatorChar=='\', ie winapi.
*/
private String fixupSeparator(String p) {
if (File.separatorChar == '/') return p;
return p.replaceAll("/", "\\\\");
}
/**
* Scan the arguments for -i -x -xf -if followed by the option
* -src, -sourcepath, -modulepath or -classpath and produce a map of all the
* files to referenced for that particular option.
*
* Store the found sources and the found modules in the supplied maps.
*/
private boolean findFiles(String[] args, String option, Set<String> suffixes,
Map<String,Source> found_files, Map<String, Module> found_modules,
Module current_module, boolean inLinksrc)
throws ProblemException, ProblemException
{
// Track which source roots, source path roots and class path roots have been added.
Set<File> roots = new HashSet<>();
// Track the current set of package includes,excludes as well as excluded source files,
// to be used in the next -src/-sourcepath/-classpath
List<String> includes = new LinkedList<>();
List<String> excludes = new LinkedList<>();
List<String> excludefiles = new LinkedList<>();
List<String> includefiles = new LinkedList<>();
// This include is used to find all modules in the source.
List<String> moduleinfo = new LinkedList<>();
moduleinfo.add("module-info.java");
for (int i = 0; i<args.length; ++i) {
if (args[i].equals("-i")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a package pattern following -i");
}
String incl = args[i+1];
checkPattern(incl);
includes.add(incl);
}
if (args[i].equals("-x")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a package pattern following -x");
}
String excl = args[i+1];
checkPattern(excl);
excludes.add(excl);
}
if (args[i].equals("-xf")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a file following -xf");
}
String exclf = args[i+1];
checkFilePattern(exclf);
exclf = Util.normalizeDriveLetter(exclf);
excludefiles.add(fixupSeparator(exclf));
}
if (args[i].equals("-if")) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a file following -xf");
}
String inclf = args[i+1];
checkFilePattern(inclf);
inclf = Util.normalizeDriveLetter(inclf);
includefiles.add(fixupSeparator(inclf));
}
if (args[i].equals(option)) {
if (i+1 >= args.length) {
throw new ProblemException("You have to specify a directory following "+option);
}
String[] root_dirs = args[i+1].split(File.pathSeparator);
for (String r : root_dirs) {
File root = new File(r);
if (!root.isDirectory()) {
throw new ProblemException("\""+r+"\" is not a directory.");
}
try {
root = root.getCanonicalFile();
} catch (IOException e) {
throw new ProblemException(""+e);
}
if (roots.contains(root)) {
throw new ProblemException("\""+r+"\" has already been used for "+option);
}
if (root.equals(bin_dir)) {
throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -d");
}
if (root.equals(gensrc_dir)) {
throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -s");
}
if (root.equals(header_dir)) {
throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -h");
}
roots.add(root);
Source.scanRoot(root, suffixes, excludes, includes, excludefiles, includefiles,
found_files, found_modules, current_module,
findBooleanOption(args, "--permit-sources-without-package"),
false, inLinksrc);
}
}
if (args[i].equals("-src") ||
args[i].equals("-sourcepath") ||
args[i].equals("-modulepath") ||
args[i].equals("-classpath") ||
args[i].equals("-cp"))
{
// Reset the includes,excludes and excludefiles after they have been used.
includes = new LinkedList<>();
excludes = new LinkedList<>();
excludefiles = new LinkedList<>();
includefiles = new LinkedList<>();
}
}
return true; return true;
} }
}
/** Find source files in the given source locations. */
public static void findSourceFiles(List<SourceLocation> sourceLocations,
Set<String> sourceTypes,
Map<String,Source> foundFiles,
Map<String, Module> foundModules,
Module currentModule,
boolean permitSourcesInDefaultPackage,
boolean inLinksrc) {
for (SourceLocation source : sourceLocations) {
source.findSourceFiles(sourceTypes,
foundFiles,
foundModules,
currentModule,
permitSourcesInDefaultPackage,
inLinksrc);
}
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -201,7 +201,7 @@ public class Source implements Comparable<Source> {
// It might contain other source files however, (for -tr and -copy) these will // It might contain other source files however, (for -tr and -copy) these will
// always be included, since no package pattern can match the root directory. // always be included, since no package pattern can match the root directory.
currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage, currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage,
excludeFiles, includeFiles, false, excludeFiles, includeFiles,
foundFiles, foundModules, currentModule, foundFiles, foundModules, currentModule,
inGensrc, inLinksrc); inGensrc, inLinksrc);
@ -211,24 +211,28 @@ public class Source implements Comparable<Source> {
// Descend into the directory structure. // Descend into the directory structure.
scanDirectory(d, root_prefix, root, suffixes, scanDirectory(d, root_prefix, root, suffixes,
excludes, includes, excludeFiles, includeFiles, excludes, includes, excludeFiles, includeFiles,
false, foundFiles, foundModules, currentModule, inGensrc, inLinksrc); foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
} }
} }
} }
/** /**
* Test if a path matches any of the patterns given. * Test if a path matches any of the patterns given.
* The pattern foo.bar matches only foo.bar * The pattern foo/bar matches only foo/bar
* The pattern foo.* matches foo.bar and foo.bar.zoo etc * The pattern foo/* matches foo/bar and foo/bar/zoo etc
*/ */
static private boolean hasMatch(String path, List<String> patterns) { static private boolean hasMatch(String path, List<String> patterns) {
// Convert Windows '\' to '/' for the sake of comparing with the patterns
path = path.replace(File.separatorChar, '/');
for (String p : patterns) { for (String p : patterns) {
// Exact match // Exact match
if (p.equals(path)) { if (p.equals(path))
return true; return true;
}
// Single dot the end matches this package and all its subpackages. // Single dot the end matches this package and all its subpackages.
if (p.endsWith(".*")) { if (p.endsWith("/*")) {
// Remove the wildcard // Remove the wildcard
String patprefix = p.substring(0,p.length()-2); String patprefix = p.substring(0,p.length()-2);
// Does the path start with the pattern prefix? // Does the path start with the pattern prefix?
@ -237,7 +241,7 @@ public class Source implements Comparable<Source> {
// If the path is longer, then make sure that // If the path is longer, then make sure that
// the next part of the path starts with a dot (.) to prevent // the next part of the path starts with a dot (.) to prevent
// wildcard matching in the middle of a package name. // wildcard matching in the middle of a package name.
if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='.') { if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='/') {
return true; return true;
} }
} }
@ -251,6 +255,9 @@ public class Source implements Comparable<Source> {
// The pattern foo/bar.java only matches foo/bar.java // The pattern foo/bar.java only matches foo/bar.java
// The pattern */bar.java matches foo/bar.java and zoo/bar.java etc // The pattern */bar.java matches foo/bar.java and zoo/bar.java etc
static private boolean hasFileMatch(String path, List<String> patterns) { static private boolean hasFileMatch(String path, List<String> patterns) {
// Convert Windows '\' to '/' for the sake of comparing with the patterns
path = path.replace(File.separatorChar, '/');
path = Util.normalizeDriveLetter(path); path = Util.normalizeDriveLetter(path);
for (String p : patterns) { for (String p : patterns) {
// Exact match // Exact match
@ -276,7 +283,7 @@ public class Source implements Comparable<Source> {
*/ */
static private Module addFilesInDir(File dir, int rootPrefix, File root, static private Module addFilesInDir(File dir, int rootPrefix, File root,
Set<String> suffixes, boolean allow_javas, Set<String> suffixes, boolean allow_javas,
List<String> excludeFiles, List<String> includeFiles, boolean all, List<String> excludeFiles, List<String> includeFiles,
Map<String,Source> foundFiles, Map<String,Source> foundFiles,
Map<String,Module> foundModules, Map<String,Module> foundModules,
Module currentModule, Module currentModule,
@ -285,79 +292,82 @@ public class Source implements Comparable<Source> {
throws ProblemException throws ProblemException
{ {
for (File f : dir.listFiles()) { for (File f : dir.listFiles()) {
if (f.isFile()) {
boolean should_add =
(excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles))
&& (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles));
if (should_add) { if (!f.isFile())
if (!allow_javas && f.getName().endsWith(".java")) { continue;
throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+
", please remove "+f.getName()); boolean should_add =
} (excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles))
// Extract the file name relative the root. && (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles));
String fn = f.getPath().substring(rootPrefix);
// Extract the package name. if (!should_add)
int sp = fn.lastIndexOf(File.separatorChar); continue;
String pkg = "";
if (sp != -1) { if (!allow_javas && f.getName().endsWith(".java")) {
pkg = fn.substring(0,sp).replace(File.separatorChar,'.'); throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+
} ", please remove "+f.getName());
// Is this a module-info.java file? }
if (fn.endsWith("module-info.java")) { // Extract the file name relative the root.
// Aha! We have recursed into a module! String fn = f.getPath().substring(rootPrefix);
if (!currentModule.name().equals("")) { // Extract the package name.
throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn); int sp = fn.lastIndexOf(File.separatorChar);
String pkg = "";
if (sp != -1) {
pkg = fn.substring(0,sp);
}
// Is this a module-info.java file?
if (fn.endsWith("module-info.java")) {
// Aha! We have recursed into a module!
if (!currentModule.name().equals("")) {
throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn);
}
String module_name = fn.substring(0,fn.length()-16);
currentModule = new Module(module_name, f.getPath());
foundModules.put(module_name, currentModule);
}
// Extract the suffix.
int dp = fn.lastIndexOf(".");
String suffix = "";
if (dp > 0) {
suffix = fn.substring(dp);
}
// Should the file be added?
if (suffixes.contains(suffix)) {
Source of = foundFiles.get(f.getPath());
if (of != null) {
throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath());
}
of = currentModule.lookupSource(f.getPath());
if (of != null) {
// Oups, the source is already added, could be ok, could be not, lets check.
if (inLinksrc) {
// So we are collecting sources for linking only.
if (of.isLinkedOnly()) {
// Ouch, this one is also for linking only. Bad.
throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath());
} }
String module_name = fn.substring(0,fn.length()-16); // Ok, the existing source is to be compiled. Thus this link only is redundant
currentModule = new Module(module_name, f.getPath()); // since all compiled are also linked to. Continue to the next source.
foundModules.put(module_name, currentModule); // But we need to add the source, so that it will be visible to linking,
} // if not the multi core compile will fail because a JavaCompiler cannot
// Extract the suffix. // find the necessary dependencies for its part of the source.
int dp = fn.lastIndexOf("."); foundFiles.put(f.getPath(), of);
String suffix = ""; continue;
if (dp > 0) { } else {
suffix = fn.substring(dp); // We are looking for sources to compile, if we find an existing to be compiled
} // source with the same name, it is an internal error, since we must
// Should the file be added? // find the sources to be compiled before we find the sources to be linked to.
if (all || suffixes.contains(suffix)) { throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath());
Source of = foundFiles.get(f.getPath());
if (of != null) {
throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath());
}
of = currentModule.lookupSource(f.getPath());
if (of != null) {
// Oups, the source is already added, could be ok, could be not, lets check.
if (inLinksrc) {
// So we are collecting sources for linking only.
if (of.isLinkedOnly()) {
// Ouch, this one is also for linking only. Bad.
throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath());
}
// Ok, the existing source is to be compiled. Thus this link only is redundant
// since all compiled are also linked to. Continue to the next source.
// But we need to add the source, so that it will be visible to linking,
// if not the multi core compile will fail because a JavaCompiler cannot
// find the necessary dependencies for its part of the source.
foundFiles.put(f.getPath(), of);
continue;
} else {
// We are looking for sources to compile, if we find an existing to be compiled
// source with the same name, it is an internal error, since we must
// find the sources to be compiled before we find the sources to be linked to.
throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath());
}
}
Source s = new Source(currentModule, f.getPath(), f, root);
if (inGensrc) s.markAsGenerated();
if (inLinksrc) {
s.markAsLinkedOnly();
}
pkg = currentModule.name()+":"+pkg;
foundFiles.put(f.getPath(), s);
currentModule.addSource(pkg, s);
} }
} }
Source s = new Source(currentModule, f.getPath(), f, root);
if (inGensrc) s.markAsGenerated();
if (inLinksrc) {
s.markAsLinkedOnly();
}
pkg = currentModule.name()+":"+pkg;
foundFiles.put(f.getPath(), s);
currentModule.addSource(pkg, s);
} }
} }
return currentModule; return currentModule;
@ -368,23 +378,22 @@ public class Source implements Comparable<Source> {
static private void scanDirectory(File dir, int rootPrefix, File root, static private void scanDirectory(File dir, int rootPrefix, File root,
Set<String> suffixes, Set<String> suffixes,
List<String> excludes, List<String> includes, List<String> excludes, List<String> includes,
List<String> excludeFiles, List<String> includeFiles, boolean all, List<String> excludeFiles, List<String> includeFiles,
Map<String,Source> foundFiles, Map<String,Source> foundFiles,
Map<String,Module> foundModules, Map<String,Module> foundModules,
Module currentModule, boolean inGensrc, boolean inLinksrc) Module currentModule, boolean inGensrc, boolean inLinksrc)
throws ProblemException { throws ProblemException {
String pkg_name = ""; String path = "";
// Remove the root prefix from the dir path, and replace file separator with dots // Remove the root prefix from the dir path
// to get the package name.
if (dir.getPath().length() > rootPrefix) { if (dir.getPath().length() > rootPrefix) {
pkg_name = dir.getPath().substring(rootPrefix).replace(File.separatorChar,'.'); path = dir.getPath().substring(rootPrefix);
} }
// Should this package directory be included and not excluded? // Should this package directory be included and not excluded?
if (all || ((includes==null || includes.isEmpty() || hasMatch(pkg_name, includes)) && if ((includes==null || includes.isEmpty() || hasMatch(path, includes)) &&
(excludes==null || excludes.isEmpty() || !hasMatch(pkg_name, excludes)))) { (excludes==null || excludes.isEmpty() || !hasMatch(path, excludes))) {
// Add the source files. // Add the source files.
currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles, all, currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles,
foundFiles, foundModules, currentModule, inGensrc, inLinksrc); foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
} }
@ -392,7 +401,7 @@ public class Source implements Comparable<Source> {
if (d.isDirectory()) { if (d.isDirectory()) {
// Descend into the directory structure. // Descend into the directory structure.
scanDirectory(d, rootPrefix, root, suffixes, scanDirectory(d, rootPrefix, root, suffixes,
excludes, includes, excludeFiles, includeFiles, all, excludes, includes, excludeFiles, includeFiles,
foundFiles, foundModules, currentModule, inGensrc, inLinksrc); foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,8 @@ import java.net.URI;
import java.util.Set; import java.util.Set;
import java.util.Map; import java.util.Map;
import com.sun.tools.sjavac.options.Options;
/** /**
* The transform interface is used to transform content inside a package, from one form to another. * The transform interface is used to transform content inside a package, from one form to another.
* Usually the output form is an unpredictable number of output files. (eg class files) * Usually the output form is an unpredictable number of output files. (eg class files)
@ -95,5 +97,5 @@ public interface Transformer
PrintStream err); PrintStream err);
void setExtra(String e); void setExtra(String e);
void setExtra(String[] args); void setExtra(Options args);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
package com.sun.tools.sjavac; package com.sun.tools.sjavac;
import java.io.File; import java.io.File;
import java.nio.file.Path;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -94,14 +95,12 @@ public class Util {
* do settings = cleanOptions("--server:",Util.set("-portfile"),settings); * do settings = cleanOptions("--server:",Util.set("-portfile"),settings);
* now settings equals "--server:portfile=bar" * now settings equals "--server:portfile=bar"
* *
* @param optionPrefix The option name, including colon, eg --server:
* @param allowsSubOptions A set of the allowed sub options, id portfile etc. * @param allowsSubOptions A set of the allowed sub options, id portfile etc.
* @param s The option settings string. * @param s The option settings string.
*/ */
public static String cleanSubOptions(String optionPrefix, Set<String> allowedSubOptions, String s) { public static String cleanSubOptions(Set<String> allowedSubOptions, String s) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (!s.startsWith(optionPrefix)) return ""; StringTokenizer st = new StringTokenizer(s, ",");
StringTokenizer st = new StringTokenizer(s.substring(optionPrefix.length()), ",");
while (st.hasMoreTokens()) { while (st.hasMoreTokens()) {
String o = st.nextToken(); String o = st.nextToken();
int p = o.indexOf('='); int p = o.indexOf('=');
@ -157,4 +156,9 @@ public class Util {
} }
return null; return null;
} }
// TODO: Remove when refactoring from java.io.File to java.nio.file.Path.
public static File pathToFile(Path path) {
return path == null ? null : path.toFile();
}
} }

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.options;
import java.util.Iterator;
public class ArgumentIterator implements Iterator<String> {
/** The underlying argument iterator */
private Iterator<String> iter;
/** Extra state used to implement peek and current */
private String current;
private String buffered;
public ArgumentIterator(Iterable<String> iter) {
this.iter = iter.iterator();
}
@Override
public boolean hasNext() {
return buffered != null || iter.hasNext();
}
@Override
public String next() {
fillBuffer();
current = buffered;
buffered = null;
return current;
}
/**
* @return the last element returned by next() (or {@code null} if next has
* never been invoked on this iterator).
*/
public String current() {
return current;
}
/** Can't remove current element, since we may have buffered it. */
@Override
public void remove() {
throw new UnsupportedOperationException();
}
/**
* @return Returns the next element without advancing the iterator
*/
public String peek() {
fillBuffer();
return buffered;
}
private void fillBuffer() {
if (buffered == null && iter.hasNext())
buffered = iter.next();
}
}

View file

@ -0,0 +1,360 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.options;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.sun.tools.sjavac.CopyFile;
import com.sun.tools.sjavac.Transformer;
/**
* Sjavac options can be classified as:
*
* (1) relevant only for sjavac, such as --server
* (2) relevant for sjavac and javac, such as -d, or
* (3) relevant only for javac, such as -g.
*
* This enum represents all options from (1) and (2). Note that instances of
* this enum only entail static information about the option. For storage of
* option values, refer to com.sun.tools.sjavac.options.Options.
*/
public enum Option {
SRC("-src", "Location of source files to be compiled") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
List<Path> paths = getFileListArg(iter, helper);
if (paths != null)
helper.sourceRoots(paths);
}
},
SOURCEPATH("-sourcepath", "Specify search path for sources.") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
List<Path> paths = getFileListArg(iter, helper);
if (paths != null)
helper.sourcepath(paths);
}
},
MODULEPATH("-modulepath", "Specify search path for modules.") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
List<Path> paths = getFileListArg(iter, helper);
if (paths != null)
helper.modulepath(paths);
}
},
CLASSPATH("-classpath", "Specify search path for classes.") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
List<Path> paths = getFileListArg(iter, helper);
if (paths != null)
helper.classpath(paths);
}
},
CP("-cp", "An alias for -classpath") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
CLASSPATH.processMatching(iter, helper);
}
},
X("-x", "Exclude directory from the subsequent source directory") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
if (pattern != null)
helper.exclude(pattern);
}
},
I("-i", "Include only the given directory from the subsequent source directory") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
if (pattern != null)
helper.include(pattern);
}
},
XF("-xf", "Exclude a given file") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
if (pattern != null)
helper.excludeFile(pattern);
}
},
IF("-if", "Include only the given file") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
String pattern = getFilePatternArg(iter, helper);
if (pattern != null)
helper.includeFile(pattern);
}
},
TR("-tr", "Translate resources") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext()) {
helper.reportError(arg + " must be followed by a translation rule");
return;
}
String trArg = iter.next();
// Validate argument syntax. Examples:
// .prop=com.sun.tools.javac.smart.CompileProperties
// .idl=com.sun.corba.CompileIdl
// .g3=antlr.CompileGrammar,debug=true
String ident = "[a-zA-Z_][a-zA-Z0-9_]*";
Pattern p = Pattern.compile("(?<suffix>\\." + ident + ")=" +
"(?<class>" + ident + "(\\." + ident + ")*)" +
"(?<extra>,.*)?");
// Check syntax
Matcher m = p.matcher(trArg);
if (!m.matches()) {
helper.reportError("The string \"" + trArg + "\" is not a " +
"valid translate pattern");
return;
}
// Extract relevant parts
String suffix = m.group("suffix");
String classname = m.group("class");
String extra = m.group("extra");
// Valid suffix?
if (suffix.matches("\\.(class|java)")) {
helper.reportError("You cannot have a translator for " +
suffix + " files!");
return;
}
// Construct transformer
try {
Class<?> trCls = Class.forName(classname);
Transformer transformer = (Transformer) trCls.newInstance();
transformer.setExtra(extra);
helper.addTransformer(suffix, transformer);
} catch (Exception e) {
helper.reportError("Cannot use " + classname +
" as a translator: " + e.getMessage());
}
}
},
COPY("-copy", "Copy resources") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext()) {
helper.reportError(arg + " must be followed by a resource type");
return;
}
String copyArg = iter.next();
// Validate argument syntax. Examples: .gif, .html
if (!copyArg.matches("\\.[a-zA-Z_][a-zA-Z0-9_]*")) {
helper.reportError("The string \"" + copyArg + "\" is not a " +
"valid resource type.");
return;
}
helper.addTransformer(copyArg, new CopyFile());
}
},
J("-j", "Number of cores") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext() || !iter.peek().matches("\\d+")) {
helper.reportError(arg + " must be followed by an integer");
return;
}
helper.numCores(Integer.parseInt(iter.next()));
}
},
SERVER("--server:", "Specify server configuration file of running server") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.serverConf(iter.current().substring(arg.length()));
}
},
STARTSERVER("--startserver:", "Start server and use the given configuration file") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.startServerConf(iter.current().substring(arg.length()));
}
},
IMPLICIT("-implicit:", "Specify how to treat implicitly referenced source code") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.implicit(iter.current().substring(arg.length()));
}
},
LOG("--log=", "Specify logging level") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.logLevel(iter.current().substring(arg.length()));
}
},
VERBOSE("-verbose", "Set verbosity level to \"info\"") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.logLevel("info");
}
},
PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Keep unidentified artifacts in destination directory") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.permitUnidentifiedArtifacts();
}
},
PERMIT_SOURCES_WITHOUT_PACKAGE("--permit-sources-without-package", "Permit sources in the default package") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
helper.permitDefaultPackage();
}
},
COMPARE_FOUND_SOURCES("--compare-found-sources", "Compare found sources with given sources") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
Path referenceSourceList = getFileArg(iter, helper, true, false);
if (referenceSourceList != null)
helper.compareFoundSources(referenceSourceList);
}
},
D("-d", "Output destination directory") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
Path dir = getFileArg(iter, helper, false, true);
if (dir != null)
helper.destDir(dir);
}
},
S("-s", "Directory for generated sources") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
Path dir = getFileArg(iter, helper, false, true);
if (dir != null)
helper.generatedSourcesDir(dir);
}
},
H("-h", "Directory for header files") {
@Override
protected void processMatching(ArgumentIterator iter, OptionHelper helper) {
Path dir = getFileArg(iter, helper, false, true);
if (dir != null)
helper.headerDir(dir);
}
};
public final String arg;
final String description;
private Option(String arg, String description) {
this.arg = arg;
this.description = description;
}
/** Retrieve and verify syntax of file list argument. */
List<Path> getFileListArg(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext()) {
helper.reportError(arg + " must be followed by a list of files " +
"separated by " + File.pathSeparator);
return null;
}
List<Path> result = new ArrayList<>();
for (String pathStr : iter.next().split(File.pathSeparator))
result.add(Paths.get(pathStr));
return result;
}
/** Retrieve and verify syntax of file argument. */
Path getFileArg(ArgumentIterator iter, OptionHelper helper, boolean fileAcceptable, boolean dirAcceptable) {
if (!iter.hasNext()) {
String errmsg = arg + " must be followed by ";
if (fileAcceptable && dirAcceptable) errmsg += "a file or directory.";
else if (fileAcceptable) errmsg += "a file.";
else if (dirAcceptable) errmsg += "a directory.";
else throw new IllegalArgumentException("File or directory must be acceptable.");
helper.reportError(errmsg);
return null;
}
return Paths.get(iter.next());
}
/** Retrieve the next file or package argument. */
String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) {
if (!iter.hasNext()) {
helper.reportError(arg + " must be followed by a file or directory pattern.");
return null;
}
return iter.next();
}
// Future cleanup: Change the "=" syntax to ":" syntax to be consistent and
// to follow the javac-option style.
public boolean hasOption() {
return arg.endsWith(":") || arg.endsWith("=");
}
/**
* Process current argument of argIter.
*
* It's final, since the option customization is typically done in
* processMatching.
*
* @param argIter Iterator to read current and succeeding arguments from.
* @param helper The helper to report back to.
* @return true iff the argument was processed by this option.
*/
public final boolean processCurrent(ArgumentIterator argIter,
OptionHelper helper) {
String fullArg = argIter.current(); // "-tr" or "-log=level"
if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) {
processMatching(argIter, helper);
return true;
}
// Did not match
return false;
}
/** Called by process if the current argument matches this option. */
protected abstract void processMatching(ArgumentIterator argIter,
OptionHelper helper);
}

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.options;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import com.sun.tools.sjavac.Transformer;
/**
* This class is used to decode sjavac options.
* See com.sun.tools.sjavac.options.Options for example usage.
*/
public abstract class OptionHelper {
/** Handle error */
public abstract void reportError(String msg);
/** Record a package exclusion pattern */
public abstract void exclude(String excl);
/** Record a package inclusion pattern */
public abstract void include(String incl);
/** Record a file exclusion */
public abstract void excludeFile(String exclFile);
/** Record a file inclusion */
public abstract void includeFile(String inclFile);
/** Record a root of sources to be compiled */
public abstract void sourceRoots(List<Path> path);
/** Record a suffix + transformer */
public abstract void addTransformer(String suffix, Transformer tr);
/** Record a sourcepath to be used */
public abstract void sourcepath(List<Path> path);
/** Record a modulepath to be used */
public abstract void modulepath(List<Path> path);
/** Record a classpath to be used */
public abstract void classpath(List<Path> path);
/** Record the number of cores */
public abstract void numCores(int parseInt);
/** Record desired log level */
public abstract void logLevel(String level);
/** Record path for reference source list */
public abstract void compareFoundSources(Path referenceList);
/** Record the fact that unidentified artifacts are permitted */
public abstract void permitUnidentifiedArtifacts();
/** Record the fact that sources in the default package are permitted */
public abstract void permitDefaultPackage();
/** Record server configuration parameters */
public abstract void serverConf(String serverConf);
/** Record server launch configuration parameters */
public abstract void startServerConf(String serverConf);
/** Record some arguments to be passed on to javac */
public abstract void javacArg(String... arg);
/** Sets the destination directory for the compilation */
public abstract void destDir(Path dir);
/** Sets the directory for generated sources */
public abstract void generatedSourcesDir(Path genSrcDir);
/** Sets the directory for generated headers */
public abstract void headerDir(Path dir);
/** Sets the implicit policy */
public abstract void implicit(String policy);
/**
* Traverses an array of arguments and performs the appropriate callbacks.
*
* @param args the arguments to traverse.
*/
void traverse(String[] args) {
ArgumentIterator argIter = new ArgumentIterator(Arrays.asList(args));
nextArg:
while (argIter.hasNext()) {
String arg = argIter.next();
if (arg.startsWith("-")) {
for (Option opt : Option.values()) {
if (opt.processCurrent(argIter, this))
continue nextArg;
}
javacArg(arg);
// Does this javac argument take an argument? If so, don't
// let it pass on to sjavac as a source root directory.
for (com.sun.tools.javac.main.Option javacOpt : com.sun.tools.javac.main.Option.values()) {
if (javacOpt.matches(arg)) {
boolean takesArgument = javacOpt.hasArg();
boolean separateToken = !arg.contains(":") && !arg.contains("=");
if (takesArgument && separateToken)
javacArg(argIter.next());
}
}
} else {
sourceRoots(Arrays.asList(Paths.get(arg)));
}
}
}
}

View file

@ -0,0 +1,490 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.options;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sun.tools.sjavac.Transformer;
/**
* Instances of this class represent values for sjavac command line options.
*/
public class Options {
// Output directories
private Path destDir, genSrcDir, headerDir;
// Input directories
private List<SourceLocation> sources = new ArrayList<>();
private List<SourceLocation> sourceSearchPaths = new ArrayList<>();
private List<SourceLocation> classSearchPaths = new ArrayList<>();
private List<SourceLocation> moduleSearchPaths = new ArrayList<>();
private String logLevel = "info";
private boolean permitUnidentifiedArtifact = false;
private boolean permitSourcesInDefaultPackage = false;
private Path sourceReferenceList;
private int numCores = 4;
private String implicitPolicy = "none";
private List<String> javacArgs = new ArrayList<>();
private Map<String, Transformer> trRules = new HashMap<>();
private boolean startServer = false;
// Server configuration string
private String serverConf;
/** Get the policy for implicit classes */
public String getImplicitPolicy() {
return implicitPolicy;
}
/** Get the path for generated sources (or null if no such path is set) */
public Path getGenSrcDir() {
return genSrcDir;
}
/** Get the path for the destination directory */
public Path getDestDir() {
return destDir;
}
/** Get the path for the header directory (or null if no such path is set) */
public Path getHeaderDir() {
return headerDir;
}
/** Get all source locations for files to be compiled */
public List<SourceLocation> getSources() {
return sources;
}
/**
* Get all paths to search for classes in .java format. (Java-files in
* found here should not be compiled.
*/
public List<SourceLocation> getSourceSearchPaths() {
return sourceSearchPaths;
}
/** Get all paths to search for classes in. */
public List<SourceLocation> getClassSearchPath() {
return classSearchPaths;
}
/** Get all paths to search for modules in. */
public List<SourceLocation> getModuleSearchPaths() {
return moduleSearchPaths;
}
/** Get the log level. */
public String getLogLevel() {
return logLevel;
}
/** Returns true iff artifacts in the output directories should be kept,
* even if they would not be generated in a clean build. */
public boolean isUnidentifiedArtifactPermitted() {
return permitUnidentifiedArtifact;
}
/** Returns true iff sources in the default package should be permitted. */
public boolean isDefaultPackagePermitted() {
return permitSourcesInDefaultPackage;
}
/** Get the path to the list of reference sources (or null if none is set) */
public Path getSourceReferenceList() {
return sourceReferenceList;
}
/** Get the number of cores to be used by sjavac */
public int getNumCores() {
return numCores;
}
/** Returns all arguments relevant to javac but irrelevant to sjavac. */
public List<String> getJavacArgs() {
return javacArgs;
}
/**
* Get a map which maps suffixes to transformers (for example
* ".java" -> CompileJavaPackages)
*/
public Map<String, Transformer> getTranslationRules() {
return trRules;
}
/** Return true iff a new server should be started */
public boolean startServerFlag() {
return startServer;
}
/** Return the server configuration string. */
public String getServerConf() {
return serverConf;
}
/**
* Parses the given argument array and returns a corresponding Options
* instance.
*/
public static Options parseArgs(String... args) {
Options options = new Options();
options.new ArgDecoderOptionHelper().traverse(args);
return options;
}
/** Returns true iff a .java file is among the javac arguments */
public boolean isJavaFilesAmongJavacArgs() {
for (String javacArg : javacArgs)
if (javacArg.endsWith(".java"))
return true;
return false;
}
/** Returns true iff an @-file is among the javac arguments */
public boolean isAtFilePresent() {
for (String javacArg : javacArgs)
if (javacArg.startsWith("@"))
return true;
return false;
}
/**
* Returns a string representation of the options that affect the result of
* the compilation. (Used for saving the state of the options used in a
* previous compile.)
*/
public String getStateArgsString() {
// Local utility class for collecting the arguments
class StateArgs {
private List<String> args = new ArrayList<>();
void addArg(Option opt) {
args.add(opt.arg);
}
void addArg(Option opt, Object val) {
addArg(opt);
args.add(val.toString());
}
void addSourceLocations(Option opt, List<SourceLocation> locs) {
for (SourceLocation sl : locs) {
for (String pkg : sl.includes) addArg(Option.I, pkg);
for (String pkg : sl.excludes) addArg(Option.X, pkg);
for (String f : sl.excludedFiles) addArg(Option.XF, f);
for (String f : sl.includedFiles) addArg(Option.IF, f);
addArg(opt, sl.getPath());
}
}
String getResult() {
String result = "";
for (String s : args)
result += s + " ";
return result.trim();
}
public void addAll(Collection<String> toAdd) {
args.addAll(toAdd);
}
}
StateArgs args = new StateArgs();
// Directories
if (genSrcDir != null)
args.addArg(Option.S, genSrcDir.normalize());
if (headerDir != null)
args.addArg(Option.H, headerDir.normalize());
if (destDir != null)
args.addArg(Option.D, destDir.normalize());
// Source roots
args.addSourceLocations(Option.SRC, sources);
args.addSourceLocations(Option.SOURCEPATH, sourceSearchPaths);
args.addSourceLocations(Option.CLASSPATH, classSearchPaths);
args.addSourceLocations(Option.MODULEPATH, moduleSearchPaths);
// Boolean options
if (permitSourcesInDefaultPackage)
args.addArg(Option.PERMIT_SOURCES_WITHOUT_PACKAGE);
if (permitUnidentifiedArtifact)
args.addArg(Option.PERMIT_UNIDENTIFIED_ARTIFACTS);
// Translation rules
for (Map.Entry<String, Transformer> tr : trRules.entrySet()) {
String val = tr.getKey() + "=" + tr.getValue().getClass().getName();
args.addArg(Option.TR, val);
}
// Javac args
args.addAll(javacArgs);
return args.getResult();
}
/** Extract the arguments to be passed on to javac. */
public String[] prepJavacArgs() {
List<String> args = new ArrayList<>();
// Output directories
args.add("-d");
args.add(destDir.toString());
if (getGenSrcDir() != null) {
args.add("-s");
args.add(genSrcDir.toString());
}
if (headerDir != null) {
args.add("-h");
args.add(headerDir.toString());
}
// Prep sourcepath
List<SourceLocation> sourcepath = new ArrayList<>();
sourcepath.addAll(sources);
sourcepath.addAll(sourceSearchPaths);
if (sourcepath.size() > 0) {
args.add("-sourcepath");
args.add(concatenateSourceLocations(sourcepath));
}
// Prep classpath
if (classSearchPaths.size() > 0) {
args.add("-classpath");
args.add(concatenateSourceLocations(classSearchPaths));
}
// This can't be anything but 'none'. Enforced by sjavac main method.
args.add("-implicit:" + implicitPolicy);
// Append javac-options (i.e. pass through options not recognized by
// sjavac to javac.)
args.addAll(javacArgs);
return args.toArray(new String[args.size()]);
}
// Helper method to join a list of source locations separated by
// File.pathSeparator
private static String concatenateSourceLocations(List<SourceLocation> locs) {
String s = "";
for (SourceLocation loc : locs)
s += (s.isEmpty() ? "" : java.io.File.pathSeparator) + loc.getPath();
return s;
}
// OptionHelper that records the traversed options in this Options instance.
private class ArgDecoderOptionHelper extends OptionHelper {
List<String> includes, excludes, includeFiles, excludeFiles;
{
resetFilters();
}
boolean headerProvided = false;
boolean genSrcProvided = false;
@Override
public void reportError(String msg) {
throw new IllegalArgumentException(msg);
}
@Override
public void sourceRoots(List<Path> paths) {
sources.addAll(createSourceLocations(paths));
}
@Override
public void exclude(String exclPattern) {
excludes.add(exclPattern);
}
@Override
public void include(String inclPattern) {
includes.add(inclPattern);
}
@Override
public void excludeFile(String exclFilePattern) {
excludeFiles.add(exclFilePattern);
}
@Override
public void includeFile(String inclFilePattern) {
includeFiles.add(inclFilePattern);
}
@Override
public void addTransformer(String suffix, Transformer tr) {
if (trRules.containsKey(suffix)) {
reportError("More than one transformer specified for " +
"suffix " + suffix + ".");
return;
}
trRules.put(suffix, tr);
}
@Override
public void sourcepath(List<Path> paths) {
sourceSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void modulepath(List<Path> paths) {
moduleSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void classpath(List<Path> paths) {
classSearchPaths.addAll(createSourceLocations(paths));
}
@Override
public void numCores(int n) {
numCores = n;
}
@Override
public void logLevel(String level) {
logLevel = level;
}
@Override
public void compareFoundSources(Path referenceList) {
sourceReferenceList = referenceList;
}
@Override
public void permitUnidentifiedArtifacts() {
permitUnidentifiedArtifact = true;
}
@Override
public void permitDefaultPackage() {
permitSourcesInDefaultPackage = true;
}
@Override
public void serverConf(String conf) {
if (serverConf != null)
reportError("Can not specify more than one server configuration.");
else
serverConf = conf;
}
@Override
public void implicit(String policy) {
implicitPolicy = policy;
}
@Override
public void startServerConf(String conf) {
if (serverConf != null)
reportError("Can not specify more than one server configuration.");
else {
startServer = true;
serverConf = conf;
}
}
@Override
public void javacArg(String... arg) {
javacArgs.addAll(Arrays.asList(arg));
}
@Override
public void destDir(Path dir) {
if (destDir != null) {
reportError("Destination directory already specified.");
return;
}
destDir = dir.toAbsolutePath();
}
@Override
public void generatedSourcesDir(Path dir) {
if (genSrcProvided) {
reportError("Directory for generated sources already specified.");
return;
}
genSrcProvided = true;
genSrcDir = dir.toAbsolutePath();
}
@Override
public void headerDir(Path dir) {
if (headerProvided) {
reportError("Header directory already specified.");
return;
}
headerProvided = true;
headerDir = dir.toAbsolutePath();
}
private List<SourceLocation> createSourceLocations(List<Path> paths) {
List<SourceLocation> result = new ArrayList<>();
for (Path path : paths) {
result.add(new SourceLocation(
path,
includes,
excludes,
includeFiles,
excludeFiles));
}
resetFilters();
return result;
}
private void resetFilters() {
includes = new ArrayList<>();
excludes = new ArrayList<>();
includeFiles = new ArrayList<>();
excludeFiles = new ArrayList<>();
}
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.sjavac.options;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.sun.tools.sjavac.Module;
import com.sun.tools.sjavac.ProblemException;
import com.sun.tools.sjavac.Source;
/**
* Represents a directory to be used for input to sjavac. (For instance a
* sourcepath or classpath.)
*/
public class SourceLocation {
// Path to the root directory
private Path path;
// Package include / exclude patterns and file includes / excludes.
List<String> includes, excludes, includedFiles, excludedFiles;
public SourceLocation(Path path,
List<String> includes,
List<String> excludes,
List<String> includedFiles,
List<String> excludedFiles) {
this.path = path;
this.includes = includes;
this.excludes = excludes;
this.includedFiles = includedFiles;
this.excludedFiles = excludedFiles;
}
/**
* Finds all files with the given suffix that pass the include / exclude
* filters in this source location.
*
* @param suffixes The set of suffixes to search for
* @param foundFiles The map in which to store the found files
* @param foundModules The map in which to store the found modules
* @param currentModule The current module
* @param permitSourcesInDefaultPackage true if sources in default package
* are to be permitted
* @param inLinksrc true if in link source
*/
public void findSourceFiles(Set<String> suffixes,
Map<String, Source> foundFiles,
Map<String, Module> foundModules,
Module currentModule,
boolean permitSourcesInDefaultPackage,
boolean inLinksrc) {
try {
Source.scanRoot(path.toFile(), suffixes, excludes, includes,
excludedFiles, includedFiles, foundFiles, foundModules,
currentModule, permitSourcesInDefaultPackage, false,
inLinksrc);
} catch (ProblemException e) {
e.printStackTrace();
}
}
/** Get the root directory of this source location */
public Path getPath() {
return path;
}
/** Get the package include patterns */
public List<String> getIncludes() {
return includes;
}
/** Get the package exclude patterns */
public List<String> getExcludes() {
return excludes;
}
/** Get the file include patterns */
public List<String> getIncludedFiles() {
return includedFiles;
}
/** Get the file exclude patterns */
public List<String> getExcludedFiles() {
return excludedFiles;
}
}

View file

@ -104,6 +104,17 @@ public class JavacServer {
allPortFiles = new HashMap<>(); allPortFiles = new HashMap<>();
} }
PortFile pf = allPortFiles.get(filename); PortFile pf = allPortFiles.get(filename);
// Port file known. Does it still exist?
if (pf != null) {
try {
if (!pf.exists())
pf = null;
} catch (IOException ioex) {
ioex.printStackTrace();
}
}
if (pf == null) { if (pf == null) {
pf = new PortFile(filename); pf = new PortFile(filename);
allPortFiles.put(filename, pf); allPortFiles.put(filename, pf);
@ -305,7 +316,7 @@ public class JavacServer {
// We could not connect to the server. Try again. // We could not connect to the server. Try again.
attempts++; attempts++;
try { try {
Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS * 1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ExclPattern {
public static void main(String[] ignore) throws IOException {
String toBeExcluded = "pkg/excl-dir/excluded.txt";
String toBeIncluded = "pkg/incl-dir/included.txt";
// Set up source directory with directory to be excluded
populate(Paths.get("srcdir"),
"pkg/SomeClass.java",
"package pkg; public class SomeClass { }",
toBeExcluded,
"This file should not end up in the dest directory.",
toBeIncluded,
"This file should end up in the dest directory.");
String[] args = {
"-x", "pkg/excl-dir/*",
"-src", "srcdir",
"-d", "dest",
"-j", "1",
"-copy", ".txt",
"--server:portfile=testserver,background=false",
"--log=debug"
};
int rc = new com.sun.tools.sjavac.Main().go(args, System.out, System.err);
if (rc != 0) throw new RuntimeException("Error during compile!");
if (!Files.exists(Paths.get("dest/" + toBeIncluded)))
throw new AssertionError("File missing: " + toBeIncluded);
if (Files.exists(Paths.get("dest/" + toBeExcluded)))
throw new AssertionError("File present: " + toBeExcluded);
}
static void populate(Path root, String... args) throws IOException {
if (!Files.exists(root))
Files.createDirectory(root);
for (int i = 0; i < args.length; i += 2) {
String filename = args[i];
String content = args[i+1];
Path p = root.resolve(filename);
Files.createDirectories(p.getParent());
try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(p,
Charset.defaultCharset()))) {
out.println(content);
}
}
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8037085
* @summary Ensures that sjavac can handle various exclusion patterns.
* @run main ExclPatternWrapper
*/
public class ExclPatternWrapper {
public static void main(String... args) throws Exception {
SJavacTestUtil.runSjavacTest("ExclPattern", args);
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Iterator;
import com.sun.tools.sjavac.options.Options;
public class JavacOptionPrep {
enum TestPath {
CP1, CP2, SRC1, SRC2, SOURCEPATH1, SOURCEPATH2;
public String toString() {
return name().toLowerCase();
}
}
private final static String SEP = File.pathSeparator;
public static void main(String[] unused) throws IOException {
for (TestPath p : TestPath.values())
Files.createDirectory(Paths.get(p.toString()));
// Test some various cases:
// - Paths combined with File.pathSeparator (CP1 / CP2)
// - Paths given as duplicate options (SOURCEPATH1 / SOURCEPATH2)
// - Sources provided by -src (SRC1)
// - Sources provided without preceding option (SRC2)
// - An unrecognized option which is to be passed on to javac
String sjavacArgs = "-cp " + TestPath.CP1 + SEP + TestPath.CP2 +
" -d dest " +
" -h header" +
" -sourcepath " + TestPath.SOURCEPATH1 +
" -src " + TestPath.SRC1 +
" -s gensrc" +
" -sourcepath " + TestPath.SOURCEPATH2 +
" " + TestPath.SRC2 +
" -unrecognized";
Options options = Options.parseArgs(sjavacArgs.split(" "));
// Extract javac-options
String[] javacArgs = options.prepJavacArgs();
// Check the result
boolean destDirFound = false;
boolean headerDirFound = false;
boolean gensrcDirFound = false;
boolean classPathFound = false;
boolean sourcePathFound = false;
boolean unrecognizedFound = false;
boolean implicitNoneFound = false;
Iterator<String> javacArgIter = Arrays.asList(javacArgs).iterator();
while (javacArgIter.hasNext()) {
String option = javacArgIter.next();
switch (option) {
case "-classpath":
case "-cp":
classPathFound = true;
assertEquals(TestPath.CP1 + SEP + TestPath.CP2,
javacArgIter.next());
break;
case "-d":
destDirFound = true;
assertEquals(Paths.get("dest").toAbsolutePath().toString(),
javacArgIter.next());
break;
case "-h":
headerDirFound = true;
assertEquals(Paths.get("header").toAbsolutePath().toString(),
javacArgIter.next());
break;
case "-s":
gensrcDirFound = true;
assertEquals(Paths.get("gensrc").toAbsolutePath().toString(),
javacArgIter.next());
break;
case "-sourcepath":
sourcePathFound = true;
assertEquals(TestPath.SRC1 + SEP +
TestPath.SRC2 + SEP +
TestPath.SOURCEPATH1 + SEP +
TestPath.SOURCEPATH2,
javacArgIter.next());
break;
case "-unrecognized":
unrecognizedFound = true;
break;
case "-implicit:none":
implicitNoneFound = true;
break;
// Note that *which* files to actually compile is not dealt
// with by prepJavacArgs.
default:
throw new AssertionError("Unexpected option found: " + option);
}
}
if (!destDirFound)
throw new AssertionError("Dest directory not found.");
if (!headerDirFound)
throw new AssertionError("Header directory not found.");
if (!gensrcDirFound)
throw new AssertionError("Generated source directory not found.");
if (!classPathFound)
throw new AssertionError("Class path not found.");
if (!sourcePathFound)
throw new AssertionError("Source path not found.");
if (!unrecognizedFound)
throw new AssertionError("\"-unrecognized\" not found.");
if (!implicitNoneFound)
throw new AssertionError("\"-implicit:none\" not found.");
}
static void assertEquals(Object expected, Object actual) {
if (!expected.equals(actual))
throw new AssertionError("Expected " + expected + " but got " + actual);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8035063
* @summary Tests the preparation of javac-arguments.
* @run main JavacOptionPrepWrapper
*/
public class JavacOptionPrepWrapper {
public static void main(String... args) throws Exception {
SJavacTestUtil.runSjavacTest("JavacOptionPrep", args);
}
}

View file

@ -0,0 +1,240 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static util.OptionTestUtil.assertEquals;
import static util.OptionTestUtil.checkFilesFound;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sun.tools.sjavac.CopyFile;
import com.sun.tools.sjavac.Main;
import com.sun.tools.sjavac.Module;
import com.sun.tools.sjavac.Source;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation;
public class OptionDecoding {
public static void main(String[] args) throws IOException {
testPaths();
testDupPaths();
testSourceLocations();
testSimpleOptions();
testServerConf();
testSearchPaths();
testTranslationRules();
}
// Test decoding of output paths
static void testPaths() throws IOException {
final String H = "headers";
final String G = "gensrc";
final String D = "dest";
final String CMP = "srcRefList.txt";
Options options = Options.parseArgs("-h", H, "-s", G, "-d", D,
"--compare-found-sources", CMP);
assertEquals(Paths.get(H).toAbsolutePath(), options.getHeaderDir());
assertEquals(Paths.get(G).toAbsolutePath(), options.getGenSrcDir());
assertEquals(Paths.get(D).toAbsolutePath(), options.getDestDir());
assertEquals(Paths.get(CMP), options.getSourceReferenceList());
}
// Providing duplicate header / dest / gensrc paths should produce an error.
static void testDupPaths() throws IOException {
try {
Options.parseArgs("-h", "dir1", "-h", "dir2");
throw new RuntimeException("Duplicate header directories should fail.");
} catch (IllegalArgumentException iae) {
// Expected
}
try {
Options.parseArgs("-s", "dir1", "-s", "dir2");
throw new RuntimeException("Duplicate paths for generated sources should fail.");
} catch (IllegalArgumentException iae) {
// Expected
}
try {
Options.parseArgs("-d", "dir1", "-d", "dir2");
throw new RuntimeException("Duplicate destination directories should fail.");
} catch (IllegalArgumentException iae) {
// Expected
}
}
// Test source locations and -x, -i, -xf, -if filters
static void testSourceLocations() throws IOException {
Path a1 = Paths.get("root/pkg1/ClassA1.java");
Path a2 = Paths.get("root/pkg1/ClassA2.java");
Path b1 = Paths.get("root/pkg1/pkg2/ClassB1.java");
Path b2 = Paths.get("root/pkg1/pkg2/ClassB2.java");
Path c1 = Paths.get("root/pkg3/ClassC1.java");
Path c2 = Paths.get("root/pkg3/ClassC2.java");
for (Path p : Arrays.asList(a1, a2, b1, b2, c1, c2)) {
Files.createDirectories(p.getParent());
Files.createFile(p);
}
// Test -if
{
Options options = Options.parseArgs("-if", "root/pkg1/ClassA1.java", "root");
Map<String, Source> foundFiles = new HashMap<>();
Main.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
new HashMap<String, Module>(), new Module("", ""), false, true);
checkFilesFound(foundFiles.keySet(), a1);
}
// Test -i
System.out.println("--------------------------- CHECKING -i ----------------");
{
Options options = Options.parseArgs("-i", "pkg1/*", "root");
Map<String, Source> foundFiles = new HashMap<>();
Main.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
new HashMap<String, Module>(), new Module("", ""), false, true);
checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
}
System.out.println("--------------------------------------------------------");
// Test -xf
{
Options options = Options.parseArgs("-xf", "root/pkg1/ClassA1.java", "root");
Map<String, Source> foundFiles = new HashMap<>();
Main.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
new HashMap<String, Module>(), new Module("", ""), false, true);
checkFilesFound(foundFiles.keySet(), a2, b1, b2, c1, c2);
}
// Test -x
{
Options options = Options.parseArgs("-i", "pkg1/*", "root");
Map<String, Source> foundFiles = new HashMap<>();
Main.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
new HashMap<String, Module>(), new Module("", ""), false, true);
checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2);
}
// Test -x and -i
{
Options options = Options.parseArgs("-i", "pkg1/*", "-x", "pkg1/pkg2/*", "root");
Map<String, Source> foundFiles = new HashMap<>();
Main.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles,
new HashMap<String, Module>(), new Module("", ""), false, true);
checkFilesFound(foundFiles.keySet(), a1, a2);
}
}
// Test basic options
static void testSimpleOptions() {
Options options = Options.parseArgs("-j", "17", "--log=debug");
assertEquals(17, options.getNumCores());
assertEquals("debug", options.getLogLevel());
assertEquals(false, options.isDefaultPackagePermitted());
assertEquals(false, options.isUnidentifiedArtifactPermitted());
options = Options.parseArgs("--permit-unidentified-artifacts",
"--permit-sources-without-package");
assertEquals("info", options.getLogLevel());
assertEquals(true, options.isDefaultPackagePermitted());
assertEquals(true, options.isUnidentifiedArtifactPermitted());
}
// Test server configuration options
static void testServerConf() {
Options options = Options.parseArgs("--server:someServerConfiguration");
assertEquals("someServerConfiguration", options.getServerConf());
assertEquals(false, options.startServerFlag());
options = Options.parseArgs("--startserver:someServerConfiguration");
assertEquals("someServerConfiguration", options.getServerConf());
assertEquals(true, options.startServerFlag());
}
// Test input paths
static void testSearchPaths() {
List<String> i, x, iF, xF;
i = x = iF = xF = new ArrayList<>();
SourceLocation dir1 = new SourceLocation(Paths.get("dir1"), i, x, iF, xF);
SourceLocation dir2 = new SourceLocation(Paths.get("dir2"), i, x, iF, xF);
Options options = Options.parseArgs("-sourcepath", "dir1:dir2");
assertEquals(options.getSourceSearchPaths(), Arrays.asList(dir1, dir2));
options = Options.parseArgs("-modulepath", "dir1:dir2");
assertEquals(options.getModuleSearchPaths(), Arrays.asList(dir1, dir2));
options = Options.parseArgs("-classpath", "dir1:dir2");
assertEquals(options.getClassSearchPath(), Arrays.asList(dir1, dir2));
}
// Test -tr option
static void testTranslationRules() {
Class<?> cls = com.sun.tools.sjavac.CompileJavaPackages.class;
Options options = Options.parseArgs(
"-tr", ".exa=" + cls.getName(),
"-tr", ".exb=" + cls.getName(),
"-copy", ".html");
assertEquals(cls, options.getTranslationRules().get(".exa").getClass());
assertEquals(cls, options.getTranslationRules().get(".exb").getClass());
assertEquals(CopyFile.class, options.getTranslationRules().get(".html").getClass());
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8035063
* @summary Tests decoding of String[] into Options.
* @run main OptionDecodingWrapper
*/
public class OptionDecodingWrapper {
public static void main(String... args) throws Exception {
SJavacTestUtil.runSjavacTest("OptionDecoding", args);
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.lang.reflect.Method;
public class SJavacTestUtil {
public static void runSjavacTest(String testClassName, String[] args)
throws Exception {
if (!isSJavacOnClassPath()) {
System.out.println("sjavac not available: pass by default");
return;
}
File srcDir = new File(System.getProperty("test.src"));
File clsDir = new File(System.getProperty("test.classes"));
File src = new File(srcDir, testClassName + ".java");
File cls = new File(clsDir, testClassName + ".class");
if (cls.lastModified() < src.lastModified()) {
System.err.println("Recompiling test class...");
String[] javacArgs = { "-d", clsDir.getPath(), src.getPath() };
int rc = com.sun.tools.javac.Main.compile(javacArgs);
if (rc != 0)
throw new Exception("compilation failed");
}
Class<?> sjavac = Class.forName(testClassName);
Method main = sjavac.getMethod("main", String[].class);
main.invoke(null, new Object[] { args });
}
private static boolean isSJavacOnClassPath() {
String cls = "com/sun/tools/sjavac/Main.class";
return SJavacTestUtil.class.getClassLoader().getResource(cls) != null;
}
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,37 +31,8 @@
* @run main SJavacWrapper * @run main SJavacWrapper
*/ */
import java.io.*; public class SJavacWrapper {
import java.lang.reflect.Method;
import java.net.*;
public
class SJavacWrapper {
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
URL url = SJavacWrapper.class.getClassLoader().getResource("com/sun/tools/sjavac/Main.class"); SJavacTestUtil.runSjavacTest("SJavac", args);
if (url == null) {
// No sjavac in the classpath.
System.out.println("sjavac not available: pass by default");
return;
}
File testSrc = new File(System.getProperty("test.src"));
File sjavac_java = new File(testSrc, "SJavac.java");
File testClasses = new File(System.getProperty("test.classes"));
File sjavac_class = new File(testClasses, "SJavac.class");
if (sjavac_class.lastModified() < sjavac_java.lastModified()) {
String[] javac_args = { "-d", testClasses.getPath(), sjavac_java.getPath() };
System.err.println("Recompiling SJavac.java");
int rc = com.sun.tools.javac.Main.compile(javac_args);
if (rc != 0)
throw new Exception("compilation failed");
}
Class<?> sjavac = Class.forName("SJavac");
Method sjavac_main = sjavac.getMethod("main", String[].class);
sjavac_main.invoke(null, new Object[] { args });
} }
} }

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import static util.OptionTestUtil.assertEquals;
import java.io.IOException;
import java.util.Map;
import com.sun.tools.sjavac.CompileJavaPackages;
import com.sun.tools.sjavac.Transformer;
import com.sun.tools.sjavac.options.Option;
import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation;
public class Serialization {
public static void main(String[] args) throws IOException {
// Create reference options
Options options1 = Options.parseArgs(
Option.H.arg, "headers",
Option.S.arg, "gensrc",
Option.D.arg, "dest",
Option.I.arg, "pkg/*",
Option.X.arg, "pkg/pkg/*",
Option.IF.arg, "root/pkg/MyClass1.java",
Option.XF.arg, "root/pkg/MyClass2.java",
Option.SRC.arg, "root",
Option.SOURCEPATH.arg, "sourcepath",
Option.CLASSPATH.arg, "classpath",
Option.MODULEPATH.arg, "modulepath",
Option.PERMIT_SOURCES_WITHOUT_PACKAGE.arg,
Option.PERMIT_UNIDENTIFIED_ARTIFACTS.arg,
Option.TR.arg, ".prop=" + CompileJavaPackages.class.getName(),
Option.J.arg, "999",
"-someJavacArg",
"-someOtherJavacArg");
// Serialize
String serialized = options1.getStateArgsString();
// Deserialize
Options options2 = Options.parseArgs(serialized.split(" "));
// Make sure we got the same result
assertEquals(options1.getHeaderDir(), options2.getHeaderDir());
assertEquals(options1.getGenSrcDir(), options2.getGenSrcDir());
assertEquals(options1.getDestDir(), options2.getDestDir());
SourceLocation sl1 = options1.getSources().get(0);
SourceLocation sl2 = options2.getSources().get(0);
assertEquals(sl1.getPath(), sl2.getPath());
assertEquals(sl1.getIncludes(), sl2.getIncludes());
assertEquals(sl1.getExcludes(), sl2.getExcludes());
assertEquals(sl1.getIncludedFiles(), sl2.getIncludedFiles());
assertEquals(sl1.getExcludedFiles(), sl2.getExcludedFiles());
assertEquals(options1.getClassSearchPath(), options2.getClassSearchPath());
assertEquals(options1.getSourceSearchPaths(), options2.getSourceSearchPaths());
assertEquals(options1.getModuleSearchPaths(), options2.getModuleSearchPaths());
Map<String, Transformer> trRules1 = options1.getTranslationRules();
Map<String, Transformer> trRules2 = options2.getTranslationRules();
assertEquals(trRules1.keySet(), trRules2.keySet());
assertEquals(trRules1.values().iterator().next().getClass(),
trRules2.values().iterator().next().getClass());
assertEquals(options1.getJavacArgs(), options2.getJavacArgs());
assertEquals(999, options1.getNumCores());
if (options2.getNumCores() == 999)
throw new AssertionError("Num cores should not be part of serialization");
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8035063
*
* @summary Tests serialization of options. The options needs to be serialized
* and saved in the state file since the files need to be recompiled
* if new options are provided.
*
* @run main SerializationWrapper
*/
public class SerializationWrapper {
public static void main(String... args) throws Exception {
SJavacTestUtil.runSjavacTest("Serialization", args);
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package util;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import com.sun.tools.sjavac.options.SourceLocation;
public class OptionTestUtil {
public static void checkFilesFound(Collection<String> found, Path... expected) {
Collection<String> expectedStrs = new HashSet<String>();
for (Path p : expected)
expectedStrs.add(p.toString());
if (!expectedStrs.containsAll(found))
throw new AssertionError("Expected (" + expectedStrs + ") does not " +
"contain all actual (" + found + ")");
if (!found.containsAll(expectedStrs))
throw new AssertionError("Actual (" + found + ") does not " +
"contain all expected (" + expectedStrs + ")");
}
public static void assertEquals(List<SourceLocation> expected, List<SourceLocation> actual) {
if (expected.size() != actual.size())
throw new AssertionError("Expected locs of length " + expected.size() + " but got something of size " + actual.size());
Iterator<SourceLocation> iter1 = expected.iterator();
Iterator<SourceLocation> iter2 = actual.iterator();
while (iter1.hasNext()) {
SourceLocation sl1 = iter1.next();
SourceLocation sl2 = iter2.next();
if (!sl1.getPath().equals(sl2.getPath()) ||
!sl1.getIncludes().equals(sl2.getIncludes()) ||
!sl1.getExcludes().equals(sl2.getExcludes()) ||
!sl1.getIncludedFiles().equals(sl2.getIncludedFiles()) ||
!sl1.getExcludedFiles().equals(sl2.getExcludedFiles()))
throw new AssertionError("Expected " + sl1 + " but got " + sl2);
}
}
public static void assertEquals(Object expected, Object actual) {
if (!expected.equals(actual))
throw new AssertionError("Expected " + expected + " but got " + actual);
}
}