diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4a0a7f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,148 @@
+#################################### Java.gitignore
+
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+#################################### Scala.gitignore
+
+*.class
+*.log
+
+# sbt specific
+.cache
+.history
+.lib/
+dist/*
+target/
+lib_managed/
+src_managed/
+project/boot/
+project/plugins/project/
+
+# Scala-IDE specific
+.scala_dependencies
+.worksheet
+
+#################################### Eclipse.gitignore
+
+*.pydevproject
+.metadata
+.gradle
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+
+# Eclipse Core
+.project
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# TeXlipse plugin
+.texlipse
+
+#################################### Linux.gitignore
+
+*~
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+#################################### JetBrains.gitignore
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
+
+*.iml
+
+## Directory-based project format:
+.idea/
+# if you remove the above rule, at least ignore the following:
+
+# User-specific stuff:
+# .idea/workspace.xml
+# .idea/tasks.xml
+# .idea/dictionaries
+
+# Sensitive or high-churn files:
+# .idea/dataSources.ids
+# .idea/dataSources.xml
+# .idea/sqlDataSources.xml
+# .idea/dynamic.xml
+# .idea/uiDesigner.xml
+
+# Gradle:
+# .idea/gradle.xml
+# .idea/libraries
+
+# Mongo Explorer plugin:
+# .idea/mongoSettings.xml
+
+## File-based project format:
+*.ipr
+*.iws
+*.iml
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+
+#################################### Mac
+
+.DS_Store
+
+#################################### Maven
+
+log/
+target/
+
+
+
diff --git a/pom.xml b/pom.xml
index f3f0cab..639f926 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,18 @@
2.2.5
test
+
+ org.apache.commons
+ commons-io
+ 1.3.2
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
@@ -131,7 +143,7 @@
- com.github.scalatojava.Main
+ com.github.scalatojava.MainExtended
diff --git a/src/main/java/com/github/scalatojava/Constants.java b/src/main/java/com/github/scalatojava/Constants.java
new file mode 100644
index 0000000..59341fe
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/Constants.java
@@ -0,0 +1,14 @@
+package com.github.scalatojava;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class Constants
+{
+ public static final String LS = System.getProperty("line.separator");
+ public static final String FS = System.getProperty("file.separator");
+ public static final String PS = System.getProperty("path.separator");
+
+ public static final String S2J = "scala2java_";
+}
diff --git a/src/main/java/com/github/scalatojava/MainExtended.java b/src/main/java/com/github/scalatojava/MainExtended.java
new file mode 100644
index 0000000..4139df6
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/MainExtended.java
@@ -0,0 +1,41 @@
+package com.github.scalatojava;
+
+import com.github.scalatojava.inputs.ScalaToJavaFromSourceTree;
+import com.github.scalatojava.inputs.ScalaToJavaFromStandaloneFile;
+import com.strobel.core.ArrayUtilities;
+import com.strobel.core.StringUtilities;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class MainExtended
+{
+ public static void main(String[] args) throws Exception
+ {
+ String pathToTranslate = System.getProperty("path");
+ String repo = System.getProperty("repo");
+ boolean slim = ArrayUtilities.contains(args, "--slim");
+
+
+ if (StringUtilities.isNullOrEmpty(pathToTranslate))
+ {
+ new ScalaToJavaFromStandardInput().run(args);
+ return;
+ }
+
+ File file = new File(pathToTranslate);
+ if (file.isDirectory())
+ {
+ new ScalaToJavaFromSourceTree().run(pathToTranslate, repo, slim);
+ }
+ else if (file.isFile())
+ {
+ new ScalaToJavaFromStandaloneFile().run(pathToTranslate, repo, slim);
+ }
+
+ System.out.println("done");
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/compilation/ScalaToJavaWithClasspath.java b/src/main/java/com/github/scalatojava/compilation/ScalaToJavaWithClasspath.java
new file mode 100644
index 0000000..b87f294
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/compilation/ScalaToJavaWithClasspath.java
@@ -0,0 +1,106 @@
+package com.github.scalatojava.compilation;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.NoRetryMetadataSystem;
+import com.github.scalatojava.files.FileExtension;
+import com.github.scalatojava.files.filters.ClassFileFilter;
+import com.strobel.assembler.InputTypeLoader;
+import com.strobel.assembler.metadata.Buffer;
+import com.strobel.assembler.metadata.TypeDefinition;
+import com.strobel.decompiler.DecompilationOptions;
+import com.strobel.decompiler.DecompilerSettings;
+import com.strobel.decompiler.PlainTextOutput;
+import com.strobel.decompiler.languages.Languages;
+import com.strobel.decompiler.languages.java.JavaFormattingOptions;
+import com.strobel.decompiler.languages.java.JavaLanguage;
+import scala.collection.JavaConversions;
+import scala.tools.nsc.Global;
+import scala.tools.nsc.Settings;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+public class ScalaToJavaWithClasspath
+{
+ protected String classpath;
+ protected boolean slim;
+
+ public ScalaToJavaWithClasspath(String classpath, boolean slim)
+ {
+ this.classpath = classpath;
+ this.slim = slim;
+ }
+
+ public String decompile(final File file) throws IOException
+ {
+ final InputTypeLoader typeLoader = new InputTypeLoader();
+ typeLoader.tryLoadType(file.getPath(), new Buffer(Files.readAllBytes(file.toPath())));
+ final JavaLanguage javaLanguage = Languages.java();
+ final NoRetryMetadataSystem metadataSystem = new NoRetryMetadataSystem(typeLoader);
+ final TypeDefinition resolvedType = metadataSystem.resolveType(FileExtension.remove(file.getName()), false);
+
+ final DecompilerSettings settings = new DecompilerSettings();
+ settings.setLanguage(javaLanguage);
+ settings.setTypeLoader(typeLoader);
+ settings.setFormattingOptions(JavaFormattingOptions.createDefault());
+ final DecompilationOptions options = new DecompilationOptions();
+ options.setSettings(settings);
+ options.setFullDecompilation(true);
+ final StringWriter writer = new StringWriter();
+ final PlainTextOutput output = new PlainTextOutput(writer);
+ javaLanguage.decompileType(resolvedType, output, options);
+ writer.flush();
+ String java = writer.toString();
+ if (slim)
+ java = java.replaceFirst("(?s)public final class _\\$\\s+.*", "");
+ return java;
+ }
+
+ public File[] compile(final File scalaSourceFile, final File containerDirForCompiledFiles)
+ {
+ final Global.Run runner = getCompilerRun(containerDirForCompiledFiles);
+ runner.compile(JavaConversions.asScalaBuffer(Arrays.asList(scalaSourceFile.getPath())).toList());
+ return containerDirForCompiledFiles.listFiles(new ClassFileFilter());
+ }
+
+ private Global.Run getCompilerRun(File dir)
+ {
+ final Settings settings = new Settings();
+ settings.processArgumentString(prepareCompileArgs(dir));
+ final Global compiler = new Global(settings);
+ return compiler.new Run();
+ }
+
+ private String prepareCompileArgs(File dir)
+ {
+ StringBuilder args = new StringBuilder();
+ args.append(" -target:jvm-1.8")
+ .append(" -explaintypes")
+ .append(" -Xscript _")
+ .append(" -usejavacp")
+ .append(" -d ").append(dir.getPath());
+ if (classpath != null && classpath.trim().length() > 0)
+ {
+ args.append(" -classpath \"").append(classpath).append("\"");
+ }
+ return args.toString();
+ }
+
+ public String apply(final String value) throws IOException
+ {
+ final File tempDir = Files.createTempDirectory("s2j").toFile();
+ final File scalaFile = new File(tempDir, "_.scala");
+ Files.write(scalaFile.toPath(), value.getBytes());
+ File[] compileds = compile(scalaFile, tempDir);
+ StringBuilder javaSource = new StringBuilder();
+ for (File compiled : compileds)
+ {
+ String s = decompile(compiled);
+ javaSource.append(s).append(Constants.LS);
+ }
+ return javaSource.toString();
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/FileExtension.java b/src/main/java/com/github/scalatojava/files/FileExtension.java
new file mode 100644
index 0000000..590f27e
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/FileExtension.java
@@ -0,0 +1,54 @@
+package com.github.scalatojava.files;
+
+import com.strobel.core.StringUtilities;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class FileExtension
+{
+ public static String replace(String filename, String extensionReplacement)
+ {
+ guardUndefined(filename);
+ if (filename.lastIndexOf(".") == -1) {
+ filename += ".";
+ }
+ if (StringUtilities.isNullOrEmpty(extensionReplacement)) {
+ return filename;
+ }
+ if (extensionReplacement.startsWith(".")) {
+ extensionReplacement = extensionReplacement.substring(1);
+ }
+
+ filename = filename.substring(0, filename.lastIndexOf(".") + 1) + extensionReplacement;
+ guardUndefined(filename);
+ return filename;
+ }
+
+ public static String get(String filename)
+ {
+ guardUndefined(filename);
+ if (filename.lastIndexOf(".") == -1) {
+ return "";
+ }
+ return filename.substring(filename.lastIndexOf(".") + 1, filename.length());
+ }
+
+ public static String remove(String filename)
+ {
+ guardUndefined(filename);
+ if (filename.lastIndexOf(".") == -1) {
+ return filename;
+ }
+ return filename.substring(0, filename.lastIndexOf("."));
+ }
+
+ private static void guardUndefined(String filename)
+ {
+ if (filename == null || filename.equals(".") || filename.equals(".."))
+ {
+ throw new IllegalArgumentException("the operation is undefined on this filename");
+ }
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/FileTreeTraversal.java b/src/main/java/com/github/scalatojava/files/FileTreeTraversal.java
new file mode 100644
index 0000000..7466d3d
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/FileTreeTraversal.java
@@ -0,0 +1,46 @@
+package com.github.scalatojava.files;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class FileTreeTraversal
+{
+ protected TraverseStrategy cs;
+
+ public void traverse(File root, TraverseStrategy cs)
+ {
+ this.cs = cs;
+ if (root.isFile())
+ {
+ cs.handleFile(root);
+ }
+ else
+ {
+ traverseRecursive(root);
+ }
+ cs.handleDone();
+ }
+
+ protected void traverseRecursive(File file)
+ {
+ if (file == null)
+ {
+ return;
+ }
+ else if (file.isFile())
+ {
+ cs.handleFile(file);
+ }
+ else
+ {
+ cs.handleDir(file);
+ for (File f : file.listFiles())
+ {
+ traverseRecursive(f);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/TraverseStrategy.java b/src/main/java/com/github/scalatojava/files/TraverseStrategy.java
new file mode 100644
index 0000000..68ba80e
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/TraverseStrategy.java
@@ -0,0 +1,15 @@
+package com.github.scalatojava.files;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public interface TraverseStrategy
+{
+ Object handleFile(File file);
+ Object handleDir(File dir);
+ Object result();
+ Object handleDone();
+}
diff --git a/src/main/java/com/github/scalatojava/files/filters/ClassFileFilter.java b/src/main/java/com/github/scalatojava/files/filters/ClassFileFilter.java
new file mode 100644
index 0000000..17a930c
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/filters/ClassFileFilter.java
@@ -0,0 +1,15 @@
+package com.github.scalatojava.files.filters;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public final class ClassFileFilter implements FilenameFilter {
+ @Override
+ public boolean accept(final File dir, final String name) {
+ return name.endsWith(".class");
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/filters/JavaFileFilter.java b/src/main/java/com/github/scalatojava/files/filters/JavaFileFilter.java
new file mode 100644
index 0000000..ee66781
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/filters/JavaFileFilter.java
@@ -0,0 +1,17 @@
+package com.github.scalatojava.files.filters;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class JavaFileFilter implements FileFilter
+{
+ @Override
+ public boolean accept(File pathname)
+ {
+ return false;
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/filters/ScalaFileFilter.java b/src/main/java/com/github/scalatojava/files/filters/ScalaFileFilter.java
new file mode 100644
index 0000000..c67f8fc
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/filters/ScalaFileFilter.java
@@ -0,0 +1,17 @@
+package com.github.scalatojava.files.filters;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public final class ScalaFileFilter implements FilenameFilter
+{
+ @Override
+ public boolean accept(final File dir, final String name)
+ {
+ return name.endsWith(".scala");
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/strategies/ConcatFiles.java b/src/main/java/com/github/scalatojava/files/strategies/ConcatFiles.java
new file mode 100644
index 0000000..f46bca0
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/ConcatFiles.java
@@ -0,0 +1,86 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.files.TraverseStrategy;
+import com.strobel.core.StringUtilities;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class ConcatFiles implements TraverseStrategy
+{
+ protected final File destFile;
+ protected final StringBuilder concatenated;
+
+ public ConcatFiles(File destFile)
+ {
+ if (destFile == null)
+ {
+ throw new IllegalArgumentException("dest file cannot be null");
+ }
+ else if (!destFile.exists())
+ {
+ try
+ {
+ destFile.createNewFile();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ this.destFile = destFile;
+ concatenated = new StringBuilder();
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ try
+ {
+ if (file == null || file.getName().contains("package.scala")) {
+ return null;
+ }
+ final List lines = Files.readAllLines(file.toPath());
+ String text = StringUtilities.join(Constants.LS, lines);
+ concatenated.append(text).append(Constants.LS);
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not read file: " + file.toPath());
+ }
+ return null;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ return null;
+ }
+
+ @Override
+ public Object result() {
+ return concatenated.toString();
+ }
+
+ @Override
+ public Object handleDone()
+ {
+ try
+ {
+ Files.write(destFile.toPath(), concatenated.toString().getBytes(), StandardOpenOption.WRITE);
+ }
+ catch (IOException e)
+ {
+ System.out.println("could not write concatenated content to: " + destFile.toPath());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/strategies/CopyScalaFiles.java b/src/main/java/com/github/scalatojava/files/strategies/CopyScalaFiles.java
new file mode 100644
index 0000000..9660da5
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/CopyScalaFiles.java
@@ -0,0 +1,83 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.TraverseStrategy;
+import com.github.scalatojava.files.filters.ScalaFileFilter;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class CopyScalaFiles implements TraverseStrategy
+{
+ protected final File destDir;
+ private final boolean overwrite;
+
+ public CopyScalaFiles(File destDir, boolean overwrite)
+ {
+ if (destDir == null || !destDir.exists())
+ {
+ throw new IllegalArgumentException("dest dir does not exist");
+ }
+ this.destDir = destDir;
+ this.overwrite = overwrite;
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ return null;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ if (dir == null)
+ {
+ return null;
+ }
+ File[] scalaSources = dir.listFiles(new ScalaFileFilter());
+ for (File file : scalaSources)
+ {
+
+ final Path sourcePath = file.toPath();
+ final Path destPath = destDir.toPath().resolve(file.getName());
+ try
+ {
+ if (overwrite)
+ {
+ Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ else if (!destPath.toFile().exists())
+ {
+ Files.copy(sourcePath, destPath);
+ }
+ else
+ {
+ System.out.println(String.format("file already exists, could not copy %s to %s", sourcePath, destPath));
+ }
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException(String.format("could not copy %s to %s", sourcePath, destPath), e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Object result()
+ {
+ return destDir;
+ }
+
+ @Override
+ public Object handleDone() {
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/strategies/CreateClasspath.java b/src/main/java/com/github/scalatojava/files/strategies/CreateClasspath.java
new file mode 100644
index 0000000..981ad37
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/CreateClasspath.java
@@ -0,0 +1,59 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.files.TraverseStrategy;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class CreateClasspath implements TraverseStrategy
+{
+ protected final StringBuilder classpath;
+
+ public CreateClasspath()
+ {
+ classpath = new StringBuilder();
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ if (isCompiledJar(file))
+ {
+ classpath.append(file.getAbsolutePath());
+ classpath.append(Constants.PS);
+ }
+ return null;
+ }
+
+ private boolean isCompiledJar(File file)
+ {
+ return file != null && file.getName().endsWith(".jar") &&
+ !file.getName().contains("dependencies.jar") &&
+ !file.getName().contains("tests.jar") &&
+ !file.getName().contains("javadoc.jar") &&
+ !file.getName().contains("sources.jar");
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ return null;
+ }
+
+ @Override
+ public Object result()
+ {
+ return classpath.toString();
+ }
+
+ @Override
+ public Object handleDone()
+ {
+ classpath.append('.');
+ return classpath;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/scalatojava/files/strategies/CreateImports.java b/src/main/java/com/github/scalatojava/files/strategies/CreateImports.java
new file mode 100644
index 0000000..0c568c6
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/CreateImports.java
@@ -0,0 +1,98 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.TraverseStrategy;
+
+import java.io.File;
+import java.util.NavigableSet;
+import java.util.TreeSet;
+
+import static com.github.scalatojava.Constants.FS;
+import static com.github.scalatojava.Constants.LS;
+
+/**
+ * @author eitanraviv@github
+ * @since 9/8/15
+ */
+public class CreateImports implements TraverseStrategy
+{
+ protected final NavigableSet importSet;
+ protected StringBuilder importStr;
+
+ public CreateImports()
+ {
+ importSet = new TreeSet<>();
+ importStr = new StringBuilder();
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ return null;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ String packageName = parsePackage(dir);
+ if (packageName != null)
+ {
+ importSet.add("import " + packageName + "._");
+ }
+ return null;
+ }
+
+ private String parsePackage(File dir)
+ {
+ String lang;
+ if (dir == null)
+ {
+ return null;
+ }
+ else if (!hasFiles(dir))
+ {
+ return null;
+ }
+ else if (isSourceDir(dir, "java"))
+ {
+ lang = "java";
+ }
+ else if (isSourceDir(dir, "scala"))
+ {
+ lang = "scala";
+ }
+ else
+ {
+ return null;
+ }
+ String dirPath = dir.getAbsolutePath();
+ String packagePath = dirPath.substring(dirPath.lastIndexOf(lang) + lang.length() + FS.length(), dirPath.length());
+ return packagePath.replace(FS, ".");
+ }
+
+ private boolean isSourceDir(File dir, String lang)
+ {
+ final String p = dir.getAbsolutePath();
+ return p.contains("src" + FS + "main" + FS + lang) && !p.endsWith(lang);
+ }
+
+ private boolean hasFiles(File dir)
+ {
+ return dir != null && dir.listFiles().length > 0;
+ }
+
+ @Override
+ public Object result()
+ {
+ return importStr.toString();
+ }
+
+ @Override
+ public Object handleDone()
+ {
+ for (String s : importSet)
+ {
+ importStr.append(s).append(LS);
+ }
+ return importSet;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/github/scalatojava/files/strategies/DeleteClassFiles.java b/src/main/java/com/github/scalatojava/files/strategies/DeleteClassFiles.java
new file mode 100644
index 0000000..9807aa2
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/DeleteClassFiles.java
@@ -0,0 +1,42 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.FileExtension;
+import com.github.scalatojava.files.TraverseStrategy;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class DeleteClassFiles implements TraverseStrategy
+{
+ protected boolean allDeleted = true;
+
+ @Override
+ public Object handleFile(File file)
+ {
+ if (file != null && "class".equals(FileExtension.get(file.getName())))
+ {
+ allDeleted &= file.delete();
+ }
+ return null;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ return null;
+ }
+
+ @Override
+ public Object result()
+ {
+ return allDeleted;
+ }
+
+ @Override
+ public Object handleDone() {
+ return allDeleted;
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/strategies/PrependText.java b/src/main/java/com/github/scalatojava/files/strategies/PrependText.java
new file mode 100644
index 0000000..b6b895f
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/PrependText.java
@@ -0,0 +1,98 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.TraverseStrategy;
+import com.strobel.core.Closeables;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.util.List;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class PrependText implements TraverseStrategy
+{
+ protected static final String LS = System.getProperty("line.separator");
+ protected String prepend;
+ protected StringBuilder newText;
+
+ public PrependText(String prepend)
+ {
+ this.prepend = prepend;
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ if (file == null)
+ {
+ return null;
+ }
+ FileReader rd = null;
+ FileWriter fw = null;
+ try
+ {
+ rd = new FileReader(file);
+ List lines = IOUtils.readLines(rd);
+ StringBuilder text = concatLines(lines);
+ newText = prepend(text);
+ fw = new FileWriter(file);
+ fw.write(newText.toString());
+ return newText;
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not read file: " + file.getAbsolutePath());
+ return null;
+ }
+ finally
+ {
+ Closeables.close(rd, fw);
+ }
+ }
+
+ private StringBuilder prepend(StringBuilder text)
+ {
+ if (prepend == null)
+ {
+ return text;
+ }
+ else
+ {
+ return new StringBuilder(prepend.length() + text.length() + LS.length()).
+ append(prepend).
+ append(LS).
+ append(text);
+ }
+ }
+
+ private StringBuilder concatLines(List lines)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (String line: lines)
+ {
+ sb.append(line).append(LS);
+ }
+ return sb;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ return null;
+ }
+
+ @Override
+ public Object result() {
+ return newText;
+ }
+
+ @Override
+ public Object handleDone()
+ {
+ return null;
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/files/strategies/RemovePackageDeclaration.java b/src/main/java/com/github/scalatojava/files/strategies/RemovePackageDeclaration.java
new file mode 100644
index 0000000..24fd6e8
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/files/strategies/RemovePackageDeclaration.java
@@ -0,0 +1,102 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.TraverseStrategy;
+import com.strobel.core.Closeables;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015
+ */
+public class RemovePackageDeclaration implements TraverseStrategy
+{
+ protected final File destFile;
+ protected List lines;
+
+ public RemovePackageDeclaration(File destFile)
+ {
+ if (destFile == null || !destFile.exists())
+ {
+ throw new IllegalArgumentException("dest file does not exist");
+ }
+ this.destFile = destFile;
+ }
+
+ @Override
+ public Object handleFile(File file)
+ {
+ if (file == null)
+ {
+ return null;
+ }
+ try
+ {
+ lines = IOUtils.readLines(new FileReader(file));
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object handleDir(File dir)
+ {
+ return null;
+ }
+
+ @Override
+ public Object result() {
+ return destFile;
+ }
+
+ @Override
+ public Object handleDone()
+ {
+ removePackageDeclarations();
+ writeLines();
+ return null;
+ }
+
+ private void removePackageDeclarations()
+ {
+ lines.removeIf(new Predicate()
+ {
+ @Override
+ public boolean test(String s)
+ {
+ return !s.matches("^package[\\s]+object.*") && s.matches("^package[\\s]+.*");
+ }
+ });
+ }
+
+ private void writeLines()
+ {
+ FileWriter writer = null;
+ try
+ {
+ writer = new FileWriter(destFile);
+ IOUtils.writeLines(lines, null, writer);
+ }
+ catch (IOException e)
+ {
+ System.out.println("could not write to: " + destFile.getAbsolutePath());
+ }
+ finally
+ {
+ if (writer != null)
+ {
+ Closeables.close(writer);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromSourceTree.java b/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromSourceTree.java
new file mode 100644
index 0000000..c58f2ff
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromSourceTree.java
@@ -0,0 +1,118 @@
+package com.github.scalatojava.inputs;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.compilation.ScalaToJavaWithClasspath;
+import com.github.scalatojava.files.FileExtension;
+import com.github.scalatojava.files.FileTreeTraversal;
+import com.github.scalatojava.files.TraverseStrategy;
+import com.github.scalatojava.files.filters.ClassFileFilter;
+import com.github.scalatojava.files.strategies.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class ScalaToJavaFromSourceTree
+{
+ public void run(String rootPath, String repoPath, boolean slim) throws IOException
+ {
+ /**
+ * Sources root dir is the root dir of the compilation unit.
+ * compilation unit - a collection of files which can produce a jar;
+ * for example, a project in eclipse or a module in intellij-idea
+ */
+ final File sourcesRootDir = new File(rootPath);
+
+ //The repository where all the dependencies of the above compilation unit reside
+ final File repo = new File(repoPath);
+
+ //Temporary directory where the output of this program will be written to
+ final File containerDir = Files.createTempDirectory(Constants.S2J).toFile();
+ System.out.println(String.format("all files written to %s", containerDir.toPath()));
+
+ //output directories
+ final File collectDir = containerDir.toPath().resolve("collect").toFile();
+ final File concatDir = containerDir.toPath().resolve("concat").toFile();
+ final File compileDir = containerDir.toPath().resolve("compiled").toFile();
+
+ boolean success = collectDir.mkdir();
+ success &= concatDir.mkdir();
+ success &= compileDir.mkdir();
+
+ if (!success) {
+ throw new IllegalStateException("could not create output dirs");
+ }
+
+ final File concatenatedScala = concatDir.toPath().resolve("concat.scala").toFile();
+ final File adjustedScala = concatDir.toPath().resolve("adjusted.scala").toFile();
+ final FileTreeTraversal t = new FileTreeTraversal();
+
+ //copy all scala file in the source tree to a single directory for further handling
+ TraverseStrategy copy = new CopyScalaFiles(collectDir, true);
+ t.traverse(sourcesRootDir, copy);
+
+ //the compiler requires a single file containing all the scala to be translated
+ TraverseStrategy concat = new ConcatFiles(concatenatedScala);
+ t.traverse(collectDir, concat);
+
+ adjustedScala.createNewFile();
+ //the compiler does not accept package declarations
+ TraverseStrategy remove = new RemovePackageDeclaration(adjustedScala);
+ t.traverse(concatenatedScala, remove);
+
+ //if there are java files in the source tree, the corresponding imports need to
+ //be added to the scala file
+ TraverseStrategy imports = new CreateImports();
+ t.traverse(sourcesRootDir, imports);
+
+ TraverseStrategy prependImports = new PrependText((String) imports.result());
+ t.traverse(adjustedScala, prependImports);
+
+ //build the classpath from the repo
+ TraverseStrategy classpath = new CreateClasspath();
+ t.traverse(repo, classpath);
+
+ translate(compileDir, adjustedScala, (String) classpath.result(), slim);
+ cleanup(compileDir);
+ System.out.println(String.format("all files written to %s", containerDir.toPath()));
+ }
+
+ /**
+ * compile the scala file to class files, and then decompile them one by one
+ * @param compileDir the directory that will contain the compiled .class files and the decompiled .java files
+ * @param adjustedScala the scala file to translate from
+ * @param classpath the classpath of the scala sources in the scala file
+ * @param slim directive to the decompiler about the output
+ * @throws IOException
+ */
+ private void translate(File compileDir, File adjustedScala, String classpath, boolean slim) throws IOException
+ {
+ ScalaToJavaWithClasspath s2j = new ScalaToJavaWithClasspath(classpath, slim);
+ s2j.compile(adjustedScala, compileDir);
+
+ for (File f: compileDir.listFiles(new ClassFileFilter()))
+ {
+ System.out.println("decompiling: " + f.getName());
+ String java = s2j.decompile(f);
+ File jf = new File(FileExtension.replace(f.getAbsolutePath(), ".java"));
+ Files.write(jf.toPath(), java.getBytes());
+ }
+ }
+
+ /**
+ * delete the .class files from the output directory
+ * @param compileDir
+ */
+ private void cleanup(File compileDir)
+ {
+ TraverseStrategy delete = new DeleteClassFiles();
+ new FileTreeTraversal().traverse(compileDir, delete);
+ if (! (boolean)delete.result()) {
+ System.out.println("could not delete all class files in " + compileDir.getName());
+ }
+ }
+}
diff --git a/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromStandaloneFile.java b/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromStandaloneFile.java
new file mode 100644
index 0000000..81a4343
--- /dev/null
+++ b/src/main/java/com/github/scalatojava/inputs/ScalaToJavaFromStandaloneFile.java
@@ -0,0 +1,57 @@
+package com.github.scalatojava.inputs;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.compilation.ScalaToJavaWithClasspath;
+import com.github.scalatojava.files.FileExtension;
+import com.github.scalatojava.files.FileTreeTraversal;
+import com.github.scalatojava.files.TraverseStrategy;
+import com.github.scalatojava.files.strategies.CreateClasspath;
+import com.strobel.core.StringUtilities;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class ScalaToJavaFromStandaloneFile
+{
+ public void run(String filename, String repoPath, boolean slim) throws IOException
+ {
+ String scala = readScala(filename);
+ String classpath = buildClasspath(repoPath);
+ String java = translate(scala, classpath, slim);
+ writeJava(filename, java);
+ }
+
+ private String buildClasspath(String repoPath)
+ {
+ final File repo = new File(repoPath);
+ final FileTreeTraversal t = new FileTreeTraversal();
+ TraverseStrategy classpath = new CreateClasspath();
+ t.traverse(repo, classpath);
+ return (String) classpath.result();
+ }
+
+ private String readScala(String filename) throws IOException
+ {
+ List lines = Files.readAllLines(new File(filename).toPath());
+ return StringUtilities.join(Constants.LS, lines);
+ }
+
+ private String translate(String scala, String classpath, boolean slim) throws IOException
+ {
+ return new ScalaToJavaWithClasspath(classpath, slim).apply(scala);
+ }
+
+ private void writeJava(String filename, String java) throws IOException
+ {
+ Path outPath = new File(FileExtension.replace(filename, ".java")).toPath();
+ Files.write(outPath, java.getBytes());
+ System.out.println("file was written to: " + outPath);
+ }
+}
diff --git a/src/main/resources/scala-to-java.sh b/src/main/resources/scala-to-java.sh
new file mode 100755
index 0000000..9b2eb93
--- /dev/null
+++ b/src/main/resources/scala-to-java.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+#args
+#path of files to translate
+path=/.../module/root
+#repository of jars that the path is dependent on
+repo=/.../.m2/repository
+
+
+echo "running java -jar scala-to-java.jar"
+echo "path:" $path
+echo "repo:" $repo
+
+#run
+java -jar -Dpath=path -Drepo=$repo scala-to-java.jar --slim
+
+echo "done"
diff --git a/src/main/scala/com/github/scalatojava/Main.scala b/src/main/scala/com/github/scalatojava/Main.scala
index 406a2dd..919d1ba 100644
--- a/src/main/scala/com/github/scalatojava/Main.scala
+++ b/src/main/scala/com/github/scalatojava/Main.scala
@@ -5,11 +5,6 @@ package com.github.scalatojava
* 2015-07-12
*/
object Main extends App {
- val source = Iterator.continually(scala.io.StdIn.readLine()).takeWhile(
- _ != null).mkString("\n")
-
- println()
- private val java = ScalaToJava(source)
-
- println(if (args.contains("--slim")) java.replaceFirst("(?s)public final class _\\$\\s+.*", "") else java)
+ val s2j: ScalaToJavaFromStandardInput = new ScalaToJavaFromStandardInput()
+ s2j.run(args)
}
diff --git a/src/main/scala/com/github/scalatojava/NoRetryMetadataSystem.scala b/src/main/scala/com/github/scalatojava/NoRetryMetadataSystem.scala
new file mode 100644
index 0000000..81c6a78
--- /dev/null
+++ b/src/main/scala/com/github/scalatojava/NoRetryMetadataSystem.scala
@@ -0,0 +1,21 @@
+package com.github.scalatojava
+
+import com.strobel.assembler.metadata.{ITypeLoader, MetadataSystem, TypeDefinition}
+
+import scala.collection.mutable
+
+class NoRetryMetadataSystem(typeLoader: ITypeLoader) extends MetadataSystem(typeLoader) {
+
+ val failedTypes = mutable.Set[String]()
+
+ override def resolveType(descriptor: String, mightBePrimitive: Boolean): TypeDefinition = {
+ if (failedTypes.contains(descriptor)) {
+ return null
+ }
+ val r = super.resolveType(descriptor, mightBePrimitive)
+ if (r == null) {
+ failedTypes.add(descriptor)
+ }
+ r
+ }
+}
diff --git a/src/main/scala/com/github/scalatojava/ScalaToJava.scala b/src/main/scala/com/github/scalatojava/ScalaToJava.scala
index 7d36193..851c006 100644
--- a/src/main/scala/com/github/scalatojava/ScalaToJava.scala
+++ b/src/main/scala/com/github/scalatojava/ScalaToJava.scala
@@ -1,17 +1,16 @@
package com.github.scalatojava
-import java.io.{File, StringWriter}
-import java.nio.file.{Paths, Files}
+import java.io.{File, StringWriter, _}
+import java.nio.file.{Files, Paths}
+import java.util.Arrays
import com.strobel.assembler.InputTypeLoader
import com.strobel.assembler.metadata._
import com.strobel.decompiler.languages.Languages
import com.strobel.decompiler.languages.java.JavaFormattingOptions
-import com.strobel.decompiler.{PlainTextOutput, DecompilerSettings, DecompilationOptions}
-import scala.collection.mutable
+import com.strobel.decompiler.{DecompilationOptions, DecompilerSettings, PlainTextOutput}
+
import scala.tools.nsc._
-import java.io._
-import java.util.Arrays
/**
* Scala-to-Java translator
@@ -42,39 +41,28 @@ object ScalaToJava {
writer.toString
}
- def compile(input: File, output: File): Array[File] = {
+ def compile(scalaFile: File, containerDir: File): Array[File] = {
val settings = new Settings
settings processArgumentString "-target:jvm-1.8 -Xscript _ -usejavacp -d " +
- output.getPath
+ containerDir.getPath
val compiler = new Global(settings)
val runner = new compiler.Run
- runner.compile(List(input.getPath))
- output.listFiles(new FilenameFilter {
- override def accept(dir: File, name: String): Boolean = name.endsWith(".class")
- })
+ runner.compile(List(scalaFile.getPath))
+ val compiledFiles: Array[File] = containerDir.listFiles(new FilenameFilter {
+ override def accept(dir: File, name: String): Boolean = name.endsWith(".class")
+ }
+ )
+ return compiledFiles
}
def apply(value: String): String = {
- val output = Files.createTempDirectory("s2j").toFile
- val input = new File(output, "_.scala")
- Files.write(input.toPath, Arrays.asList(value))
- compile(input, output).map(decompile).mkString("\n\n")
+ val containerDir = Files.createTempDirectory("s2j").toFile
+ val scalaFile = new File(containerDir, "_.scala")
+ Files.write(scalaFile.toPath, Arrays.asList(value))
+ val compiled: Array[File] = compile(scalaFile, containerDir)
+ val map: Array[String] = compiled.map(decompile)
+ map.mkString("\n\n")
}
- class NoRetryMetadataSystem(typeLoader: ITypeLoader) extends MetadataSystem(typeLoader) {
-
- val failedTypes = mutable.Set[String]()
-
- override def resolveType(descriptor: String, mightBePrimitive: Boolean): TypeDefinition = {
- if (failedTypes.contains(descriptor)) {
- return null
- }
- val r = super.resolveType(descriptor, mightBePrimitive)
- if (r == null) {
- failedTypes.add(descriptor)
- }
- r
- }
- }
}
diff --git a/src/main/scala/com/github/scalatojava/ScalaToJavaFromStandardInput.scala b/src/main/scala/com/github/scalatojava/ScalaToJavaFromStandardInput.scala
new file mode 100644
index 0000000..a83c879
--- /dev/null
+++ b/src/main/scala/com/github/scalatojava/ScalaToJavaFromStandardInput.scala
@@ -0,0 +1,15 @@
+package com.github.scalatojava
+
+class ScalaToJavaFromStandardInput
+{
+ def run(args: Array[String])
+ {
+ val source = Iterator.continually(scala.io.StdIn.readLine()).takeWhile(
+ _ != null).mkString("\n")
+
+ println()
+ val java = ScalaToJava(source)
+
+ println(if (args.contains("--slim")) java.replaceFirst("(?s)public final class _\\$\\s+.*", "") else java)
+ }
+}
diff --git a/src/test/java/com/github/scalatojava/files/FileExtensionTest.java b/src/test/java/com/github/scalatojava/files/FileExtensionTest.java
new file mode 100644
index 0000000..3a953bb
--- /dev/null
+++ b/src/test/java/com/github/scalatojava/files/FileExtensionTest.java
@@ -0,0 +1,337 @@
+package com.github.scalatojava.files;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sep 2015
+ */
+public class FileExtensionTest
+{
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ /********** remove ************/
+
+ @Test
+ public void testRemove0()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("");
+ //assert
+ assertEquals("", filename);
+ }
+
+ @Test
+ public void testRemove1()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("name");
+ //assert
+ assertEquals("name", filename);
+ }
+
+ @Test
+ public void testRemove2()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("name.");
+ //assert
+ assertEquals("name", filename);
+ }
+
+ @Test
+ public void testRemove3()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("name.e");
+ //assert
+ assertEquals("name", filename);
+ }
+
+ @Test
+ public void testRemove4()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("name.ext");
+ //assert
+ assertEquals("name", filename);
+ }
+
+ @Test
+ public void testRemove5()
+ {
+ //arrange + act
+ final String filename = FileExtension.remove("first.last.ext");
+ //assert
+ assertEquals("first.last", filename);
+ }
+
+ @Test
+ public void testRemove6()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.remove(".");
+ }
+
+ @Test
+ public void testRemove7()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.remove("..");
+ }
+
+ @Test
+ public void testRemove8()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.remove(null);
+ }
+
+ /********** get ************/
+
+ @Test
+ public void testGet0()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("");
+ //assert
+ assertEquals("", ext);
+ }
+
+ @Test
+ public void testGet1()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("name");
+ //assert
+ assertEquals("", ext);
+ }
+
+ @Test
+ public void testGet2()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("name.");
+ //assert
+ assertEquals("", ext);
+ }
+
+ @Test
+ public void testGet3()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("name.e");
+ //assert
+ assertEquals("e", ext);
+ }
+
+ @Test
+ public void testGet4()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("name.ext");
+ //assert
+ assertEquals("ext", ext);
+ }
+
+ @Test
+ public void testGet5()
+ {
+ //arrange + act
+ final String ext = FileExtension.get("first.last.ext");
+ //assert
+ assertEquals("ext", ext);
+ }
+
+ @Test
+ public void testGet6()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.get(".");
+ }
+
+ @Test
+ public void testGet7()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.get("..");
+ }
+
+ @Test
+ public void testGet8()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.get(null);
+ }
+
+ /********** replace ************/
+
+ @Test
+ public void testReplace0()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("", "");
+ //assert
+ assertEquals(".", filename);
+ }
+
+ @Test
+ public void testReplace1()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name", "txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace2()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name.", "txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace3()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name.e", "txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace4()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name.ext", "txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace5()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("first.last.ext", "txt");
+ //assert
+ assertEquals("first.last.txt", filename);
+ }
+
+ @Test
+ public void testReplace6()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.replace(".", "");
+ }
+
+ @Test
+ public void testReplace7()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.replace("..", "");
+ }
+
+ @Test
+ public void testReplace8()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.replace(null, "");
+ }
+
+ @Test
+ public void testReplace9()
+ {
+ //act
+ final String filename = FileExtension.replace("", null);
+ assertEquals(".", filename);
+ }
+
+ @Test
+ public void testReplace10()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name", ".txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace11()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name.", ".txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace12()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("name.e", ".txt");
+ //assert
+ assertEquals("name.txt", filename);
+ }
+
+ @Test
+ public void testReplace13()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("", ".txt");
+ //assert
+ assertEquals(".txt", filename);
+ }
+
+ @Test
+ public void testReplace14()
+ {
+ //arrange + act
+ final String filename = FileExtension.replace("", "txt");
+ //assert
+ assertEquals(".txt", filename);
+ }
+
+ @Test
+ public void testReplace15()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.replace("", ".");
+ }
+
+ @Test
+ public void testReplace16()
+ {
+ //arrange
+ exception.expect(IllegalArgumentException.class);
+ //act
+ FileExtension.replace(".", "");
+ }
+}
diff --git a/src/test/java/com/github/scalatojava/files/strategies/CopyScalaFilesTest.java b/src/test/java/com/github/scalatojava/files/strategies/CopyScalaFilesTest.java
new file mode 100644
index 0000000..069e8fd
--- /dev/null
+++ b/src/test/java/com/github/scalatojava/files/strategies/CopyScalaFilesTest.java
@@ -0,0 +1,43 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.Constants;
+import com.github.scalatojava.files.FileTreeTraversal;
+import com.github.scalatojava.files.TraverseStrategy;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class CopyScalaFilesTest
+{
+ @Test
+ public void test() throws IOException
+ {
+ final File destDir = Files.createTempDirectory(Constants.S2J + CopyScalaFilesTest.class.getSimpleName()).toFile();
+ System.out.println(String.format("all files written to %s", destDir.toPath()));
+ destDir.delete();
+ destDir.mkdir();
+
+ TraverseStrategy s = new CopyScalaFiles(destDir, false);
+ FileTreeTraversal t = new FileTreeTraversal();
+ t.traverse(new File("path/to/module/to/translate"), s);
+ }
+
+ @Test
+ public void testOverwrite() throws IOException
+ {
+ final File destDir = Files.createTempDirectory(Constants.S2J + CopyScalaFilesTest.class.getSimpleName()).toFile();
+ System.out.println(String.format("all files written to %s", destDir.toPath()));
+ destDir.delete();
+ destDir.mkdir();
+
+ TraverseStrategy s = new CopyScalaFiles(destDir, true);
+ FileTreeTraversal t = new FileTreeTraversal();
+ t.traverse(new File("path/to/module/to/translate"), s);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/github/scalatojava/files/strategies/CreateClasspathTest.java b/src/test/java/com/github/scalatojava/files/strategies/CreateClasspathTest.java
new file mode 100644
index 0000000..6901d5e
--- /dev/null
+++ b/src/test/java/com/github/scalatojava/files/strategies/CreateClasspathTest.java
@@ -0,0 +1,25 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.FileTreeTraversal;
+import com.github.scalatojava.files.TraverseStrategy;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class CreateClasspathTest
+{
+ @Test
+ public void test()
+ {
+ final File jarRepo = new File("/path/to/repository/with/jars");
+ FileTreeTraversal t = new FileTreeTraversal();
+
+ TraverseStrategy s1 = new CreateClasspath();
+ t.traverse(jarRepo, s1);
+ System.out.println(s1.result());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/github/scalatojava/files/strategies/CreateImportsTest.java b/src/test/java/com/github/scalatojava/files/strategies/CreateImportsTest.java
new file mode 100644
index 0000000..47f3f55
--- /dev/null
+++ b/src/test/java/com/github/scalatojava/files/strategies/CreateImportsTest.java
@@ -0,0 +1,24 @@
+package com.github.scalatojava.files.strategies;
+
+import com.github.scalatojava.files.FileTreeTraversal;
+import com.github.scalatojava.files.TraverseStrategy;
+import org.junit.Test;
+
+import java.io.File;
+
+/**
+ * @author eitanraviv@github
+ * @since 21 Sept 2015.
+ */
+public class CreateImportsTest
+{
+ @Test
+ public void test()
+ {
+ FileTreeTraversal t = new FileTreeTraversal();
+ final File sourceDir = new File("path/to/module/to/translate");
+ TraverseStrategy s = new CreateImports();
+ t.traverse(sourceDir, s);
+ System.out.println(s.result());
+ }
+}
\ No newline at end of file