From cd9339243cfa6f3b4cb9db4ea17dcb6ad5af827c Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Thu, 1 Mar 2018 20:35:53 +0100 Subject: [PATCH 01/20] Fixed verification with exports --- src/main/java/pro/javacard/ant/JavaCard.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index ed6e63a..4528997 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -686,8 +686,11 @@ public void execute() { } // Copy output - Files.copy(exp, exp_path.resolve(exp.getFileName()), StandardCopyOption.REPLACE_EXISTING); - log("EXP saved to " + exp_path.resolve(exp.getFileName()), Project.MSG_INFO); + java.nio.file.Path exp_file = exp_path.resolve(exp.getFileName()); + Files.copy(exp, exp_file, StandardCopyOption.REPLACE_EXISTING); + log("EXP saved to " + exp_file, Project.MSG_INFO); + exps.add(exp_file.toString()); + // Make Jar for the export Jar jarz = new Jar(); jarz.setProject(getProject()); From 03cf8dcdbb6c7bc932b95eaba16d225d115b0ec4 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Thu, 1 Mar 2018 20:52:54 +0100 Subject: [PATCH 02/20] Separated JAR generation from EXP generation Generate a JAR that contains all intermediates for later reference. --- src/main/java/pro/javacard/ant/JavaCard.java | 30 ++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 4528997..03a843b 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -28,6 +28,7 @@ import org.apache.tools.ant.taskdefs.Java; import org.apache.tools.ant.taskdefs.Javac; import org.apache.tools.ant.types.Environment.Variable; +import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import java.io.File; @@ -265,6 +266,7 @@ public class JCCap extends Task { private Vector raw_imports = new Vector<>(); private String output_cap = null; private String output_exp = null; + private String output_jar = null; private String output_jca = null; private String jckit_path = null; private boolean verify = true; @@ -287,6 +289,10 @@ public void setExport(String msg) { output_exp = msg; } + public void setJar(String msg) { + output_jar = msg; + } + public void setJca(String msg) { output_jca = msg; } @@ -644,7 +650,7 @@ public void execute() { j.execute(); // Copy results - if (output_cap != null || output_exp != null || output_jca != null) { + if (output_cap != null || output_exp != null || output_jca != null || output_jar != null) { // Last component of the package String ln = package_name; if (ln.lastIndexOf(".") != -1) { @@ -691,13 +697,27 @@ public void execute() { log("EXP saved to " + exp_file, Project.MSG_INFO); exps.add(exp_file.toString()); - // Make Jar for the export + } + // Make JAR + if (output_jar != null) { + setTaskName("jar"); + File outJar = getProject().resolveFile(output_jar); + // create a new JAR task Jar jarz = new Jar(); jarz.setProject(getProject()); - jarz.setTaskName("export"); - jarz.setBasedir(getProject().resolveFile(classes_path)); - jarz.setDestFile(opf.toPath().resolve(ln + ".jar").toFile()); + jarz.setTaskName("jar"); + jarz.setDestFile(outJar); + // include class files + FileSet jarcls = new FileSet(); + jarcls.setDir(getProject().resolveFile(classes_path)); + jarz.add(jarcls); + // include conversion output + FileSet jarout = new FileSet(); + jarout.setDir(applet_folder); + jarz.add(jarout); + // create the JAR jarz.execute(); + log("JAR created at " + outJar.getAbsolutePath(), Project.MSG_INFO); } // Copy JCA if (output_jca != null) { From a46b99a2112e00bde545cf34cd5b1626271b2437 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Sat, 3 Mar 2018 03:14:42 +0100 Subject: [PATCH 03/20] Reworked SDK detection and handling --- src/main/java/pro/javacard/ant/JCKit.java | 146 ++++++++++++++ src/main/java/pro/javacard/ant/JavaCard.java | 190 ++++--------------- 2 files changed, 183 insertions(+), 153 deletions(-) create mode 100644 src/main/java/pro/javacard/ant/JCKit.java diff --git a/src/main/java/pro/javacard/ant/JCKit.java b/src/main/java/pro/javacard/ant/JCKit.java new file mode 100644 index 0000000..798c938 --- /dev/null +++ b/src/main/java/pro/javacard/ant/JCKit.java @@ -0,0 +1,146 @@ +package pro.javacard.ant; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class JCKit { + + public static JCKit detectSDK(String path) { + if (path == null || path.trim() == "") { + return null; + } + + File root = new File(path); + if(!root.isDirectory()) { + return null; + } + + Version version = detectSDKVersion(root); + if(version == null) { + return null; + } + + return new JCKit(root, version); + } + + private static Version detectSDKVersion(File root) { + Version version = null; + File libDir = new File(root, "lib"); + if (new File(libDir, "tools.jar").exists()) { + version = JCKit.Version.V3; + } else if (new File(libDir, "api21.jar").exists()) { + version = JCKit.Version.V21; + } else if (new File(libDir, "converter.jar").exists()) { + // assume 2.2.1 first + version = Version.V221; + // test for 2.2.2 by testing api.jar + File api = new File(libDir, "api.jar"); + try { + ZipFile apiZip = new ZipFile(api); + ZipEntry testEntry = apiZip.getEntry("javacardx/apdu/ExtendedLength.class"); + if(testEntry != null) { + version = JCKit.Version.V222; + } + } catch (IOException ignored) { + // do not ignore this, escalate it + throw new RuntimeException(ignored); + } + } + return version; + } + + private Version version = Version.NONE; + private File path = null; + + public JCKit(File root, Version version) { + this.path = root; + this.version = version; + } + + public File getRoot() { + return path; + } + + public Version getVersion() { + return version; + } + + public boolean isVersion(Version v) { + return version.equals(v); + } + + public String getJavaVersion() { + switch(version) { + case V3: + return "1.5"; + case V222: + return "1.3"; + case V221: + return "1.2"; + case V21: + default: + return "1.1"; + } + } + + public File getJar(String name) { + File libDir = new File(path, "lib"); + return new File(libDir, name); + } + + public File getApiJar() { + switch (version) { + case V21: + return getJar("api21.jar"); + case V3: + return getJar("api_classic.jar"); + default: + return getJar("api.jar"); + } + } + + public File getExportDir() { + switch (version) { + case V21: + return new File(path, "api21_export_files"); + default: + return new File(path, "api_export_files"); + } + } + + public List getToolJars() { + List jars = new ArrayList<>(); + switch (version) { + case V3: + jars.add(getJar("tools.jar")); + break; + default: + jars.add(getJar("converter.jar")); + jars.add(getJar("offcardverifier.jar")); + break; + } + return jars; + } + + enum Version { + NONE, V21, V221, V222, V3; + + @Override + public String toString() { + if (this.equals(V3)) + return "v3.x"; + if (this.equals(V222)) + return "v2.2.2"; + if (this.equals(V221)) + return "v2.2.1"; + if (this.equals(V21)) + return "v2.1.x"; + return "unknown"; + } + } + +} diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 03a843b..4975cb2 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -32,13 +32,10 @@ import org.apache.tools.ant.types.Path; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; public class JavaCard extends Task { // This code has been taken from Apache commons-codec 1.7 (License: Apache @@ -135,61 +132,6 @@ public void setJCKit(String msg) { master_jckit_path = msg; } - /** - * Given a path, return a meta-info object about possible JavaCard SDK in that path. - * - * @param path raw string as present in build.xml or environment, or null - * @return a {@link JavaCardKit} instance - */ - public JavaCardKit detectSDK(String path) { - JavaCardKit detected = new JavaCardKit(); - if (path == null || path.trim() == "") { - return detected; - } - // Expand user - String real_path = path.replaceFirst("^~", System.getProperty("user.home")); - // Check if path is OK - if (!new File(real_path).exists()) { - log("JavaCard SDK folder " + path + " does not exist!", Project.MSG_WARN); - return detected; - } - detected.path = real_path; - // Identify jckit type - if (Paths.get(detected.path, "lib", "tools.jar").toFile().exists()) { - log("JavaCard 3.x SDK detected in " + detected.path, Project.MSG_VERBOSE); - detected.version = JC.V3; - } else if (Paths.get(detected.path, "lib", "api21.jar").toFile().exists()) { - detected.version = JC.V212; - log("JavaCard 2.1.x SDK detected in " + detected.path, Project.MSG_VERBOSE); - } else if (Paths.get(detected.path, "lib", "converter.jar").toFile().exists()) { - // Detect if 2.2.1 or 2.2.2 - File api = Paths.get(detected.path, "lib", "api.jar").toFile(); - try (ZipInputStream zip = new ZipInputStream(new FileInputStream(api))) { - while (true) { - ZipEntry entry = zip.getNextEntry(); - if (entry == null) { - break; - } - if (entry.getName().equals("javacardx/apdu/ExtendedLength.class")) { - detected.version = JC.V222; - log("JavaCard 2.2.2 SDK detected in " + detected.path, Project.MSG_VERBOSE); - } - } - } catch (IOException e) { - log("Could not parse api.jar", Project.MSG_DEBUG); - } finally { - // Assume older SDK if jar parsing fails. - if (detected.version == JC.NONE) { - detected.version = JC.V221; - log("JavaCard 2.x SDK detected in " + detected.path, Project.MSG_VERBOSE); - } - } - } else { - log("Could not detect a JavaCard SDK in " + Paths.get(path).toAbsolutePath(), Project.MSG_WARN); - } - return detected; - } - public JCCap createCap() { JCCap pkg = new JCCap(); packages.add(pkg); @@ -203,28 +145,6 @@ public void execute() { } } - private enum JC { - NONE, V212, V221, V222, V3; - - @Override - public String toString() { - if (this.equals(V3)) - return "v3.x"; - if (this.equals(V222)) - return "v2.2.2"; - if (this.equals(V221)) - return "v2.2.1"; - if (this.equals(V212)) - return "v2.1.x"; - return "unknown"; - } - } - - private static class JavaCardKit { - JC version = JC.NONE; - String path = null; - } - public static class JCApplet { private String klass = null; private byte[] aid = null; @@ -256,7 +176,7 @@ public HelpingBuildException(String msg) { } public class JCCap extends Task { - private JavaCardKit jckit = null; + private JCKit jckit = null; private String classes_path = null; private String sources_path = null; private String package_name = null; @@ -359,41 +279,37 @@ public JCImport createJimport() { return this.createImport(); } - // Check that arguments are sufficient and do some DWIM - private void check() { - JavaCardKit env = detectSDK(System.getenv("JC_HOME")); - JavaCardKit prop = detectSDK(getProject().getProperty("jc.home")); - JavaCardKit master = detectSDK(master_jckit_path); - JavaCardKit current = detectSDK(jckit_path); - - if (current.version == JC.NONE && master.version == JC.NONE && env.version == JC.NONE && prop.version == JC.NONE) { - throw new HelpingBuildException("Must specify usable JavaCard SDK path in build.xml or set JC_HOME or jc.home"); + private JCKit findSDK() { + // try configuration first + if(jckit_path != null) { + return JCKit.detectSDK(jckit_path); } - - - if (current.version == JC.NONE) { - // if master path is specified but is not usable, - // override with environment, variable, if usable - if (prop.version != JC.NONE) { - jckit = prop; - } else if (master.version == JC.NONE && env.version != JC.NONE) { - jckit = env; - } else { - jckit = master; - } - } else { - if (prop.version != JC.NONE) { - jckit = prop; - } else { - jckit = current; - } + if(master_jckit_path != null) { + return JCKit.detectSDK(master_jckit_path); + } + // now check via ant property + String propPath = getProject().getProperty("jc.home"); + if(propPath != null) { + return JCKit.detectSDK(propPath); + } + // finally via the environment + String envPath = System.getenv("JC_HOME"); + if(envPath != null) { + return JCKit.detectSDK(envPath); } + // return null if no options + return null; + } + + // Check that arguments are sufficient and do some DWIM + private void check() { + jckit = findSDK(); // Sanity check - if (jckit == null || jckit.version == JC.NONE) { + if (jckit == null) { throw new HelpingBuildException("No usable JavaCard SDK referenced"); } else { - log("INFO: using JavaCard " + jckit.version + " SDK in " + jckit.path, Project.MSG_INFO); + log("INFO: using JavaCard " + jckit.getVersion() + " SDK in " + jckit.getRoot(), Project.MSG_INFO); } // sources or classes must be set @@ -497,18 +413,13 @@ private void compile() { j.setDestdir(tmp); // See "Setting Java Compiler Options" in User Guide j.setDebug(true); - if (jckit.version == JC.V212) { - j.setTarget("1.1"); - j.setSource("1.1"); + String javaVersion = jckit.getJavaVersion(); + j.setTarget(javaVersion); + j.setSource(javaVersion); + if (jckit.isVersion(JCKit.Version.V21)) { // Always set debug to disable "contains local variables, // but not local variable table." messages j.setDebug(true); - } else if (jckit.version == JC.V221) { - j.setTarget("1.2"); - j.setSource("1.2"); - } else { - j.setTarget("1.5"); - j.setSource("1.5"); } j.setIncludeantruntime(false); j.createCompilerArg().setValue("-Xlint"); @@ -520,14 +431,7 @@ private void compile() { // set classpath Path cp = j.createClasspath(); - String api = null; - if (jckit.version == JC.V3) { - api = Paths.get(jckit.path, "lib", "api_classic.jar").toAbsolutePath().toString(); - } else if (jckit.version == JC.V212) { // V2.1.X - api = Paths.get(jckit.path, "lib", "api21.jar").toAbsolutePath().toString(); - } else { // V2.2.X - api = Paths.get(jckit.path, "lib", "api.jar").toAbsolutePath().toString(); - } + String api = jckit.getApiJar().toString(); cp.append(new Path(getProject(), api)); for (JCImport i : raw_imports) { // Support import clauses with only jar or exp values @@ -552,23 +456,8 @@ public void execute() { Java j = new Java(this); // classpath to jckit bits Path cp = j.createClasspath(); - // converter - File jar = null; - if (jckit.version == JC.V3) { - jar = Paths.get(jckit.path, "lib", "tools.jar").toFile(); - Path jarpath = new Path(getProject()); - jarpath.setLocation(jar); - cp.append(jarpath); - } else { - // XXX: this should be with less lines ? - jar = Paths.get(jckit.path, "lib", "converter.jar").toFile(); - Path jarpath = new Path(getProject()); - jarpath.setLocation(jar); - cp.append(jarpath); - jar = Paths.get(jckit.path, "lib", "offcardverifier.jar").toFile(); - jarpath = new Path(getProject()); - jarpath.setLocation(jar); - cp.append(jarpath); + for(File jar: jckit.getToolJars()) { + cp.append(new Path(getProject(), jar.getPath())); } // Create temporary folder and add to cleanup @@ -580,12 +469,7 @@ public void execute() { // Construct exportpath ArrayList exps = new ArrayList<>(); - // JC kit - if (jckit.version == JC.V212) { - exps.add(Paths.get(jckit.path, "api21_export_files").toString()); - } else { - exps.add(Paths.get(jckit.path, "api_export_files").toString()); - } + exps.add(jckit.getExportDir().toString()); // add imports for (JCImport imp : raw_imports) { @@ -612,7 +496,7 @@ public void execute() { if (!verify) { j.createArg().setLine("-noverify"); } - if (jckit.version == JC.V3) { + if (jckit.isVersion(JCKit.Version.V3)) { j.createArg().setLine("-useproxyclass"); } if (ints) { @@ -633,12 +517,12 @@ public void execute() { j.createArg().setLine(package_name + " " + hexAID(package_aid) + " " + package_version); // Call converter - if (jckit.version == JC.V3) { + if (jckit.isVersion(JCKit.Version.V3)) { j.setClassname("com.sun.javacard.converter.Main"); // XXX: See https://community.oracle.com/message/10452555 Variable jchome = new Variable(); jchome.setKey("jc.home"); - jchome.setValue(jckit.path); + jchome.setValue(jckit.getRoot().toString()); j.addSysproperty(jchome); } else { j.setClassname("com.sun.javacard.converter.Converter"); From a828fd2cb4488a1290ede32c63b9652c61b477bb Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 16:12:00 +0100 Subject: [PATCH 04/20] Allow overriding the java version This is to allow compiling with certain features enabled even on JC platforms that do not support those features. Among those features is using annotations. --- src/main/java/pro/javacard/ant/JavaCard.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 4975cb2..ae2808e 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -42,6 +42,7 @@ public class JavaCard extends Task { // 2.0) private static final char[] LOWER_HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; private String master_jckit_path = null; + private String master_java_version = null; private Vector packages = new Vector<>(); private static String hexAID(byte[] aid) { @@ -132,6 +133,10 @@ public void setJCKit(String msg) { master_jckit_path = msg; } + public void setJavaVersion(String msg) { + master_java_version = msg; + } + public JCCap createCap() { JCCap pkg = new JCCap(); packages.add(pkg); @@ -189,6 +194,7 @@ public class JCCap extends Task { private String output_jar = null; private String output_jca = null; private String jckit_path = null; + private String java_version = null; private boolean verify = true; private boolean debug = false; private boolean ints = false; @@ -201,6 +207,10 @@ public void setJCKit(String msg) { jckit_path = msg; } + public void setJavaVersion(String msg) { + java_version = msg; + } + public void setOutput(String msg) { output_cap = msg; } @@ -414,6 +424,13 @@ private void compile() { // See "Setting Java Compiler Options" in User Guide j.setDebug(true); String javaVersion = jckit.getJavaVersion(); + if(java_version != null) { + javaVersion = java_version; + } else { + if(master_java_version != null) { + javaVersion = master_java_version; + } + } j.setTarget(javaVersion); j.setSource(javaVersion); if (jckit.isVersion(JCKit.Version.V21)) { From ed292178e73b5b85e1ac3c19aab2fad360167b28 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 16:42:08 +0100 Subject: [PATCH 05/20] Removed command logging: ant does that --- src/main/java/pro/javacard/ant/JavaCard.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index ae2808e..bafc5a4 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -547,7 +547,6 @@ public void execute() { j.setFailonerror(true); j.setFork(true); - log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); j.execute(); // Copy results @@ -672,7 +671,6 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at j.setFailonerror(true); j.setFork(true); - log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); j.execute(); } } finally { From bbe571149cbb915f62d0f6e8a118b06bbf0c63c2 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:01:26 +0100 Subject: [PATCH 06/20] Replaced references to getProject() with a variable Makes for better readability. --- src/main/java/pro/javacard/ant/JavaCard.java | 30 +++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index bafc5a4..c24a7bb 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -399,15 +399,17 @@ private void check() { } private void compile() { + Project project = getProject(); + Javac j = new Javac(); - j.setProject(getProject()); + j.setProject(project); j.setTaskName("compile"); - j.setSrcdir(new Path(getProject(), sources_path)); + j.setSrcdir(new Path(project, sources_path)); File tmp; if (classes_path != null) { - tmp = getProject().resolveFile(classes_path); + tmp = project.resolveFile(classes_path); if (!tmp.exists()) { if (!tmp.mkdir()) throw new BuildException("Could not create temporary folder " + tmp.getAbsolutePath()); @@ -449,11 +451,11 @@ private void compile() { // set classpath Path cp = j.createClasspath(); String api = jckit.getApiJar().toString(); - cp.append(new Path(getProject(), api)); + cp.append(new Path(project, api)); for (JCImport i : raw_imports) { // Support import clauses with only jar or exp values if (i.jar != null) { - cp.append(new Path(getProject(), i.jar)); + cp.append(new Path(project, i.jar)); } } j.execute(); @@ -461,6 +463,8 @@ private void compile() { @Override public void execute() { + Project project = getProject(); + // Convert check(); @@ -474,7 +478,7 @@ public void execute() { // classpath to jckit bits Path cp = j.createClasspath(); for(File jar: jckit.getToolJars()) { - cp.append(new Path(getProject(), jar.getPath())); + cp.append(new Path(project, jar.getPath())); } // Create temporary folder and add to cleanup @@ -568,7 +572,7 @@ public void execute() { throw new BuildException("Can not find CAP in " + jcsrc); } // Resolve output file - File opf = getProject().resolveFile(output_cap); + File opf = project.resolveFile(output_cap); // Copy CAP Files.copy(cap, opf.toPath(), StandardCopyOption.REPLACE_EXISTING); log("CAP saved to " + opf.getAbsolutePath(), Project.MSG_INFO); @@ -579,7 +583,7 @@ public void execute() { throw new BuildException("Can not find EXP in " + jcsrc); } // output_exp is the folder name - opf = getProject().resolveFile(output_exp); + opf = project.resolveFile(output_exp); // Get the folder under the output folder java.nio.file.Path exp_path = opf.toPath().resolve(package_name.replace(".", File.separator)).resolve("javacard"); @@ -601,15 +605,15 @@ public void execute() { // Make JAR if (output_jar != null) { setTaskName("jar"); - File outJar = getProject().resolveFile(output_jar); + File outJar = project.resolveFile(output_jar); // create a new JAR task Jar jarz = new Jar(); - jarz.setProject(getProject()); + jarz.setProject(project); jarz.setTaskName("jar"); jarz.setDestFile(outJar); // include class files FileSet jarcls = new FileSet(); - jarcls.setDir(getProject().resolveFile(classes_path)); + jarcls.setDir(project.resolveFile(classes_path)); jarz.add(jarcls); // include conversion output FileSet jarout = new FileSet(); @@ -625,7 +629,7 @@ public void execute() { if (!jca.toFile().exists()) { throw new BuildException("Can not find JCA in " + jcsrc); } - opf = getProject().resolveFile(output_jca); + opf = project.resolveFile(output_jca); Files.copy(jca, opf.toPath(), StandardCopyOption.REPLACE_EXISTING); log("JCA saved to " + opf.getAbsolutePath(), Project.MSG_INFO); } @@ -667,7 +671,7 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at for (String exp : expfiles) { j.createArg().setLine("'" + exp + "'"); } - j.createArg().setLine("'" + getProject().resolveFile(output_cap).toString() + "'"); + j.createArg().setLine("'" + project.resolveFile(output_cap).toString() + "'"); j.setFailonerror(true); j.setFork(true); From 12f43f48d09ec6f223c5f87eaa48b24dad5196bb Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 14:09:41 +0100 Subject: [PATCH 07/20] Simplified temporary directory handling --- src/main/java/pro/javacard/ant/JavaCard.java | 39 +++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index c24a7bb..1fbff3f 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -56,15 +56,6 @@ private static String hexAID(byte[] aid) { return hex.substring(0, hex.length() - 1); } - private static java.nio.file.Path mktemp() { - try { - java.nio.file.Path p = Files.createTempDirectory("jccpro"); - return p; - } catch (IOException e) { - throw new RuntimeException("Can not make temporary folder", e); - } - } - private static void rmminusrf(java.nio.file.Path path) { try { Files.walkFileTree(path, new SimpleFileVisitor() { @@ -416,8 +407,7 @@ private void compile() { } } else { // Generate temporary folder - java.nio.file.Path p = mktemp(); - temporary.add(p); + java.nio.file.Path p = makeTemp(); tmp = p.toFile(); classes_path = tmp.getAbsolutePath(); } @@ -482,8 +472,7 @@ public void execute() { } // Create temporary folder and add to cleanup - java.nio.file.Path p = mktemp(); - temporary.add(p); + java.nio.file.Path p = makeTemp(); File applet_folder = p.toFile(); j.createArg().setLine("-classdir '" + classes_path + "'"); j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); @@ -678,11 +667,25 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at j.execute(); } } finally { - // Clean temporary files. - for (java.nio.file.Path p : temporary) { - if (p.toFile().exists()) { - rmminusrf(p); - } + cleanTemp(); + } + } + + private java.nio.file.Path makeTemp() { + try { + java.nio.file.Path p = Files.createTempDirectory("jccpro"); + temporary.add(p); + return p; + } catch (IOException e) { + throw new RuntimeException("Can not make temporary folder", e); + } + } + + private void cleanTemp() { + // Clean temporary files. + for (java.nio.file.Path p : temporary) { + if (p.toFile().exists()) { + rmminusrf(p); } } } From f0fb1d36b3c9833cf2be0ab39cdb02ec21b2b32c Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 14:55:19 +0100 Subject: [PATCH 08/20] Switch from Path to File: temporary directories --- src/main/java/pro/javacard/ant/JavaCard.java | 21 ++++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 1fbff3f..006ab97 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -189,7 +189,7 @@ public class JCCap extends Task { private boolean verify = true; private boolean debug = false; private boolean ints = false; - private List temporary = new ArrayList<>(); + private List temporary = new ArrayList<>(); public JCCap() { } @@ -407,8 +407,7 @@ private void compile() { } } else { // Generate temporary folder - java.nio.file.Path p = makeTemp(); - tmp = p.toFile(); + tmp = makeTemp(); classes_path = tmp.getAbsolutePath(); } @@ -472,8 +471,7 @@ public void execute() { } // Create temporary folder and add to cleanup - java.nio.file.Path p = makeTemp(); - File applet_folder = p.toFile(); + File applet_folder = makeTemp(); j.createArg().setLine("-classdir '" + classes_path + "'"); j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); @@ -671,11 +669,12 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at } } - private java.nio.file.Path makeTemp() { + private File makeTemp() { try { java.nio.file.Path p = Files.createTempDirectory("jccpro"); - temporary.add(p); - return p; + File fp = p.toFile(); + temporary.add(fp); + return fp; } catch (IOException e) { throw new RuntimeException("Can not make temporary folder", e); } @@ -683,9 +682,9 @@ private java.nio.file.Path makeTemp() { private void cleanTemp() { // Clean temporary files. - for (java.nio.file.Path p : temporary) { - if (p.toFile().exists()) { - rmminusrf(p); + for (File f : temporary) { + if (f.exists()) { + rmminusrf(f.toPath()); } } } From cee934a54d150111c4d8318e00b3afd4674fb711 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:21:12 +0100 Subject: [PATCH 09/20] Switch from Path to File: build functions --- src/main/java/pro/javacard/ant/JavaCard.java | 32 +++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 006ab97..65a9806 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -547,44 +547,46 @@ public void execute() { if (ln.lastIndexOf(".") != -1) { ln = ln.substring(ln.lastIndexOf(".") + 1); } - // JavaCard folder - java.nio.file.Path jcsrc = applet_folder.toPath().resolve(package_name.replace(".", File.separator)).resolve("javacard"); + // directory of package + String pkgPath = package_name.replace(".", File.separator); + File pkgDir = new File(applet_folder, pkgPath); + File jcsrc = new File(pkgDir, "javacard"); // Interesting paths inside the JC folder - java.nio.file.Path cap = jcsrc.resolve(ln + ".cap"); - java.nio.file.Path exp = jcsrc.resolve(ln + ".exp"); - java.nio.file.Path jca = jcsrc.resolve(ln + ".jca"); + File cap = new File(jcsrc, ln + ".cap"); + File exp = new File(jcsrc, ln + ".exp"); + File jca = new File(jcsrc, ln + ".jca"); try { - if (!cap.toFile().exists()) { + if (!cap.exists()) { throw new BuildException("Can not find CAP in " + jcsrc); } // Resolve output file File opf = project.resolveFile(output_cap); // Copy CAP - Files.copy(cap, opf.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.copy(cap.toPath(), opf.toPath(), StandardCopyOption.REPLACE_EXISTING); log("CAP saved to " + opf.getAbsolutePath(), Project.MSG_INFO); // Copy exp file if (output_exp != null) { setTaskName("export"); - if (!exp.toFile().exists()) { + if (!exp.exists()) { throw new BuildException("Can not find EXP in " + jcsrc); } // output_exp is the folder name opf = project.resolveFile(output_exp); // Get the folder under the output folder - java.nio.file.Path exp_path = opf.toPath().resolve(package_name.replace(".", File.separator)).resolve("javacard"); + File exp_path = new File(opf.toString(), pkgPath); // Create the output folder - if (!exp_path.toFile().exists()) { - if (!exp_path.toFile().mkdirs()) { + if (!exp_path.exists()) { + if (!exp_path.mkdirs()) { throw new HelpingBuildException("Can not make path for EXP output: " + opf.getAbsolutePath()); } } // Copy output - java.nio.file.Path exp_file = exp_path.resolve(exp.getFileName()); - Files.copy(exp, exp_file, StandardCopyOption.REPLACE_EXISTING); + File exp_file = new File(exp_path, exp.getName()); + Files.copy(exp.toPath(), exp_file.toPath(), StandardCopyOption.REPLACE_EXISTING); log("EXP saved to " + exp_file, Project.MSG_INFO); exps.add(exp_file.toString()); @@ -613,11 +615,11 @@ public void execute() { // Copy JCA if (output_jca != null) { setTaskName("jca"); - if (!jca.toFile().exists()) { + if (!jca.exists()) { throw new BuildException("Can not find JCA in " + jcsrc); } opf = project.resolveFile(output_jca); - Files.copy(jca, opf.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.copy(jca.toPath(), opf.toPath(), StandardCopyOption.REPLACE_EXISTING); log("JCA saved to " + opf.getAbsolutePath(), Project.MSG_INFO); } } catch (IOException e) { From fc0f1bf255d351d2e34c1a70d687f9de5109dc36 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:43:58 +0100 Subject: [PATCH 10/20] Switch from Path to File: change export handling to use File --- src/main/java/pro/javacard/ant/JavaCard.java | 24 +++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 65a9806..32d1a60 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -476,23 +476,24 @@ public void execute() { j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); // Construct exportpath - ArrayList exps = new ArrayList<>(); - exps.add(jckit.getExportDir().toString()); + ArrayList exps = new ArrayList<>(); + exps.add(jckit.getExportDir()); // add imports for (JCImport imp : raw_imports) { // Support import clauses with only jar or exp values if (imp.exps != null) { - String s = Paths.get(imp.exps).toAbsolutePath().toString(); + File f = new File(imp.exps).getAbsoluteFile(); // Avoid duplicates - if (!exps.contains(s)) - exps.add(s); + if (!exps.contains(f)) { + exps.add(f); + } } } StringJoiner expstringbuilder = new StringJoiner(File.pathSeparator); - for (String imp : exps) { - expstringbuilder.add(imp); + for (File imp : exps) { + expstringbuilder.add(imp.toString()); } j.createArg().setLine("-exportpath '" + expstringbuilder.toString() + "'"); @@ -575,7 +576,8 @@ public void execute() { opf = project.resolveFile(output_exp); // Get the folder under the output folder - File exp_path = new File(opf.toString(), pkgPath); + File exp_pkg_path = new File(opf.toString(), pkgPath); + File exp_path = new File(exp_pkg_path, "javacard"); // Create the output folder if (!exp_path.exists()) { @@ -588,7 +590,7 @@ public void execute() { File exp_file = new File(exp_path, exp.getName()); Files.copy(exp.toPath(), exp_file.toPath(), StandardCopyOption.REPLACE_EXISTING); log("EXP saved to " + exp_file, Project.MSG_INFO); - exps.add(exp_file.toString()); + exps.add(opf); } // Make JAR @@ -637,8 +639,8 @@ public void execute() { // Find all expfiles final ArrayList expfiles = new ArrayList<>(); try { - for (String e : exps) { - Files.walkFileTree(Paths.get(e), new SimpleFileVisitor() { + for (File e : exps) { + Files.walkFileTree(e.toPath(), new SimpleFileVisitor() { @Override public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException { From e3f2047b989bd6499b62284651e02ec0b09f1e7f Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:24:28 +0100 Subject: [PATCH 11/20] Extracted verify to its own method --- src/main/java/pro/javacard/ant/JavaCard.java | 78 +++++++++++--------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 32d1a60..25c302e 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -450,6 +450,47 @@ private void compile() { j.execute(); } + private void verify(Path cp, List exps) { + Project project = getProject(); + setTaskName("verify"); + // construct the Java task that executes converter + Java j = new Java(this); + j.setClasspath(cp); + j.setClassname("com.sun.javacard.offcardverifier.Verifier"); + // Find all expfiles + final ArrayList expfiles = new ArrayList<>(); + try { + for (File e : exps) { + Files.walkFileTree(e.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) + throws IOException { + if (file.toString().endsWith(".exp")) { + expfiles.add(file.toAbsolutePath().toString()); + } + return FileVisitResult.CONTINUE; + } + }); + } + } catch (IOException e) { + log("Could not find .exp files: " + e.getMessage(), Project.MSG_ERR); + return; + } + + // Arguments to verifier + j.createArg().setLine("-nobanner"); + //TODO j.createArg().setLine("-verbose"); + for (String exp : expfiles) { + j.createArg().setLine("'" + exp + "'"); + } + j.createArg().setLine("'" + project.resolveFile(output_cap).toString() + "'"); + j.setFailonerror(true); + j.setFork(true); + + log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); + j.execute(); + } + @Override public void execute() { Project project = getProject(); @@ -631,42 +672,7 @@ public void execute() { } if (verify) { - setTaskName("verify"); - // construct the Java task that executes converter - j = new Java(this); - j.setClasspath(cp); - j.setClassname("com.sun.javacard.offcardverifier.Verifier"); - // Find all expfiles - final ArrayList expfiles = new ArrayList<>(); - try { - for (File e : exps) { - Files.walkFileTree(e.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) - throws IOException { - if (file.toString().endsWith(".exp")) { - expfiles.add(file.toAbsolutePath().toString()); - } - return FileVisitResult.CONTINUE; - } - }); - } - } catch (IOException e) { - log("Could not find .exp files: " + e.getMessage(), Project.MSG_ERR); - return; - } - - // Arguments to verifier - j.createArg().setLine("-nobanner"); - //TODO j.createArg().setLine("-verbose"); - for (String exp : expfiles) { - j.createArg().setLine("'" + exp + "'"); - } - j.createArg().setLine("'" + project.resolveFile(output_cap).toString() + "'"); - j.setFailonerror(true); - j.setFork(true); - - j.execute(); + verify(cp, exps); } } finally { cleanTemp(); From 273a0e1d76943de0e7043d73e0157365872aa872 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:35:42 +0100 Subject: [PATCH 12/20] Extracted method for tool classpath --- src/main/java/pro/javacard/ant/JavaCard.java | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 25c302e..225f98e 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -450,12 +450,22 @@ private void compile() { j.execute(); } - private void verify(Path cp, List exps) { + private void addKitClasses(Java j) { Project project = getProject(); + // classpath to jckit bits + Path cp = j.createClasspath(); + for(File jar: jckit.getToolJars()) { + cp.append(new Path(project, jar.getPath())); + } + j.setClasspath(cp); + } + + private void verify(List exps) { + Project project = getProject(); setTaskName("verify"); // construct the Java task that executes converter Java j = new Java(this); - j.setClasspath(cp); + addKitClasses(j); j.setClassname("com.sun.javacard.offcardverifier.Verifier"); // Find all expfiles final ArrayList expfiles = new ArrayList<>(); @@ -505,11 +515,7 @@ public void execute() { } // construct the Java task that executes converter Java j = new Java(this); - // classpath to jckit bits - Path cp = j.createClasspath(); - for(File jar: jckit.getToolJars()) { - cp.append(new Path(project, jar.getPath())); - } + addKitClasses(j); // Create temporary folder and add to cleanup File applet_folder = makeTemp(); @@ -672,7 +678,7 @@ public void execute() { } if (verify) { - verify(cp, exps); + verify(exps); } } finally { cleanTemp(); From 2bccfcb3e2efbb5b8489e122d78317bf8ba3e8cb Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:40:05 +0100 Subject: [PATCH 13/20] Extracted convert to its own method --- src/main/java/pro/javacard/ant/JavaCard.java | 116 ++++++++++--------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 225f98e..0fc0bca 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -460,6 +460,66 @@ private void addKitClasses(Java j) { j.setClasspath(cp); } + private void convert(File applet_folder, List exps) { + // construct the Java task that executes converter + Java j = new Java(this); + addKitClasses(j); + + j.createArg().setLine("-classdir '" + classes_path + "'"); + j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); + + StringJoiner expstringbuilder = new StringJoiner(File.pathSeparator); + for (File imp : exps) { + expstringbuilder.add(imp.toString()); + } + + j.createArg().setLine("-exportpath '" + expstringbuilder.toString() + "'"); + j.createArg().setLine("-verbose"); + j.createArg().setLine("-nobanner"); + if (debug) { + j.createArg().setLine("-debug"); + } + if (!verify) { + j.createArg().setLine("-noverify"); + } + if (jckit.isVersion(JCKit.Version.V3)) { + j.createArg().setLine("-useproxyclass"); + } + if (ints) { + j.createArg().setLine("-i"); + } + + String outputs = "CAP"; + if (output_exp != null) { + outputs += " EXP"; + } + if (output_jca != null) { + outputs += " JCA"; + } + j.createArg().setLine("-out " + outputs); + for (JCApplet app : raw_applets) { + j.createArg().setLine("-applet " + hexAID(app.aid) + " " + app.klass); + } + j.createArg().setLine(package_name + " " + hexAID(package_aid) + " " + package_version); + + // Call converter + if (jckit.isVersion(JCKit.Version.V3)) { + j.setClassname("com.sun.javacard.converter.Main"); + // XXX: See https://community.oracle.com/message/10452555 + Variable jchome = new Variable(); + jchome.setKey("jc.home"); + jchome.setValue(jckit.getRoot().toString()); + j.addSysproperty(jchome); + } else { + j.setClassname("com.sun.javacard.converter.Converter"); + } + j.setFailonerror(true); + j.setFork(true); + + log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); + j.execute(); + } + private void verify(List exps) { Project project = getProject(); setTaskName("verify"); @@ -513,14 +573,9 @@ public void execute() { if (sources_path != null) { compile(); } - // construct the Java task that executes converter - Java j = new Java(this); - addKitClasses(j); // Create temporary folder and add to cleanup File applet_folder = makeTemp(); - j.createArg().setLine("-classdir '" + classes_path + "'"); - j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); // Construct exportpath ArrayList exps = new ArrayList<>(); @@ -538,55 +593,8 @@ public void execute() { } } - StringJoiner expstringbuilder = new StringJoiner(File.pathSeparator); - for (File imp : exps) { - expstringbuilder.add(imp.toString()); - } - - j.createArg().setLine("-exportpath '" + expstringbuilder.toString() + "'"); - j.createArg().setLine("-verbose"); - j.createArg().setLine("-nobanner"); - if (debug) { - j.createArg().setLine("-debug"); - } - if (!verify) { - j.createArg().setLine("-noverify"); - } - if (jckit.isVersion(JCKit.Version.V3)) { - j.createArg().setLine("-useproxyclass"); - } - if (ints) { - j.createArg().setLine("-i"); - } - - String outputs = "CAP"; - if (output_exp != null) { - outputs += " EXP"; - } - if (output_jca != null) { - outputs += " JCA"; - } - j.createArg().setLine("-out " + outputs); - for (JCApplet app : raw_applets) { - j.createArg().setLine("-applet " + hexAID(app.aid) + " " + app.klass); - } - j.createArg().setLine(package_name + " " + hexAID(package_aid) + " " + package_version); - - // Call converter - if (jckit.isVersion(JCKit.Version.V3)) { - j.setClassname("com.sun.javacard.converter.Main"); - // XXX: See https://community.oracle.com/message/10452555 - Variable jchome = new Variable(); - jchome.setKey("jc.home"); - jchome.setValue(jckit.getRoot().toString()); - j.addSysproperty(jchome); - } else { - j.setClassname("com.sun.javacard.converter.Converter"); - } - j.setFailonerror(true); - j.setFork(true); - - j.execute(); + // perform conversion + convert(applet_folder, exps); // Copy results if (output_cap != null || output_exp != null || output_jca != null || output_jar != null) { From e617c75118f4aae5e48cd6aa01c04b8453c5caf8 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:04:38 +0100 Subject: [PATCH 14/20] Fixed and added comments --- src/main/java/pro/javacard/ant/JavaCard.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 0fc0bca..a786528 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -392,21 +392,24 @@ private void check() { private void compile() { Project project = getProject(); + // construct javac task Javac j = new Javac(); j.setProject(project); j.setTaskName("compile"); j.setSrcdir(new Path(project, sources_path)); + // determine output directory File tmp; if (classes_path != null) { + // if specified use that tmp = project.resolveFile(classes_path); if (!tmp.exists()) { if (!tmp.mkdir()) throw new BuildException("Could not create temporary folder " + tmp.getAbsolutePath()); } } else { - // Generate temporary folder + // else generate temporary folder tmp = makeTemp(); classes_path = tmp.getAbsolutePath(); } @@ -461,7 +464,7 @@ private void addKitClasses(Java j) { } private void convert(File applet_folder, List exps) { - // construct the Java task that executes converter + // construct java task Java j = new Java(this); addKitClasses(j); @@ -523,7 +526,7 @@ private void convert(File applet_folder, List exps) { private void verify(List exps) { Project project = getProject(); setTaskName("verify"); - // construct the Java task that executes converter + // construct java task Java j = new Java(this); addKitClasses(j); j.setClassname("com.sun.javacard.offcardverifier.Verifier"); @@ -565,7 +568,7 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at public void execute() { Project project = getProject(); - // Convert + // perform checks check(); try { From 1a82a1d02704d0e317d9dad494b1bd185726d13e Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 15:50:02 +0100 Subject: [PATCH 15/20] Cleaned up task names --- src/main/java/pro/javacard/ant/JavaCard.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index a786528..0bbe35b 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -391,6 +391,7 @@ private void check() { private void compile() { Project project = getProject(); + setTaskName("compile"); // construct javac task Javac j = new Javac(); @@ -464,8 +465,10 @@ private void addKitClasses(Java j) { } private void convert(File applet_folder, List exps) { + setTaskName("convert"); // construct java task Java j = new Java(this); + j.setTaskName("convert"); addKitClasses(j); j.createArg().setLine("-classdir '" + classes_path + "'"); @@ -529,6 +532,7 @@ private void verify(List exps) { // construct java task Java j = new Java(this); addKitClasses(j); + j.setTaskName("verify"); j.setClassname("com.sun.javacard.offcardverifier.Verifier"); // Find all expfiles final ArrayList expfiles = new ArrayList<>(); From 0d48d024b554f69495eac9b1e827fbd29e718618 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 16:30:38 +0100 Subject: [PATCH 16/20] Cleaned up convert phase --- src/main/java/pro/javacard/ant/JavaCard.java | 49 +++++++++++++------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 0bbe35b..5b5d1fc 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -469,19 +469,42 @@ private void convert(File applet_folder, List exps) { // construct java task Java j = new Java(this); j.setTaskName("convert"); + j.setFailonerror(true); + j.setFork(true); + + // add classpath for SDK tools addKitClasses(j); - j.createArg().setLine("-classdir '" + classes_path + "'"); + // set class depending on SDK + if (jckit.isVersion(JCKit.Version.V3)) { + j.setClassname("com.sun.javacard.converter.Main"); + // XXX: See https://community.oracle.com/message/10452555 + Variable jchome = new Variable(); + jchome.setKey("jc.home"); + jchome.setValue(jckit.getRoot().toString()); + j.addSysproperty(jchome); + } else { + j.setClassname("com.sun.javacard.converter.Converter"); + } + + // output path j.createArg().setLine("-d '" + applet_folder.getAbsolutePath() + "'"); + // classes for conversion + j.createArg().setLine("-classdir '" + classes_path + "'"); + + // construct export path StringJoiner expstringbuilder = new StringJoiner(File.pathSeparator); for (File imp : exps) { expstringbuilder.add(imp.toString()); } - j.createArg().setLine("-exportpath '" + expstringbuilder.toString() + "'"); + + // always be a little verbose j.createArg().setLine("-verbose"); j.createArg().setLine("-nobanner"); + + // simple options if (debug) { j.createArg().setLine("-debug"); } @@ -495,6 +518,7 @@ private void convert(File applet_folder, List exps) { j.createArg().setLine("-i"); } + // determine output types String outputs = "CAP"; if (output_exp != null) { outputs += " EXP"; @@ -503,26 +527,19 @@ private void convert(File applet_folder, List exps) { outputs += " JCA"; } j.createArg().setLine("-out " + outputs); + + // define applets for (JCApplet app : raw_applets) { j.createArg().setLine("-applet " + hexAID(app.aid) + " " + app.klass); } + + // package properties j.createArg().setLine(package_name + " " + hexAID(package_aid) + " " + package_version); - // Call converter - if (jckit.isVersion(JCKit.Version.V3)) { - j.setClassname("com.sun.javacard.converter.Main"); - // XXX: See https://community.oracle.com/message/10452555 - Variable jchome = new Variable(); - jchome.setKey("jc.home"); - jchome.setValue(jckit.getRoot().toString()); - j.addSysproperty(jchome); - } else { - j.setClassname("com.sun.javacard.converter.Converter"); - } - j.setFailonerror(true); - j.setFork(true); + // report the command + log("command: " + j.getCommandLine(), Project.MSG_VERBOSE); - log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); + // execute the converter j.execute(); } From 614f6d05778eb6228f91aa27faf8ae56174ea604 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 16:41:41 +0100 Subject: [PATCH 17/20] Cleaned up verify phase --- src/main/java/pro/javacard/ant/JavaCard.java | 44 +++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 5b5d1fc..2f1c1a8 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -546,13 +546,9 @@ private void convert(File applet_folder, List exps) { private void verify(List exps) { Project project = getProject(); setTaskName("verify"); - // construct java task - Java j = new Java(this); - addKitClasses(j); - j.setTaskName("verify"); - j.setClassname("com.sun.javacard.offcardverifier.Verifier"); - // Find all expfiles - final ArrayList expfiles = new ArrayList<>(); + + // collect all export files + final ArrayList expfiles = new ArrayList<>(); try { for (File e : exps) { Files.walkFileTree(e.toPath(), new SimpleFileVisitor() { @@ -560,7 +556,7 @@ private void verify(List exps) { public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs) throws IOException { if (file.toString().endsWith(".exp")) { - expfiles.add(file.toAbsolutePath().toString()); + expfiles.add(file.toFile()); } return FileVisitResult.CONTINUE; } @@ -571,17 +567,33 @@ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes at return; } - // Arguments to verifier - j.createArg().setLine("-nobanner"); - //TODO j.createArg().setLine("-verbose"); - for (String exp : expfiles) { - j.createArg().setLine("'" + exp + "'"); - } - j.createArg().setLine("'" + project.resolveFile(output_cap).toString() + "'"); + // construct java task + Java j = new Java(this); + j.setTaskName("verify"); j.setFailonerror(true); j.setFork(true); - log("cmdline: " + j.getCommandLine(), Project.MSG_VERBOSE); + // add classpath for SDK tools + addKitClasses(j); + // set main class + j.setClassname("com.sun.javacard.offcardverifier.Verifier"); + + // not verbose for now + //j.createArg().setLine("-verbose"); + j.createArg().setLine("-nobanner"); + + // export files for verification + for (File exp : expfiles) { + j.createArg().setLine(exp.toString()); + } + + // cap file for verification + j.createArg().setLine(project.resolveFile(output_cap).toString()); + + // report the command + log("command: " + j.getCommandLine(), Project.MSG_VERBOSE); + + // perform verification j.execute(); } From b1047adbfb010a937916a656c3b266cedd26bc99 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Wed, 7 Mar 2018 16:57:48 +0100 Subject: [PATCH 18/20] Cleaned up copy phase --- src/main/java/pro/javacard/ant/JavaCard.java | 74 +++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/main/java/pro/javacard/ant/JavaCard.java b/src/main/java/pro/javacard/ant/JavaCard.java index 2f1c1a8..9e0ce9f 100644 --- a/src/main/java/pro/javacard/ant/JavaCard.java +++ b/src/main/java/pro/javacard/ant/JavaCard.java @@ -649,42 +649,60 @@ public void execute() { File jca = new File(jcsrc, ln + ".jca"); try { + // copy CAP file + setTaskName("cap"); + // check that a CAP file got created if (!cap.exists()) { throw new BuildException("Can not find CAP in " + jcsrc); } - // Resolve output file - File opf = project.resolveFile(output_cap); - // Copy CAP - Files.copy(cap.toPath(), opf.toPath(), StandardCopyOption.REPLACE_EXISTING); - log("CAP saved to " + opf.getAbsolutePath(), Project.MSG_INFO); - // Copy exp file + // resolve output path + File outCap = project.resolveFile(output_cap); + // perform the copy + Files.copy(cap.toPath(), outCap.toPath(), StandardCopyOption.REPLACE_EXISTING); + // report destination + log("CAP saved to " + outCap, Project.MSG_INFO); + + // copy EXP file if (output_exp != null) { - setTaskName("export"); + setTaskName("exp"); + // check that an EXP file got created if (!exp.exists()) { throw new BuildException("Can not find EXP in " + jcsrc); } - // output_exp is the folder name - opf = project.resolveFile(output_exp); - - // Get the folder under the output folder - File exp_pkg_path = new File(opf.toString(), pkgPath); - File exp_path = new File(exp_pkg_path, "javacard"); - - // Create the output folder - if (!exp_path.exists()) { - if (!exp_path.mkdirs()) { - throw new HelpingBuildException("Can not make path for EXP output: " + opf.getAbsolutePath()); + // resolve output directory + File outExp = project.resolveFile(output_exp); + // determine package directories + File outExpPkg = new File(outExp.toString(), pkgPath); + File outExpPkgJc = new File(outExpPkg, "javacard"); + // create directories + if (!outExpPkgJc.exists()) { + if (!outExpPkgJc.mkdirs()) { + throw new HelpingBuildException("Could not create directory " + outExpPkgJc); } } - - // Copy output - File exp_file = new File(exp_path, exp.getName()); + // perform the copy + File exp_file = new File(outExpPkgJc, exp.getName()); Files.copy(exp.toPath(), exp_file.toPath(), StandardCopyOption.REPLACE_EXISTING); + // report destination log("EXP saved to " + exp_file, Project.MSG_INFO); - exps.add(opf); + // add the export directory to the export path for verification + exps.add(outExp); + } + // copy JCA file + if (output_jca != null) { + setTaskName("jca"); + // check that a JCA file got created + if (!jca.exists()) { + throw new BuildException("Can not find JCA in " + jcsrc); + } + // resolve output path + outCap = project.resolveFile(output_jca); + Files.copy(jca.toPath(), outCap.toPath(), StandardCopyOption.REPLACE_EXISTING); + log("JCA saved to " + outCap.getAbsolutePath(), Project.MSG_INFO); } - // Make JAR + + // create JAR file if (output_jar != null) { setTaskName("jar"); File outJar = project.resolveFile(output_jar); @@ -705,16 +723,6 @@ public void execute() { jarz.execute(); log("JAR created at " + outJar.getAbsolutePath(), Project.MSG_INFO); } - // Copy JCA - if (output_jca != null) { - setTaskName("jca"); - if (!jca.exists()) { - throw new BuildException("Can not find JCA in " + jcsrc); - } - opf = project.resolveFile(output_jca); - Files.copy(jca.toPath(), opf.toPath(), StandardCopyOption.REPLACE_EXISTING); - log("JCA saved to " + opf.getAbsolutePath(), Project.MSG_INFO); - } } catch (IOException e) { e.printStackTrace(); throw new BuildException("Can not copy output CAP, EXP or JCA", e); From bf5467145a619ad15e0b4f7cfd82478d7c7723a2 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Mon, 19 Mar 2018 18:11:20 +0100 Subject: [PATCH 19/20] Missing copyright header --- src/main/java/pro/javacard/ant/JCKit.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/pro/javacard/ant/JCKit.java b/src/main/java/pro/javacard/ant/JCKit.java index 798c938..c4a33f5 100644 --- a/src/main/java/pro/javacard/ant/JCKit.java +++ b/src/main/java/pro/javacard/ant/JCKit.java @@ -1,3 +1,24 @@ +/** + * Copyright (c) 2015-2018 Martin Paljak + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package pro.javacard.ant; import java.io.File; From 4615d20ce0902b849c19828dc402af44f0e40ad0 Mon Sep 17 00:00:00 2001 From: Ingo Albrecht Date: Mon, 19 Mar 2018 18:28:24 +0100 Subject: [PATCH 20/20] Fixed undocumented parameter --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5241a60..e749aca 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Details: * `aid` attribute - AID (hex) of the package. Recommended - or set to the 5 first bytes of the applet AID if left unspecified. * `output` attribute - path where to save the generated CAP file. Required. * `export` attribtue - path (folder) where to place the JAR and generated EXP file. Optional. + * `jar` attribute - path where to save the generated archive JAR file. Optional. * `jca` attribute - path where to save the generated JavaCard Assembly (JCA) file. Optional. * `verify` attribute - if set to false, disables verification of the resulting CAP file with offcardeverifier. Optional. * `debug` attribute - if set to true, generates debug CAP components. Optional.