diff --git a/docs/unimelb-mf-upload.md b/docs/unimelb-mf-upload.md index 5621b297a22d9493429095896007fe264e53a319..87119fc9d9c72fd166bd6463fb1edfbd1aaab915 100644 --- a/docs/unimelb-mf-upload.md +++ b/docs/unimelb-mf-upload.md @@ -32,5 +32,5 @@ POSITIONAL ARGUMENTS: <src-dir> Source directory to upload. EXAMPLES: - unimelb-mf-upload --mf.config ~/.Arcitecta/mflux.cfg --nb-queriers 2 --nb-workers 4 --namespace /projects/proj-1128.1.59 ~/Documents/foo ~/Documents/bar + unimelb-mf-upload --mf.config ~/.Arcitecta/mflux.cfg --nb-workers 4 --namespace /projects/proj-1128.1.59 ~/Documents/foo ~/Documents/bar ``` diff --git a/pom.xml b/pom.xml index fa8a9b6c63153dc64f7bad33d83441ac8e284605..bb251ffc94f6cff83fbeaf9d2fec840b73cd836e 100644 --- a/pom.xml +++ b/pom.xml @@ -5,16 +5,22 @@ <groupId>au.edu.unimelb.mf</groupId> <artifactId>unimelb-mf-clients</artifactId> - <version>0.1.9</version> + <version>0.2.0</version> <packaging>jar</packaging> <name>unimelb-mf-clients</name> - <url>https://github.com/UoM-ResPlat-DevOps/unimelb-mf-clients</url> + <url>https://gitlab.unimelb.edu.au/resplat-mediaflux/unimelb-mf-clients</url> <description>UniMelb Mediaflux clients.</description> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <skipTests>true</skipTests> <mexplorer.version>1.3.27</mexplorer.version> + <jre8mac64file>jre-8u191-macosx-x64</jre8mac64file> + <jre8mac64url>https://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jre-8u191-macosx-x64.tar.gz</jre8mac64url> + <jre8win64file>jre-8u191-windows-x64</jre8win64file> + <jre8win64url>https://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jre-8u191-windows-x64.tar.gz</jre8win64url> + <dist>${project.build.directory}/dist</dist> </properties> <repositories> <repository> @@ -43,23 +49,22 @@ </dependencies> <build> <plugins> + <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-antrun-plugin</artifactId> - <version>1.7</version> + <groupId>org.codehaus.mojo</groupId> + <artifactId>wagon-maven-plugin</artifactId> + <version>1.0</version> <executions> <execution> - <phase>package</phase> <id>download-mexplorer</id> + <phase>prepare-package</phase> <goals> - <goal>run</goal> + <goal>download-single</goal> </goals> <configuration> - <target> - <get - src="http://www.arcitecta.com/software/mexplorer/mexplorer-${mexplorer.version}.jar" - dest="${project.build.directory}" /> - </target> + <url>http://www.arcitecta.com</url> + <fromFile>/software/mexplorer/mexplorer-${mexplorer.version}.jar</fromFile> + <toFile>${project.build.directory}/mexplorer.jar</toFile> </configuration> </execution> </executions> @@ -108,6 +113,148 @@ </execution> </executions> </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.8</version> + <executions> + <execution> + <phase>package</phase> + <configuration> + <target> + <!-- Initialisation --> + <tstamp /> + <delete dir="${dist}" /> + <mkdir dir="${dist}" /> + + <!-- Mac OS package --> + <echo + message="building Mac OS package with 64 bit Java 8 Runtime..." /> + + <mkdir dir="${dist}/mac" /> + <mkdir dir="${dist}/mac/temp" /> + <mkdir + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}" /> + <mkdir + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin" /> + <mkdir + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin/unix" /> + <mkdir + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/lib" /> + <copy + file="${project.build.directory}/unimelb-mf-clients-${project.version}-jar-with-dependencies.jar" + tofile="${dist}/mac/temp/unimelb-mf-clients-${project.version}/lib/unimelb-mf-clients.jar" /> + <copy file="${project.build.directory}/mexplorer.jar" + tofile="${dist}/mac/temp/unimelb-mf-clients-${project.version}/lib/mexplorer.jar" /> + <copy + todir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin/unix"> + <fileset dir="${project.basedir}/src/main/scripts/unix" /> + </copy> + <exec executable="curl" dir="${dist}/mac"> + <arg value="-L" /> + <arg value="-O" /> + <arg value="-H" /> + <arg + value="Cookie: oraclelicense=accept-securebackup-cookie" /> + <arg value="-k" /> + <arg value="${jre8mac64url}" /> + </exec> + <gunzip src="${dist}/mac/${jre8mac64file}.tar.gz" + dest="${dist}/mac" /> + <untar src="${dist}/mac/${jre8mac64file}.tar" + dest="${dist}/mac/temp/unimelb-mf-clients-${project.version}" /> + <dirset + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}" + id="jreDirId"> + <include name="jre*" /> + </dirset> + <property name="jreDir" refid="jreDirId" /> + <property name="javaHome" + value="${jreDir}/Contents/Home" /> + <replace + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin/unix" + token="@JAVA_HOME@" value="${javaHome}" /> + <replace + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin/unix" + token="#export JAVA_HOME=" value="export JAVA_HOME=" /> + <replace + dir="${dist}/mac/temp/unimelb-mf-clients-${project.version}/bin/unix" + token="#export PATH=" value="export PATH=" /> + <zip + destfile="${dist}/mac/unimelb-mf-clients-${project.version}-mac-x64.zip"> + <zipfileset dir="${dist}/mac/temp" filemode="755" /> + </zip> + <delete dir="${dist}/mac/temp" /> + <delete file="${dist}/mac/${jre8mac64file}.tar.gz" /> + <delete file="${dist}/mac/${jre8mac64file}.tar" /> + + <!-- Windows package --> + <echo + message="building Windows package with 64 bit Java 8 Runtime..." /> + <mkdir dir="${dist}/windows" /> + <mkdir dir="${dist}/windows/temp" /> + <mkdir + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}" /> + <mkdir + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin" /> + <mkdir + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin/windows" /> + <mkdir + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/lib" /> + <copy + file="${project.build.directory}/unimelb-mf-clients-${project.version}-jar-with-dependencies.jar" + tofile="${dist}/windows/temp/unimelb-mf-clients-${project.version}/lib/unimelb-mf-clients.jar" /> + <copy file="${project.build.directory}/mexplorer.jar" + tofile="${dist}/windows/temp/unimelb-mf-clients-${project.version}/lib/mexplorer.jar" /> + <copy + todir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin/windows"> + <fileset + dir="${project.basedir}/src/main/scripts/windows" /> + </copy> + <exec executable="curl" dir="${dist}/windows"> + <arg value="-L" /> + <arg value="-O" /> + <arg value="-H" /> + <arg + value="Cookie: oraclelicense=accept-securebackup-cookie" /> + <arg value="-k" /> + <arg value="${jre8win64url}" /> + </exec> + <gunzip src="${dist}/windows/${jre8win64file}.tar.gz" + dest="${dist}/windows" /> + <untar src="${dist}/windows/${jre8win64file}.tar" + dest="${dist}/windows/temp/unimelb-mf-clients-${project.version}" /> + <dirset + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}" + id="jreDirId"> + <include name="jre*" /> + </dirset> + <property name="jreDir" refid="jreDirId" /> + <property name="javaHome" value="${jreDir}" /> + <replace + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin/windows" + token="@JAVA_HOME@" value="${javaHome}" /> + <replace + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin/windows" + token="@REM set JAVA_HOME=" value="set JAVA_HOME=" /> + <replace + dir="${dist}/windows/temp/unimelb-mf-clients-${project.version}/bin/windows" + token="@REM set PATH=" value="set PATH=" /> + <zip + destfile="${dist}/windows/unimelb-mf-clients-${project.version}-windows-x64.zip"> + <zipfileset dir="${dist}/windows/temp" + filemode="755" /> + </zip> + <delete dir="${dist}/windows/temp" /> + <delete file="${dist}/windows/${jre8win64file}.tar.gz" /> + <delete file="${dist}/windows/${jre8win64file}.tar" /> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> </project> diff --git a/src/main/assembly/make-zip.xml b/src/main/assembly/make-zip.xml index 1dcedc4b16fc4bf016d54fc12983b64877ff949c..f478e57ae68884649b0314532e0f6e727e62fc2b 100644 --- a/src/main/assembly/make-zip.xml +++ b/src/main/assembly/make-zip.xml @@ -14,9 +14,9 @@ <destName>${project.artifactId}.jar</destName> </file> <file> - <source>${project.build.directory}/mexplorer-${mexplorer.version}.jar</source> + <source>${project.build.directory}/mexplorer.jar</source> <outputDirectory>${project.artifactId}-${project.version}/lib</outputDirectory> - <destName>mexplorer-${mexplorer.version}.jar</destName> + <destName>mexplorer.jar</destName> </file> </files> <fileSets> diff --git a/src/main/config/samples/unimelb-mf-clients-properties.xml b/src/main/config/samples/unimelb-mf-clients-properties.xml index d6214f8f472b2f23fb76c6f3815bbb2c190ed2d7..d0f23f9ab9a680a6713daedd06f83abf2cae8a02 100644 --- a/src/main/config/samples/unimelb-mf-clients-properties.xml +++ b/src/main/config/samples/unimelb-mf-clients-properties.xml @@ -6,7 +6,7 @@ <!-- Mediaflux server port --> <port>443</port> <!-- Mediaflux server transport. https, http or tcp/ip --> - <protocol>https</protocol> + <transport>https</transport> <session> <!-- Retry times on Mediaflux connection failure --> <connectRetryTimes>1</connectRetryTimes> diff --git a/src/main/config/samples/unimelb-mf-perf-properties.xml b/src/main/config/samples/unimelb-mf-perf-properties.xml new file mode 100644 index 0000000000000000000000000000000000000000..af715ab7dd14513b507f84c90be8243aad7f33bd --- /dev/null +++ b/src/main/config/samples/unimelb-mf-perf-properties.xml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<properties> + <server> + <host>localhost</host> + <port>8086</port> + <transport>http</transport> + </server> + <credential> + <domain>system</domain> + <user>manager</user> + <password>change_me</password> + </credential> + <perf> + <verbose>true</verbose> + <logDirectory>/tmp</logDirectory> + <test> + <action>ping</action> + <action>upload</action> + <action>download</action> + <numberOfThreads>1</numberOfThreads> + <useClusterIO>true</useClusterIO> + <useInMemoryFile>false</useInMemoryFile> + <numberOfFiles>10</numberOfFiles> + <fileSize>10000000</fileSize> + <namespace>/mf-perf-test</namespace> + <directory>/tmp/mf-perf-test</directory> + </test> + <result> + <asset> + <path>/test-result/mf-perf-result.csv</path> + </asset> + <file> + <path>/tmp/mf-perf-result.csv</path> + </file> + </result> + </perf> +</properties> diff --git a/src/main/java/unimelb/mf/client/gui/MFSessionGUI.java b/src/main/java/unimelb/mf/client/gui/MFSessionGUI.java index a93123a3cb5f3042b605e926f71351cc62c4bea0..5f7be830168b29aadd020eba3cab36bb5260ec63 100644 --- a/src/main/java/unimelb/mf/client/gui/MFSessionGUI.java +++ b/src/main/java/unimelb/mf/client/gui/MFSessionGUI.java @@ -1,6 +1,7 @@ package unimelb.mf.client.gui; -import unimelb.mf.client.session.MFConnectionSettings; +import arc.mf.client.AuthenticationDetails; +import arc.mf.client.RemoteServer; import unimelb.mf.client.session.MFSession; public class MFSessionGUI extends MFSession { @@ -8,12 +9,8 @@ public class MFSessionGUI extends MFSession { private ErrorDialog _ed; private LogonDialog _ld; - public MFSessionGUI(MFConnectionSettings settings, LogonDialog ld, ErrorDialog ed) { - super(settings); -// this.settings.setExecuteRetryTimes(0); -// this.settings.setExecuteRetryInterval(0); -// this.settings.setConnectRetryTimes(0); -// this.settings.setConnectRetryInterval(0); + protected MFSessionGUI(RemoteServer rs, AuthenticationDetails ad, String session, LogonDialog ld, ErrorDialog ed) { + super(rs, ad, session, 0, 0, 0, 0); _ld = ld; _ed = ed; } diff --git a/src/main/java/unimelb/mf/client/perf/Action.java b/src/main/java/unimelb/mf/client/perf/Action.java new file mode 100644 index 0000000000000000000000000000000000000000..419bcc55bfe066e5a2ff10ce0c9ae31fd555edad --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/Action.java @@ -0,0 +1,26 @@ +package unimelb.mf.client.perf; + +public enum Action { + + PING("server.ping"), UPLOAD("asset.create"), DOWNLOAD("asset.get"); + + private String _service; + + Action(String service) { + _service = service; + } + + public String service() { + return _service; + } + + public static Action fromString(String a) { + Action[] vs = values(); + for (Action v : vs) { + if (v.name().equalsIgnoreCase(a == null ? null : a.trim())) { + return v; + } + } + return null; + } +} diff --git a/src/main/java/unimelb/mf/client/perf/MFPerf.java b/src/main/java/unimelb/mf/client/perf/MFPerf.java new file mode 100644 index 0000000000000000000000000000000000000000..c3bff7a444b9d2cb9677873dcfa7101302e55162 --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/MFPerf.java @@ -0,0 +1,142 @@ +package unimelb.mf.client.perf; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; + +import arc.mf.client.ServerClient; +import arc.xml.XmlStringWriter; +import unimelb.mf.client.session.MFSession; +import unimelb.mf.client.util.AssetUtils; +import unimelb.mf.client.util.LoggingUtils; + +public class MFPerf implements Callable<Void> { + + public static final String APPLICATION_NAME = "unimelb-mf-perf"; + + private MFSession _session; + private MFPerfSettings _settings; + private Logger _logger; + + public MFPerf(MFSession session, MFPerfSettings settings) throws Throwable { + _session = session; + _settings = settings; + if (_settings.logDirectory() != null) { + _logger = LoggingUtils.createFileAndConsoleLogger(_settings.logDirectory(), APPLICATION_NAME); + } else { + _logger = LoggingUtils.createConsoleLogger(APPLICATION_NAME); + } + } + + @Override + public Void call() throws Exception { + try { + List<TestResult> results = new ArrayList<TestResult>(); + List<TestSettings> tss = _settings.testSettings(); + if (_settings.verbose()) { + _logger.info("starting tests..."); + } + for (TestSettings ts : tss) { + results.addAll(new Test(_session, ts, _logger, _settings.verbose()).call()); + } + if (_settings.resultAssetID() != null) { + if (_settings.verbose()) { + _logger.info("updating result asset " + _settings.resultAssetID() + "..."); + } + updateResultAsset(_session, results, _settings.resultAssetID(), _settings.resultAssetRetain()); + } + if (_settings.resultFilePath() != null) { + if (_settings.verbose()) { + _logger.info("updating result file " + _settings.resultFilePath() + "..."); + } + saveResultsToFile(results, _settings.resultFilePath().toFile()); + } + + printResults(results); + + return null; + } catch (Throwable e) { + _logger.log(Level.SEVERE, e.getMessage(), e); + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + + private static void updateResultAsset(MFSession session, List<TestResult> results, String resultAssetID, int retain) + throws Throwable { + updateResultAsset(session, results, resultAssetID, retain, null); + } + + private static void updateResultAsset(MFSession session, List<TestResult> results, String resultAssetID, int retain, + Path tmpDir) throws Throwable { + File tmpFile = tmpDir != null ? File.createTempFile(APPLICATION_NAME + "-result-", ".csv", tmpDir.toFile()) + : File.createTempFile(APPLICATION_NAME + "-result-", ".csv"); + try { + if (AssetUtils.assetExists(session, resultAssetID)) { + XmlStringWriter w = new XmlStringWriter(); + w.add("id", resultAssetID); + session.execute("asset.get", w.document(), new ServerClient.FileOutput(tmpFile)); + } + + saveResultsToFile(results, tmpFile); + + XmlStringWriter w = new XmlStringWriter(); + w.add("id", resultAssetID); + w.add("create", true); + session.execute("asset.set", w.document(), new ServerClient.FileInput(tmpFile)); + if (retain > 0) { + pruneAsset(session, resultAssetID, retain); + } + } finally { + Files.deleteIfExists(tmpFile.toPath()); + } + } + + private static void saveResultsToFile(List<TestResult> results, File file) throws Throwable { + boolean fileExists = file.exists(); + try (Writer w = new BufferedWriter(new FileWriter(file, fileExists))) { + if (!fileExists) { + TestResult.saveCSVHeader(w); + } + for (TestResult r : results) { + r.saveCSV(w); + } + } + } + + private static void pruneAsset(MFSession session, String assetId, int retain) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("id", assetId); + w.add("retain", retain); + session.execute("asset.prune", w.document()); + } + + private static void printResults(List<TestResult> results) throws IOException { + System.out.println(); + OutputStreamWriter w = new OutputStreamWriter(System.out); + TestResult.saveCSVHeader(w); + if (results != null && !results.isEmpty()) { + for (TestResult r : results) { + r.saveCSV(w); + } + w.flush(); + } + System.out.println(); + } +} diff --git a/src/main/java/unimelb/mf/client/perf/MFPerfSettings.java b/src/main/java/unimelb/mf/client/perf/MFPerfSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..9120021f97aed93a5fdb3a176f095af55498a60e --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/MFPerfSettings.java @@ -0,0 +1,163 @@ +package unimelb.mf.client.perf; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import arc.xml.XmlDoc; +import unimelb.mf.client.session.MFSession; + +public class MFPerfSettings { + + public static final int RESULT_ASSET_RETAIN = 10; + + private String _resultAssetID; + private String _resultAssetPath; + private int _resultAssetRetain = RESULT_ASSET_RETAIN; + private Path _resultFilePath; + private List<TestSettings> _testSettings; + private boolean _verbose = false; + private Path _logDir = null; + + MFPerfSettings() { + _testSettings = new ArrayList<TestSettings>(); + } + + MFPerfSettings(XmlDoc.Element pe) throws Throwable { + this(); + parse(pe); + } + + public Path resultFilePath() { + return _resultFilePath; + } + + public String resultAssetID() { + if (_resultAssetID != null) { + return _resultAssetID; + } else if (_resultAssetPath != null) { + return "path=" + _resultAssetPath; + } else { + return null; + } + } + + public String resultAssetPath() { + return _resultAssetPath; + } + + public int resultAssetRetain() { + return _resultAssetRetain; + } + + public boolean verbose() { + return _verbose; + } + + public Path logDirectory() { + return _logDir; + } + + public MFPerfSettings setResultFilePath(Path path) { + _resultFilePath = path; + return this; + } + + public MFPerfSettings setResultAssetID(String assetID) { + _resultAssetID = assetID; + return this; + } + + public MFPerfSettings setResultAssetPath(String assetPath) { + _resultAssetPath = assetPath; + return this; + } + + public MFPerfSettings setResultAssetRetain(int retain) { + _resultAssetRetain = retain; + return this; + } + + public MFPerfSettings setResultFilePath(String path) { + _resultFilePath = Paths.get(path); + return this; + } + + public MFPerfSettings setVerbose(boolean verbose) { + _verbose = verbose; + return this; + } + + public MFPerfSettings setLogDirectory(Path logDir) { + _logDir = logDir; + return this; + } + + public void addTestSettings(TestSettings ts) { + _testSettings.add(ts); + } + + public List<TestSettings> testSettings() { + return Collections.unmodifiableList(_testSettings); + } + + public void parse(XmlDoc.Element e) throws Throwable { + _verbose = e.booleanValue("verbose", false); + String logDir = e.value("logDirectory"); + if (logDir != null) { + + } + if (e.elementExists("logDirectory")) { + _logDir = Paths.get(e.value("logDirectory")); + if (!Files.isDirectory(_logDir)) { + throw new IllegalArgumentException( + "Log directory: " + _logDir.toString() + " does not exist or it is not a directory."); + } + } + if (e.elementExists("result/asset/id")) { + setResultAssetID(e.value("result/asset/id")); + } + if (e.elementExists("result/asset/path")) { + setResultAssetPath(e.value("result/asset/path")); + } + if (e.elementExists("result/asset/retain")) { + setResultAssetRetain(e.intValue("result/asset/retain")); + } + if (e.elementExists("result/file/path")) { + setResultFilePath(Paths.get(e.value("result/file/path"))); + } + List<XmlDoc.Element> tes = e.elements("test"); + if (tes != null && !tes.isEmpty()) { + for (XmlDoc.Element te : tes) { + addTestSettings(new TestSettings(te)); + } + } + } + + public void validate(MFSession session) throws Throwable { + + for (TestSettings ts : _testSettings) { + ts.validate(session); + } + } + + public static MFPerfSettings parse(File xmlFile) throws Throwable { + try (Reader r = new BufferedReader(new FileReader(xmlFile))) { + XmlDoc.Element e = new XmlDoc().parse(r); + if (!e.elementExists("perf")) { + throw new IllegalArgumentException( + "No perf element found from XML file: " + xmlFile.getPath() + ". Invalid configuration."); + } + XmlDoc.Element pe = e.element("perf"); + return new MFPerfSettings(pe); + } + } + +} diff --git a/src/main/java/unimelb/mf/client/perf/Test.java b/src/main/java/unimelb/mf/client/perf/Test.java new file mode 100644 index 0000000000000000000000000000000000000000..74f31ba31b62269b97a971312366214921b80d67 --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/Test.java @@ -0,0 +1,409 @@ +package unimelb.mf.client.perf; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +import arc.mf.client.ServerClient; +import arc.xml.XmlDoc; +import arc.xml.XmlDoc.Element; +import arc.xml.XmlStringWriter; +import unimelb.mf.client.session.MFSession; +import unimelb.mf.client.util.AssetNamespaceUtils; + +public class Test implements Callable<List<TestResult>> { + + private TestSettings _settings; + private MFSession _session; + private Logger _logger; + private boolean _verbose; + + public Test(MFSession session, TestSettings settings, Logger logger, boolean verbose) { + _session = session; + _settings = settings; + _logger = logger; + _verbose = verbose; + } + + @Override + public List<TestResult> call() throws Exception { + try { + List<TestResult> results = new ArrayList<TestResult>(); + ExecutorService executor = Executors.newFixedThreadPool(_settings.numberOfThreads()); + if (_settings.ping()) { + if (_verbose) { + _logger.info("starting ping test..."); + } + TestResult pr = ping(executor); + if (_verbose) { + _logger.info("completed ping test. Result:\n" + pr.toString()); + } + results.add(pr); + } + if (_settings.upload() || _settings.download()) { + String store = _settings.useClusterIO() ? null + : AssetNamespaceUtils.getStore(_session, _settings.namespace()); + List<String> assetIds = new ArrayList<String>(); + try { + if (_verbose) { + _logger.info("starting upload test..."); + } + TestResult ur = upload(executor, assetIds, store); + if (_verbose) { + _logger.info("completed upload test. Result:\n" + ur.toString()); + } + results.add(ur); + if (_settings.download()) { + if (_verbose) { + _logger.info("starting download test..."); + } + TestResult dr = download(executor, assetIds); + if (_verbose) { + _logger.info("completed download test. Result:\n" + dr.toString()); + } + results.add(dr); + } + } finally { + if (!assetIds.isEmpty()) { + if (_verbose) { + _logger.info("cleaning up uploaded test assets in namespace: " + _settings.namespace()); + } + destroyAssets(_session, assetIds); + } + } + } + executor.shutdown(); + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MICROSECONDS); + return results; + } catch (Throwable e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + + private TestResult download(ExecutorService executor, List<String> assetIds) throws Throwable { + long totalSize = getTotalContentSize(_session, assetIds); + List<Future<Void>> futures = new ArrayList<Future<Void>>(assetIds.size()); + long startTime = System.currentTimeMillis(); + for (String assetId : assetIds) { + Future<Void> future = executor.submit(new Callable<Void>() { + + @Override + public Void call() throws Exception { + try { + download(_session, assetId, _settings.useInMemoryFile() ? null : _settings.directory()); + return null; + } catch (Throwable e) { + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + }); + futures.add(future); + } + for (Future<Void> future : futures) { + future.get(); + } + long endTime = System.currentTimeMillis(); + return new TestResult(Action.DOWNLOAD, totalSize, startTime, endTime, _settings.numberOfThreads(), + assetIds.size(), _settings.fileSize(), _settings.useClusterIO(), _settings.useInMemoryFile(), + _settings.useInMemoryFile() ? null : _settings.directory(), _settings.namespace()); + + } + + public static long getTotalContentSize(MFSession session, List<String> assetIds) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("display", "total"); + for (String assetId : assetIds) { + w.add("id", assetId); + } + return session.execute("asset.content.size", w.document()).longValue("total"); + } + + public static void download(MFSession session, String assetId, Path dir) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("id", assetId); + ServerClient.Output output = null; + File file = null; + try { + if (dir == null) { + output = new ServerClient.NullOutput(); + } else { + file = File.createTempFile("test", ".tmp", dir.toFile()); + output = new ServerClient.FileOutput(file); + } + session.execute(Action.DOWNLOAD.service(), w.document(), output); + } finally { + if (file != null) { + Files.deleteIfExists(file.toPath()); + } + } + } + + private TestResult upload(ExecutorService executor, List<String> assetIds, String store) throws Throwable { + if (_settings.useInMemoryFile()) { + return upload(executor, _settings.fileSize(), _settings.numberOfFiles(), assetIds, store); + } else { + List<File> files = generateTmpFiles(_settings.directory(), _settings.fileSize(), _settings.numberOfFiles()); + try { + return upload(executor, files, assetIds, store); + } finally { + for (File file : files) { + Files.delete(file.toPath()); + } + } + } + } + + private TestResult upload(ExecutorService executor, long fileSize, int numberOfFiles, List<String> assetIds, + String store) throws Throwable { + long totalSize = fileSize * numberOfFiles; + List<Future<String>> futures = new ArrayList<Future<String>>(numberOfFiles); + long startTime = System.currentTimeMillis(); + for (int i = 0; i < numberOfFiles; i++) { + final String name = String.format("test%d-%d.tmp", i, System.currentTimeMillis()); + Future<String> future = executor.submit(new Callable<String>() { + + @Override + public String call() throws Exception { + try { + return upload(_session, fileSize, name, _settings.namespace(), store); + } catch (Throwable e) { + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + }); + futures.add(future); + } + for (Future<String> future : futures) { + assetIds.add(future.get()); + } + long endTime = System.currentTimeMillis(); + return new TestResult(Action.UPLOAD, totalSize, startTime, endTime, _settings.numberOfThreads(), numberOfFiles, + fileSize, _settings.useClusterIO(), true, null, _settings.namespace()); + + } + + private TestResult upload(ExecutorService executor, Collection<File> files, List<String> assetIds, String store) + throws Throwable { + long totalSize = 0L; + for (File file : files) { + totalSize += file.length(); + } + List<Future<String>> futures = new ArrayList<Future<String>>(files.size()); + long startTime = System.currentTimeMillis(); + for (File file : files) { + Future<String> future = executor.submit(new Callable<String>() { + + @Override + public String call() throws Exception { + try { + return upload(_session, file, _settings.namespace(), store); + } catch (Throwable e) { + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + + }); + futures.add(future); + } + for (Future<String> future : futures) { + assetIds.add(future.get()); + } + long endTime = System.currentTimeMillis(); + return new TestResult(Action.UPLOAD, totalSize, startTime, endTime, _settings.numberOfThreads(), files.size(), + _settings.fileSize(), _settings.useClusterIO(), false, _settings.directory(), _settings.namespace()); + } + + public static String upload(MFSession session, File file, String namespace, String store) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("namespace", namespace); + w.add("name", file.getName()); + if (store != null) { + w.add("store", store); + } + ServerClient.Input input = new ServerClient.FileInput(file); + if (store != null) { + input.setStore("asset:" + store); + } + return session.execute(Action.UPLOAD.service(), w.document(), input).value("id"); + } + + public static String upload(MFSession session, long fileSize, String name, String namespace, String store) + throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("namespace", namespace); + w.add("name", name); + if (store != null) { + w.add("store", store); + } + ServerClient.Input input = new ServerClient.NullInput(fileSize); + input.setStore(store); + return session.execute(Action.UPLOAD.service(), w.document(), input).value("id"); + } + + private TestResult ping(ExecutorService executor) throws Throwable { + if (_settings.useInMemoryFile()) { + return ping(executor, _settings.fileSize(), _settings.numberOfFiles()); + } else { + List<File> files = generateTmpFiles(_settings.directory(), _settings.fileSize(), _settings.numberOfFiles()); + try { + return ping(executor, files); + } finally { + for (File file : files) { + Files.delete(file.toPath()); + } + } + + } + } + + private TestResult ping(ExecutorService executor, long fileSize, int numberOfFiles) throws Throwable { + long totalSize = fileSize * numberOfFiles; + List<Future<XmlDoc.Element>> futures = new ArrayList<Future<XmlDoc.Element>>(numberOfFiles); + long startTime = System.currentTimeMillis(); + for (int i = 0; i < numberOfFiles; i++) { + Future<XmlDoc.Element> future = executor.submit(new Callable<XmlDoc.Element>() { + + @Override + public Element call() throws Exception { + try { + return ping(_session, fileSize); + } catch (Throwable e) { + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + }); + futures.add(future); + } + List<XmlDoc.Element> res = new ArrayList<XmlDoc.Element>(futures.size()); + for (Future<XmlDoc.Element> future : futures) { + res.add(future.get()); + } + long endTime = System.currentTimeMillis(); + return new TestResult(Action.PING, totalSize, startTime, endTime, _settings.numberOfThreads(), numberOfFiles, + fileSize, _settings.useClusterIO(), true, null, null); + } + + private TestResult ping(ExecutorService executor, Collection<File> files) throws Throwable { + long totalSize = 0L; + for (File file : files) { + totalSize += file.length(); + } + List<Future<XmlDoc.Element>> futures = new ArrayList<Future<XmlDoc.Element>>(files.size()); + long startTime = System.currentTimeMillis(); + for (File file : files) { + Future<XmlDoc.Element> future = executor.submit(new Callable<XmlDoc.Element>() { + + @Override + public Element call() throws Exception { + try { + return ping(_session, file); + } catch (Throwable e) { + if (e instanceof Exception) { + throw (Exception) e; + } else { + throw new Exception(e); + } + } + } + }); + futures.add(future); + } + List<XmlDoc.Element> res = new ArrayList<XmlDoc.Element>(futures.size()); + for (Future<XmlDoc.Element> future : futures) { + res.add(future.get()); + } + long endTime = System.currentTimeMillis(); + return new TestResult(Action.PING, totalSize, startTime, endTime, _settings.numberOfThreads(), files.size(), + _settings.fileSize(), _settings.useClusterIO(), false, _settings.directory(), null); + } + + public static XmlDoc.Element ping(MFSession session, File file) throws Throwable { + return session.execute(Action.PING.service(), null, new ServerClient.FileInput(file)); + } + + public static XmlDoc.Element ping(MFSession session, long length) throws Throwable { + return session.execute(Action.PING.service(), null, new ServerClient.NullInput(length)); + } + + private static List<File> generateTmpFiles(Path dir, long length, int nbFiles) throws Throwable { + List<File> testFiles = new ArrayList<File>(nbFiles); + for (int i = 0; i < nbFiles; i++) { + File file = generateTmpFile(dir, String.format("test%d-%d.tmp", i, System.currentTimeMillis()), length); + testFiles.add(file); + } + return testFiles; + } + + private static File generateTmpFile(Path dir, String name, long length) throws Throwable { + + Path path = Paths.get(dir.toString(), name); + File file = path.toFile(); + OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + byte[] buffer = new byte[1024]; + Random random = new Random(); + try { + long remaining = length; + while (remaining > 0) { + random.nextBytes(buffer); + if (remaining >= buffer.length) { + out.write(buffer); + remaining -= buffer.length; + } else { + out.write(buffer, 0, (int) remaining); + remaining = 0; + } + } + out.flush(); + return file; + } finally { + out.close(); + } + + } + + private static void destroyAssets(MFSession session, Collection<String> assetIds) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + for (String assetId : assetIds) { + w.add("id", assetId); + } + session.execute("asset.destroy", w.document()); + } + +} diff --git a/src/main/java/unimelb/mf/client/perf/TestResult.java b/src/main/java/unimelb/mf/client/perf/TestResult.java new file mode 100644 index 0000000000000000000000000000000000000000..6af738bedab01efda57019239a15f6756df24ae9 --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/TestResult.java @@ -0,0 +1,118 @@ +package unimelb.mf.client.perf; + +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Path; +import java.text.SimpleDateFormat; +import java.util.Date; + +import arc.utils.DateTime; + +public class TestResult { + + public final Action action; + public final long size; + public final long startTime; + public final long endTime; + + public final int numberOfThreads; + public final int numberOfFiles; + public final long fileSize; + + public final boolean useClusterIO; + public final boolean useInMemoryFile; + public final Path directory; + public final String namespace; + + public TestResult(Action action, long size, long startTime, long endTime, int numberOfThreads, int numberOfFiles, + long fileSize, boolean useClusterIO, boolean useInMemoryFile, Path directory, String namespace) { + this.action = action; + this.size = size; + this.startTime = startTime; + this.endTime = endTime; + + this.numberOfThreads = numberOfThreads; + this.numberOfFiles = numberOfFiles; + this.useClusterIO = useClusterIO; + this.useInMemoryFile = useInMemoryFile; + this.fileSize = fileSize; + this.directory = directory; + this.namespace = namespace; + } + + public final long timeMillisecs() { + return this.endTime - this.startTime; + } + + public final double timeSeconds() { + return (double) timeMillisecs() / 1000.0; + } + + public final double rateBPS() { + return ((double) this.size) / ((double) timeMillisecs() / 1000.0); + } + + public final double rateKPS() { + return rateBPS() / 1000.0; + } + + public final double rateMPS() { + return rateBPS() / 1000000.0; + } + + public final double rateGPS() { + return rateBPS() / 1000000000.0; + } + + public void saveCSV(Writer w) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append(this.action.name().toLowerCase()).append(","); + sb.append(this.numberOfThreads).append(","); + sb.append(this.useClusterIO).append(","); + sb.append(this.useInMemoryFile).append(","); + sb.append(this.fileSize).append(","); + sb.append(this.numberOfFiles).append(","); + sb.append(formatTime(this.startTime)).append(","); + sb.append(formatTime(this.endTime)).append(","); + sb.append(String.format("%.3f", this.timeSeconds())).append(","); + sb.append(String.format("%.3f", this.rateMPS())).append(","); + sb.append("\n"); + w.write(sb.toString()); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("\taction: %s,\n", this.action.name().toLowerCase())); + sb.append(String.format("\tnumber-of-threads: %s,\n", this.numberOfThreads)); + sb.append(String.format("\tuse-cluster-io: %s\n", this.useClusterIO)); + sb.append(String.format("\tuse-in-memory-file: %s\n", this.useInMemoryFile)); + sb.append(String.format("\tfile-size: %d bytes\n", this.fileSize)); + sb.append(String.format("\tnumber-of-files: %d\n", this.numberOfFiles)); + sb.append(String.format("\tstart-time: %s\n", formatTime(this.startTime))); + sb.append(String.format("\tend-time: %s\n", formatTime(this.endTime))); + sb.append(String.format("\tduration(seconds): %.3f\n", this.timeSeconds())); + sb.append(String.format("\trate(MB/s): %.3f\n", this.rateMPS())); + return sb.toString(); + } + + public static void saveCSVHeader(Writer w) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append("\"Action\"").append(","); + sb.append("\"Number of Threads\"").append(","); + sb.append("\"Use Cluster IO?\"").append(","); + sb.append("\"Use In-Memory File?\"").append(","); + sb.append("\"File Size\"").append(","); + sb.append("\"Number of Files\"").append(","); + sb.append("\"Start Time\"").append(","); + sb.append("\"End Time\"").append(","); + sb.append("\"Duration(Seconds)\"").append(","); + sb.append("\"Rate(MB/s)\"").append(","); + sb.append("\n"); + w.write(sb.toString()); + } + + static String formatTime(long timeMillisecs) { + return new SimpleDateFormat(DateTime.DATE_TIME_MS_FORMAT).format(new Date(timeMillisecs)); + } + +} diff --git a/src/main/java/unimelb/mf/client/perf/TestSettings.java b/src/main/java/unimelb/mf/client/perf/TestSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..7f2c02cb781bc30418b20dba835925f48143b5ac --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/TestSettings.java @@ -0,0 +1,182 @@ +package unimelb.mf.client.perf; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import arc.xml.XmlDoc; +import unimelb.mf.client.session.MFSession; + +public class TestSettings { + + public static final int DEFAULT_NUMBER_OF_THREADS = 1; + public static final int DEFAULT_NUMBER_OF_FILES = 1; + public static final long DEFAULT_FILE_SIZE = 1048576L; // 1 MiB; + + private Set<Action> _actions; + private int _nbThreads; + private int _nbFiles; + private boolean _useClusterIO; + private boolean _useInMemoryFile; + private long _fileSize; + private Path _dir; + private String _namespace; + + public TestSettings() { + _actions = new LinkedHashSet<Action>(); + _nbThreads = DEFAULT_NUMBER_OF_THREADS; + _nbFiles = DEFAULT_NUMBER_OF_FILES; + _useClusterIO = false; + _useInMemoryFile = true; + _fileSize = DEFAULT_FILE_SIZE; + _dir = null; + _namespace = null; + + } + + public TestSettings(XmlDoc.Element e) throws Throwable { + this(); + parse(e); + } + + public boolean ping() { + return _actions.contains(Action.PING); + } + + public boolean upload() { + return _actions.contains(Action.UPLOAD); + } + + public boolean download() { + return _actions.contains(Action.DOWNLOAD); + } + + public int numberOfThreads() { + return _nbThreads; + } + + public int numberOfFiles() { + return _nbFiles; + } + + public boolean useClusterIO() { + return _useClusterIO; + } + + public boolean useInMemoryFile() { + return _useInMemoryFile; + } + + public long fileSize() { + return _fileSize; + } + + public Path directory() { + return _dir; + } + + public String namespace() { + return _namespace; + } + + public TestSettings addAction(Action action) { + _actions.add(action); + return this; + } + + public TestSettings setNumberOfThreads(int nbThreads) { + _nbThreads = nbThreads; + return this; + } + + public TestSettings setNumberOfFiles(int nbFiles) { + _nbFiles = nbFiles; + return this; + } + + public TestSettings setUseClusterIO(boolean useClusterIO) { + _useClusterIO = useClusterIO; + return this; + } + + public TestSettings setUseInMemoryFile(boolean useInMemoryFile) { + _useInMemoryFile = useInMemoryFile; + return this; + } + + public TestSettings setFileSize(long fileSize) { + _fileSize = fileSize; + return this; + } + + public TestSettings setDirectory(Path dir) { + _dir = dir; + return this; + } + + public TestSettings setNamespace(String ns) { + _namespace = ns; + return this; + } + + public TestSettings parse(XmlDoc.Element e) throws Throwable { + if (e != null) { + if (e.elementExists("action")) { + Collection<String> as = e.values("action"); + for (String a : as) { + Action action = Action.fromString(a); + if (a == null) { + throw new IllegalArgumentException("Invalid action: " + a); + } + addAction(action); + } + } + if (e.elementExists("threads")) { + setNumberOfFiles(e.intValue("threads", 1)); + } + if (e.elementExists("numberOfFiles")) { + setNumberOfFiles(e.intValue("numberOfFiles")); + } + if (e.elementExists("useClusterIO")) { + setUseClusterIO(e.booleanValue("useClusterIO")); + } + if (e.elementExists("useInMemoryFile")) { + setUseInMemoryFile(e.booleanValue("useInMemoryFile")); + } + if (e.elementExists("fileSize")) { + setFileSize(e.longValue("fileSize")); + } + if (e.elementExists("directory")) { + Path dir = Paths.get(e.value("directory")); + if (!Files.exists(dir)) { + throw new IllegalArgumentException("Directory: " + dir.toString() + " does not exist."); + } + if (!Files.isDirectory(dir)) { + throw new IllegalArgumentException(dir.toString() + " is not a directory."); + } + setDirectory(dir); + } + if (e.elementExists("namespace")) { + setNamespace(e.value("namespace")); + } + + } + return this; + } + + public void validate(MFSession session) { + if (_actions.isEmpty()) { + throw new IllegalArgumentException("Invalid configuration: missing action."); + } + if (_namespace == null && (_actions.contains(Action.DOWNLOAD) || _actions.contains(Action.UPLOAD))) { + throw new IllegalArgumentException("Invalid configuration: missing namespace."); + } + if (_dir == null && !_useInMemoryFile) { + throw new IllegalArgumentException("Invalid configuration: missing directory."); + } + } + +} diff --git a/src/main/java/unimelb/mf/client/perf/cli/MFPerfCLI.java b/src/main/java/unimelb/mf/client/perf/cli/MFPerfCLI.java new file mode 100644 index 0000000000000000000000000000000000000000..dd56543b2de63b0db417840d27e1fe0ed935b330 --- /dev/null +++ b/src/main/java/unimelb/mf/client/perf/cli/MFPerfCLI.java @@ -0,0 +1,75 @@ +package unimelb.mf.client.perf.cli; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import unimelb.mf.client.perf.MFPerf; +import unimelb.mf.client.perf.MFPerfSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; +import unimelb.mf.client.session.MFSession; + +public class MFPerfCLI { + + public static void main(String[] args) throws Throwable { + + try { + Path configFile = null; + if (args != null) { + for (int i = 0; i < args.length;) { + if ("--config".equalsIgnoreCase(args[i])) { + if (configFile != null) { + throw new IllegalArgumentException( + "Multiple --config configuration files specified. Expects only one."); + } + configFile = Paths.get(args[i + 1]); + if (!Files.exists(configFile)) { + throw new IllegalArgumentException("Cannot find file: " + args[i + 1]); + } + if (!Files.isRegularFile(configFile)) { + throw new IllegalArgumentException("File: " + args[i + 1] + " is not a regular file."); + } + i += 2; + } else { + throw new IllegalArgumentException("Unexpected argument: " + args[i]); + } + } + } + if (configFile == null) { + throw new IllegalArgumentException("No --config configuration file is specified."); + } + + MFConfigurationBuilder mfconfig = new MFConfigurationBuilder(); + mfconfig.loadFromXmlFile(configFile.toFile()); + mfconfig.setApp(MFPerf.APPLICATION_NAME); + + MFSession session = MFSession.create(mfconfig); + + MFPerfSettings settings = MFPerfSettings.parse(configFile.toFile()); + if (settings.testSettings().isEmpty()) { + throw new IllegalArgumentException( + "Failed to parse settings from configuration file: " + configFile.toString()); + } + settings.validate(session); + + new MFPerf(session, settings).call(); + } catch (Throwable e) { + e.printStackTrace(); + if (e instanceof IllegalArgumentException) { + printUsage(); + } + } + + } + + public static void printUsage() { + System.out.println(); + System.out.println("USAGE:"); + System.out.println(String.format(" %s --config <config-file>", MFPerf.APPLICATION_NAME)); + System.out.println(); + System.out.println("DESCRIPTION:"); + System.out.println(" Test network transfer rates to/from the specified Mediaflux server."); + System.out.println(); + } + +} diff --git a/src/main/java/unimelb/mf/client/session/AuthenticationDetailsUtils.java b/src/main/java/unimelb/mf/client/session/AuthenticationDetailsUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..c881e1dbf90863438147f88f545768e9c3edd5fb --- /dev/null +++ b/src/main/java/unimelb/mf/client/session/AuthenticationDetailsUtils.java @@ -0,0 +1,25 @@ +package unimelb.mf.client.session; + +import arc.mf.client.AuthenticationDetails; +import unimelb.mf.client.util.ObjectUtils; + +public class AuthenticationDetailsUtils { + + public static boolean equals(AuthenticationDetails ad1, AuthenticationDetails ad2) { + if (ad1 == ad2) { + return true; + } + if (ad1 == null || ad2 == null) { + return false; + } + return ObjectUtils.equals(ad1.application(), ad2.application()) && ObjectUtils.equals(ad1.token(), ad2.token()) + && ObjectUtils.equals(ad1.domain(), ad2.domain()) && ObjectUtils.equals(ad1.userName(), ad2.userName()) + && ObjectUtils.equals(ad1.userPassword(), ad2.userPassword()) + && ObjectUtils.equals(ad1.loginIdentity(), ad2.loginIdentity()); + } + + public static boolean differ(AuthenticationDetails ad1, AuthenticationDetails ad2) { + return !equals(ad1, ad2); + } + +} diff --git a/src/main/java/unimelb/mf/client/session/MFConfiguration.java b/src/main/java/unimelb/mf/client/session/MFConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..681e3d6a15e6cb20d090b16914a1cf6c99077906 --- /dev/null +++ b/src/main/java/unimelb/mf/client/session/MFConfiguration.java @@ -0,0 +1,82 @@ +package unimelb.mf.client.session; + +import java.io.File; + +import arc.mf.client.AuthenticationDetails; +import arc.mf.client.ConnectionDetails; + +/** + * See src/main/config/mf-sync-properties.sample.xml + * + * @author wliu5 + * + */ +public class MFConfiguration { + + public static final String DEFAULT_MFLUX_CFG_FILE = System.getProperty("user.home") + File.separator + ".Arcitecta" + + File.separator + "mflux.cfg"; + public static final String ENV_MFLUX_CFG = "MFLUX_CFG"; + public static final String PROPERTY_MF_CONFIG = "mf.cfg"; + + private ConnectionDetails _connectionDetails; + private AuthenticationDetails _authenticationDetails; + + private boolean _connectionPooling = true; + private int _connectRetryTimes = MFSession.DEFAULT_CONNECT_RETRY_TIMES; + private int _connectRetryInterval = MFSession.DEFAULT_CONNECT_RETRY_INTERVAL; + private int _executeRetryTimes = MFSession.DEFAULT_EXECUTE_RETRY_TIMES; + private int _executeRetryInterval = MFSession.DEFAULT_EXECUTE_RETRY_INTERVAL; + private String _sessionKey = null; + + public MFConfiguration(ConnectionDetails connectionDetails, AuthenticationDetails authenticationDetails, + boolean connectionPooling, int connectRetryTimes, int connectRetryInterval, int execRetryTimes, + int execRetryInterval, String sessionKey) { + _connectionDetails = connectionDetails; + _authenticationDetails = authenticationDetails; + _connectionPooling = connectionPooling; + _connectRetryTimes = connectRetryTimes; + _connectRetryInterval = connectRetryInterval; + _executeRetryTimes = execRetryTimes; + _executeRetryInterval = execRetryInterval; + _sessionKey = sessionKey; + } + + public MFConfiguration(ConnectionDetails connectionDetails, AuthenticationDetails authenticationDetails) { + this(connectionDetails, authenticationDetails, true, MFSession.DEFAULT_CONNECT_RETRY_TIMES, + MFSession.DEFAULT_CONNECT_RETRY_INTERVAL, MFSession.DEFAULT_EXECUTE_RETRY_TIMES, + MFSession.DEFAULT_EXECUTE_RETRY_INTERVAL, null); + } + + public ConnectionDetails connectionDetails() { + return _connectionDetails; + } + + public AuthenticationDetails authenticationDetails() { + return _authenticationDetails; + } + + public String sessionKey() { + return _sessionKey; + } + + public int executeRetryInterval() { + return _executeRetryInterval; + } + + public int connectRetryInterval() { + return _connectRetryInterval; + } + + public int executeRetryTimes() { + return _executeRetryTimes; + } + + public int connectRetryTimes() { + return _connectRetryTimes; + } + + public boolean connectionPooling() { + return _connectionPooling; + } + +} diff --git a/src/main/java/unimelb/mf/client/session/MFConnectionSettings.java b/src/main/java/unimelb/mf/client/session/MFConfigurationBuilder.java similarity index 62% rename from src/main/java/unimelb/mf/client/session/MFConnectionSettings.java rename to src/main/java/unimelb/mf/client/session/MFConfigurationBuilder.java index d5b9380a013c11cc4203a7ae89d48046c1c066c3..d4c260a96095b2b71186a42828d86efb20892922 100644 --- a/src/main/java/unimelb/mf/client/session/MFConnectionSettings.java +++ b/src/main/java/unimelb/mf/client/session/MFConfigurationBuilder.java @@ -14,72 +14,60 @@ import java.util.List; import java.util.Properties; import arc.mf.client.AuthenticationDetails; +import arc.mf.client.ConnectionDetails; +import arc.mf.client.ConnectionSpec; import arc.xml.XmlDoc; -/** - * See src/main/config/mf-sync-properties.sample.xml - * - * @author wliu5 - * - */ -public class MFConnectionSettings { - - public static final String DEFAULT_MFLUX_CFG_FILE = System.getProperty("user.home") + File.separator + ".Arcitecta" - + File.separator + "mflux.cfg"; - public static final String ENV_MFLUX_CFG = "MFLUX_CFG"; - public static final String PROPERTY_MF_CONFIG = "mf.config"; - - private String _serverHost = null; - private String _serverTransport = null; - private int _serverPort; - private boolean _connectionPooling = true; +public class MFConfigurationBuilder { - private int _connectRetryTimes = MFSession.DEFAULT_CONNECT_RETRY_TIMES; + private boolean _allowUntrustedServer = true; + private String _app = null; + private boolean _connectionPooling = true; private int _connectRetryInterval = MFSession.DEFAULT_CONNECT_RETRY_INTERVAL; - private int _executeRetryTimes = MFSession.DEFAULT_EXECUTE_RETRY_TIMES; - private int _executeRetryInterval = MFSession.DEFAULT_EXECUTE_RETRY_INTERVAL; + private int _connectRetryTimes = MFSession.DEFAULT_CONNECT_RETRY_TIMES; + + private boolean _consoleLogon = true; - private String _app = null; private String _domain = null; - private String _user = null; + private boolean _encrypt = true; + private int _executeRetryInterval = MFSession.DEFAULT_EXECUTE_RETRY_INTERVAL; + private int _executeRetryTimes = MFSession.DEFAULT_EXECUTE_RETRY_TIMES; + + private String _host = null; private String _password = null; - private String _token = null; + private int _port; private String _sessionKey = null; + private String _token = null; + private boolean _useHttp = true; - public MFConnectionSettings() throws Throwable { + private String _user = null; - } + public MFConfigurationBuilder() throws Throwable { - public MFConnectionSettings(Path xmlFile) throws Throwable { - this(xmlFile == null ? null : xmlFile.toFile()); } - public MFConnectionSettings(File xmlFile) throws Throwable { + public MFConfigurationBuilder(File xmlFile) throws Throwable { if (xmlFile != null && xmlFile.exists()) { loadFromXmlFile(xmlFile); } } - public MFConnectionSettings(XmlDoc.Element pe) throws Throwable { + public MFConfigurationBuilder(Path xmlFile) throws Throwable { + this(xmlFile == null ? null : xmlFile.toFile()); + } + + public MFConfigurationBuilder(XmlDoc.Element pe) throws Throwable { if (pe != null) { loadFromXml(pe); } } - private static String parseServerTransport(String proto) throws Exception { - if (proto != null) { - if ("http".equalsIgnoreCase(proto)) { - return "http"; - } - if ("https".equalsIgnoreCase(proto)) { - return "https"; - } - if (proto.toLowerCase().startsWith("tcp")) { - return "tcp/ip"; - } - throw new Exception("Invalid transport protocol: " + proto); - } - return null; + public boolean allowUntrustedServer() { + return _allowUntrustedServer; + } + + public String app() { + return _app; } public AuthenticationDetails authenticationDetails() { @@ -94,18 +82,139 @@ public class MFConnectionSettings { } } + public MFConfiguration build() { + checkMissingArguments(); + return new MFConfiguration(connectionDetails(), authenticationDetails(), connectionPooling(), + connectRetryTimes(), connectRetryInterval(), executeRetryTimes(), executeRetryInterval(), sessionKey()); + } + + public void checkMissingArguments() throws IllegalArgumentException { + if (_host == null) { + throw new IllegalArgumentException("Missing mf.host"); + } + if (_port <= 0) { + throw new IllegalArgumentException("Missing mf.port"); + } + if (transport() == null) { + throw new IllegalArgumentException("Missing mf.transport"); + } + if (_token == null && (_domain == null || _user == null || _password == null) && _sessionKey == null) { + throw new IllegalArgumentException("Missing/Incomplete mf.token or mf.auth."); + } + } + + public ConnectionDetails connectionDetails() { + if (hasConnectionDetails()) { + return new ConnectionSpec().setHostName(_host).setPort(_port).setUseHttp(_useHttp).setEncrypt(_encrypt) + .setAllowUntrustedServer(_allowUntrustedServer).build(); + } else { + return null; + } + } + + public boolean connectionPooling() { + return _connectionPooling; + } + + public int connectRetryInterval() { + return _connectRetryInterval; + } + + public int connectRetryTimes() { + return _connectRetryTimes; + } + + public boolean consoleLogon() { + return _consoleLogon; + } + public String domain() { return _domain; } public boolean encrypt() { - return "https".equalsIgnoreCase(_serverTransport); + return _encrypt; + } + + public int executeRetryInterval() { + return _executeRetryInterval; + } + + public int executeRetryTimes() { + return _executeRetryTimes; + } + + // @formatter:off + /** + * Try finding mflux.cfg file in the following order: + * 1. try system property: mf.cfg + * 2. try system environment variable: MFLUX_CFG + * 3. try default location: $HOME/.Arcitecta/mflux.cfg + * @return the absolute path of the configuration file. if not found, return null. + * @throws Throwable + */ + // @formatter:on + public String findAndLoadFromConfigFile() throws Throwable { + String cfgFile = System.getProperty(MFConfiguration.PROPERTY_MF_CONFIG); + + /* + * try system property: mf.cfg + */ + if (cfgFile != null) { + File f = new File(cfgFile); + if (f.exists()) { + loadFromConfigFile(f); + return f.getAbsolutePath(); + } + } + + /* + * try system environment variable: MFLUX_CFG + */ + cfgFile = System.getenv(MFConfiguration.ENV_MFLUX_CFG); + if (cfgFile != null) { + File f = new File(cfgFile); + if (f.exists()) { + loadFromConfigFile(f); + return f.getAbsolutePath(); + } + } + + /* + * try default location: $HOME/.Arcitecta/mflux.cfg + */ + cfgFile = MFConfiguration.DEFAULT_MFLUX_CFG_FILE; + if (cfgFile != null) { + File f = new File(cfgFile); + if (f.exists()) { + loadFromConfigFile(f); + return f.getAbsolutePath(); + } + } + return null; } public boolean hasAuthenticationDetails() { return hasToken() || hasUserCredentials(); } + public boolean hasConnectionDetails() { + return _host != null && _port > 0; + } + + public boolean hasMissingArgument() { + if (_host == null) { + return true; + } + if (_port <= 0) { + return true; + } + if (_token == null && (_domain == null || _user == null || _password == null) && _sessionKey == null) { + return true; + } + return false; + } + public boolean hasSessionKey() { return _sessionKey != null; } @@ -118,23 +227,144 @@ public class MFConnectionSettings { return _domain != null && _user != null && _password != null; } + public String host() { + return _host; + } + + public void loadFromConfigFile(File configFile) throws Exception { + Properties props = new Properties(); + InputStream in = new BufferedInputStream(new FileInputStream(configFile)); + try { + props.load(in); + if (props.containsKey("host")) { + String host = props.getProperty("host"); + if (host != null) { + host = host.trim(); + if (!host.isEmpty()) { + setHost(host); + } + } + } + if (props.containsKey("port")) { + String portStr = props.getProperty("port"); + if (portStr != null) { + portStr = portStr.trim(); + if (!portStr.isEmpty()) { + int port = Integer.parseInt(portStr); + setPort(port); + } + } + } + if (props.containsKey("transport")) { + String transport = props.getProperty("transport"); + if (transport != null) { + transport = transport.trim(); + if (!transport.isEmpty()) { + setTransport(transport); + } + } + } + if (props.containsKey("domain")) { + String domain = props.getProperty("domain"); + if (domain != null) { + domain = domain.trim(); + if (!domain.isEmpty()) { + setDomain(domain); + } + } + } + if (props.containsKey("user")) { + String user = props.getProperty("user"); + if (user != null) { + user = user.trim(); + if (!user.isEmpty()) { + setUser(user); + } + } + } + if (props.containsKey("password")) { + String password = props.getProperty("password"); + if (password != null) { + password = password.trim(); + if (!password.isEmpty()) { + setPassword(password); + } + } + } + if (props.containsKey("token")) { + String token = props.getProperty("token"); + if (token != null) { + token = token.trim(); + if (!token.isEmpty()) { + setToken(token); + } + } + } + } finally { + in.close(); + } + } + + public void loadFromConfigFile(String configFile) throws Exception { + loadFromConfigFile(new File(configFile)); + } + + /** + * Load the specified Mediaflux configuration file. If the specified file is + * null or the file is not found. Try finding and loading the file specified + * in 1) system property; 2) system environment variable 3) default + * location: $HOME/.Arcitecta/mflux.cfg + * + * @param configFile + * @throws Throwable + */ + public String loadFromConfigFileOrFind(String configFile) throws Throwable { + if (configFile != null) { + File cfgFile = new File(configFile); + if (cfgFile.exists()) { + loadFromConfigFile(cfgFile); + return cfgFile.getAbsolutePath(); + } + } + return findAndLoadFromConfigFile(); + } + private void loadFromXml(XmlDoc.Element pe) throws Throwable { // @formatter:off - _serverHost = pe.value("server/host"); - _serverTransport = parseServerTransport(pe.value("server/protocol")); - _serverPort = pe.intValue("server/port", 0); - if (_serverPort == 0) { - if ("http".equalsIgnoreCase(_serverTransport)) { - _serverPort = 80; + _host = pe.value("server/host"); + _port = pe.intValue("server/port", 0); + + String transport = "HTTPS"; + if(pe.elementExists("server/transport")) { + transport = pe.stringValue("server/transport", "HTTPS"); + } else { + // back compatible with old element name: protocol + transport = pe.stringValue("server/protocol", "HTTPS"); + } + + if ("HTTP".equalsIgnoreCase(transport)) { + _useHttp = true; + _encrypt = false; + if (_port == 0) { + _port = 80; } - if ("https".equalsIgnoreCase(_serverTransport)) { - _serverPort = 443; + } + if ("HTTPS".equalsIgnoreCase(transport)) { + _useHttp = true; + _encrypt = true; + if (_port == 0) { + _port = 443; } - if ("tcp/ip".equalsIgnoreCase(_serverTransport)) { - _serverPort = 1967; + } + if (transport.toLowerCase().startsWith("tcp")) { + _useHttp = false; + _encrypt = false; + if (_port == 0) { + _port = 1967; } } + _connectRetryTimes = pe.intValue("server/session/connectRetryTimes", MFSession.DEFAULT_CONNECT_RETRY_TIMES); _connectRetryInterval = pe.intValue("server/session/connectRetryInterval", MFSession.DEFAULT_CONNECT_RETRY_INTERVAL); _executeRetryTimes = pe.intValue("server/session/executeRetryTimes", MFSession.DEFAULT_EXECUTE_RETRY_TIMES); @@ -160,40 +390,85 @@ public class MFConnectionSettings { } } - public String password() { - return _password; - } - - public String serverHost() { - return _serverHost; - } - - public int serverPort() { - return _serverPort; - } - - public String serverTransport() { - return _serverTransport; - } - - public String sessionKey() { - return _sessionKey; - } - - public MFConnectionSettings setApp(String app) { - _app = app; - return this; + public List<String> parseArgs(String[] args) throws Throwable { + return parseArgs(args, 0, args.length); } - public MFConnectionSettings setDomain(String domain) { - _domain = domain; - return this; - } + public List<String> parseArgs(String[] args, int offset, int length) throws Throwable { - public MFConnectionSettings readDomainFromConsole(Console console) { - String domain = null; - do { - domain = _domain == null ? console.readLine("Domain: ") : console.readLine("Domain[%s]: ", _domain); + List<String> remainArgs = new ArrayList<String>(); + for (int i = offset; i < offset + length;) { + if ("--mf.config".equalsIgnoreCase(args[i])) { + try { + loadFromConfigFile(args[i + 1]); + } catch (Throwable e) { + throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); + } + i += 2; + } else if ("--mf.host".equalsIgnoreCase(args[i])) { + setHost(args[i + 1]); + i += 2; + } else if ("--mf.port".equalsIgnoreCase(args[i])) { + setPort(Integer.parseInt(args[i + 1])); + i += 2; + } else if ("--mf.transport".equalsIgnoreCase(args[i])) { + setTransport(args[i + 1]); + i += 2; + } else if ("--mf.auth".equalsIgnoreCase(args[i])) { + String auth = args[i + 1]; + String[] parts = auth.split(","); + if (parts == null || parts.length != 3) { + throw new IllegalArgumentException("Invalid mf.auth: " + auth); + } + setUserCredentials(parts[0], parts[1], parts[2]); + i += 2; + } else if ("--mf.token".equalsIgnoreCase(args[i])) { + setToken(args[i + 1]); + i += 2; + } else { + remainArgs.add(args[i]); + i++; + } + } + + return remainArgs; + } + + private void parseTransport(String proto) { + if (proto != null) { + proto = proto.trim(); + if (!proto.isEmpty()) { + if ("HTTP".equalsIgnoreCase(proto)) { + _useHttp = true; + _encrypt = false; + return; + } else if ("HTTPS".equalsIgnoreCase(proto)) { + _useHttp = true; + _encrypt = true; + return; + } else if (proto.toLowerCase().startsWith("tcp")) { + _useHttp = false; + _encrypt = false; + return; + } else { + throw new IllegalArgumentException("Invalid transport protocol: " + proto); + } + } + } + } + + public String password() { + return _password; + } + + public int port() { + return _port; + } + + public MFConfigurationBuilder readDomainFromConsole(Console console) { + String domain = null; + do { + domain = _domain == null ? console.readLine("Domain: ") : console.readLine("Domain[%s]: ", _domain); if (_domain != null && domain != null && domain.trim().isEmpty()) { // use existing value, no change return this; @@ -204,12 +479,7 @@ public class MFConnectionSettings { return this; } - public MFConnectionSettings setPassword(String password) { - _password = password; - return this; - } - - public MFConnectionSettings readPasswordFromConsole(Console console) { + public MFConfigurationBuilder readPasswordFromConsole(Console console) { String password = null; do { char[] pwd = console.readPassword("Password: "); @@ -222,53 +492,25 @@ public class MFConnectionSettings { return this; } - public MFConnectionSettings setServer(String host, int port, boolean useHttp, boolean encrypt) { - _serverHost = host; - _serverPort = port; - if (useHttp) { - _serverTransport = encrypt ? "https" : "http"; - } else { - _serverTransport = "tcp/ip"; - } - return this; - } - - public MFConnectionSettings setServer(String host, int port, String transport) throws Exception { - _serverHost = host; - _serverPort = port; - setServerTransport(transport); - return this; - } - - public MFConnectionSettings setServerHost(String host) { - _serverHost = host; - return this; - } - - public MFConnectionSettings readServerHostFromConsole(Console console) { + public MFConfigurationBuilder readServerHostFromConsole(Console console) { String host = null; do { - host = _serverHost == null ? console.readLine("Host: ") : console.readLine("Host[%s]: ", _serverHost); - if (_serverHost != null && host != null && host.trim().isEmpty()) { + host = _host == null ? console.readLine("Host: ") : console.readLine("Host[%s]: ", _host); + if (_host != null && host != null && host.trim().isEmpty()) { // use existing value, no change return this; } } while (host == null || host.trim().isEmpty()); - _serverHost = host.trim(); + _host = host.trim(); return this; } - public MFConnectionSettings setServerPort(int port) { - _serverPort = port; - return this; - } - - public MFConnectionSettings readServerPortFromConsole(Console console) { + public MFConfigurationBuilder readServerPortFromConsole(Console console) { int port = -1; do { - String p = _serverPort <= 0 ? console.readLine("Port: ") : console.readLine("Port[%d]: ", _serverPort); - if (_serverPort > 0 && p != null && p.trim().isEmpty()) { + String p = _port <= 0 ? console.readLine("Port: ") : console.readLine("Port[%d]: ", _port); + if (_port > 0 && p != null && p.trim().isEmpty()) { // use existing value, no change return this; } @@ -284,57 +526,35 @@ public class MFConnectionSettings { } } while (port <= 0 || port > 65535); - _serverPort = port; - return this; - } - - public MFConnectionSettings setServerTransport(String transport) throws Exception { - _serverTransport = parseServerTransport(transport); + _port = port; return this; } - public MFConnectionSettings readServerTransportFromConsole(Console console) { - String transport = null; - do { - transport = _serverTransport == null ? console.readLine("Transport(https/http/tcpip): ") - : console.readLine("Transport[%s]: ", _serverTransport); - if (_serverTransport != null && transport != null && transport.trim().isEmpty()) { - // use existing value, no change - return this; - } + public MFConfigurationBuilder readServerTransportFromConsole(Console console) { + while (true) { + String transport = console.readLine("Transport(HTTP/HTTPS/TCP_IP)[%s]: ", transport()); if (transport != null) { - transport = transport.trim(); - if (!transport.equalsIgnoreCase("http") && !transport.equalsIgnoreCase("https") - && !transport.toLowerCase().startsWith("tcp")) { - // invalid value - console.printf("%n"); - console.printf("Invalid transport: %s. Expects http, https or tcp/ip%n", transport); - console.printf("%n"); - transport = null; + if (transport.trim().isEmpty()) { + // use existing value, no change + return this; + } else { + transport = transport.trim(); + if (!transport.equalsIgnoreCase("HTTP") && !transport.equalsIgnoreCase("HTTPS") + && !transport.toLowerCase().startsWith("tcp")) { + // invalid value + console.printf("%n"); + console.printf("Invalid transport: %s. Expects HTTP, HTTPS or TCP_IP%n", transport); + console.printf("%n"); + } else { + parseTransport(transport); + return this; + } } } - } while (transport == null || transport.isEmpty()); - - _serverTransport = transport; - return this; - } - - public MFConnectionSettings setSessionKey(String sessionKey) { - _sessionKey = sessionKey; - return this; - } - - public MFConnectionSettings setToken(String token) { - _token = token; - return this; - } - - public MFConnectionSettings setUser(String user) { - _user = user; - return this; + } } - public MFConnectionSettings readUserFromConsole(Console console) { + public MFConfigurationBuilder readUserFromConsole(Console console) { String user = null; do { user = _user == null ? console.readLine("User: ") : console.readLine("User[%s]: ", _user); @@ -348,290 +568,150 @@ public class MFConnectionSettings { return this; } - public MFConnectionSettings setUserCredentials(String domain, String user, String password) { - _domain = domain; - _user = user; - _password = password; - return this; + public String sessionKey() { + return _sessionKey; } - public String token() { - return _token; + public MFConfigurationBuilder setAllowUntrustedServer(boolean allowUntrustedServer) { + _allowUntrustedServer = allowUntrustedServer; + return this; } - public boolean useHttp() { - return "https".equalsIgnoreCase(_serverTransport) || "http".equalsIgnoreCase(_serverTransport); + public MFConfigurationBuilder setApp(String app) { + _app = app; + return this; } - public String user() { - return _user; + public MFConfigurationBuilder setAuthenticationDetails(AuthenticationDetails authenticationDetails) { + _domain = authenticationDetails.domain(); + _user = authenticationDetails.userName(); + _password = authenticationDetails.userPassword(); + _token = authenticationDetails.token(); + _app = authenticationDetails.application(); + return this; } - public MFConnectionSettings setConnectRetryTimes(int retryTimes) { - _connectRetryTimes = retryTimes; + public MFConfigurationBuilder setConnectionDetails(ConnectionDetails connectionDetails) { + _host = connectionDetails.hostName(); + if (_host == null) { + _host = connectionDetails.hostAddressOrName(); + } + _port = connectionDetails.port(); + _useHttp = connectionDetails.useHttp(); + _encrypt = connectionDetails.encrypt(); + _allowUntrustedServer = connectionDetails.allowUntrustedServer(); return this; } - public int connectRetryTimes() { - return _connectRetryTimes; + public void setConnectionPooling(boolean connectionPooling) { + _connectionPooling = connectionPooling; } - public MFConnectionSettings setConnectRetryInterval(int millisecs) { + public MFConfigurationBuilder setConnectRetryInterval(int millisecs) { _connectRetryInterval = millisecs; return this; } - public int connectRetryInterval() { - return _connectRetryInterval; + public MFConfigurationBuilder setConnectRetryTimes(int retryTimes) { + _connectRetryTimes = retryTimes; + return this; } - public MFConnectionSettings setExecuteRetryTimes(int retryTimes) { - _executeRetryTimes = retryTimes; + public MFConfigurationBuilder setConsoleLogon(boolean consoleLogon) { + _consoleLogon = consoleLogon; return this; } - public int executeRetryTimes() { - return _executeRetryTimes; + public MFConfigurationBuilder setDomain(String domain) { + _domain = domain; + return this; } - public MFConnectionSettings setExecuteRetryInterval(int millisecs) { + public MFConfigurationBuilder setExecuteRetryInterval(int millisecs) { _executeRetryInterval = millisecs; return this; } - public int executeRetryInterval() { - return _executeRetryInterval; + public MFConfigurationBuilder setExecuteRetryTimes(int retryTimes) { + _executeRetryTimes = retryTimes; + return this; } - public boolean connectionPooling() { - return _connectionPooling; + public MFConfigurationBuilder setHost(String host) { + _host = host; + return this; } - public void setConnectionPooling(boolean connectionPooling) { - _connectionPooling = connectionPooling; + public MFConfigurationBuilder setPassword(String password) { + _password = password; + return this; } - public void checkMissingArguments() throws Throwable { - if (_serverHost == null) { - throw new IllegalArgumentException("Missing mf.host"); - } - if (_serverPort <= 0) { - throw new IllegalArgumentException("Missing mf.port"); - } - if (serverTransport() == null) { - throw new IllegalArgumentException("Missing mf.transport"); - } - if (_token == null && (_domain == null || _user == null || _password == null) && _sessionKey == null) { - throw new IllegalArgumentException("Missing/Incomplete mf.token or mf.auth."); - } + public MFConfigurationBuilder setPort(int port) { + _port = port; + return this; } - public boolean hasMissingArgument() { - if (_serverHost == null) { - return true; - } - if (_serverPort <= 0) { - return true; - } - if (serverTransport() == null) { - return true; - } - if (_token == null && (_domain == null || _user == null || _password == null) && _sessionKey == null) { - return true; - } - return false; + public MFConfigurationBuilder setServer(String host, int port, boolean useHttp, boolean encrypt) { + _host = host; + _port = port; + _useHttp = useHttp; + _encrypt = encrypt; + return this; } - public void loadFromConfigFile(String configFile) throws Exception { - loadFromConfigFile(new File(configFile)); + public MFConfigurationBuilder setServer(String host, int port, String transport) throws Exception { + _host = host; + _port = port; + setTransport(transport); + return this; } - public void loadFromConfigFile(File configFile) throws Exception { - Properties props = new Properties(); - InputStream in = new BufferedInputStream(new FileInputStream(configFile)); - try { - props.load(in); - if (props.containsKey("host")) { - String host = props.getProperty("host"); - if (host != null) { - host = host.trim(); - if (!host.isEmpty()) { - setServerHost(host); - } - } - } - if (props.containsKey("port")) { - String portStr = props.getProperty("port"); - if (portStr != null) { - portStr = portStr.trim(); - if (!portStr.isEmpty()) { - int port = Integer.parseInt(portStr); - setServerPort(port); - } - } - } - if (props.containsKey("transport")) { - String transport = props.getProperty("transport"); - if (transport != null) { - transport = transport.trim(); - if (!transport.isEmpty()) { - setServerTransport(transport); - } - } - } - if (props.containsKey("domain")) { - String domain = props.getProperty("domain"); - if (domain != null) { - domain = domain.trim(); - if (!domain.isEmpty()) { - setDomain(domain); - } - } - } - if (props.containsKey("user")) { - String user = props.getProperty("user"); - if (user != null) { - user = user.trim(); - if (!user.isEmpty()) { - setUser(user); - } - } - } - if (props.containsKey("password")) { - String password = props.getProperty("password"); - if (password != null) { - password = password.trim(); - if (!password.isEmpty()) { - setPassword(password); - } - } - } - if (props.containsKey("token")) { - String token = props.getProperty("token"); - if (token != null) { - token = token.trim(); - if (!token.isEmpty()) { - setToken(token); - } - } - } - } finally { - in.close(); - } + public MFConfigurationBuilder setSessionKey(String sessionKey) { + _sessionKey = sessionKey; + return this; } - // @formatter:off - /** - * Try finding mflux.cfg file in the following order: - * 1. try system property: mf.config - * 2. try system environment variable: MFLUX_CFG - * 3. try default location: $HOME/.Arcitecta/mflux.cfg - * @return the absolute path of the configuration file. if not found, return null. - * @throws Throwable - */ - // @formatter:on - public String findAndLoadFromConfigFile() throws Throwable { - String cfgFile = System.getProperty(PROPERTY_MF_CONFIG); - - /* - * try system property: mf.config - */ - if (cfgFile != null) { - File f = new File(cfgFile); - if (f.exists()) { - loadFromConfigFile(f); - return f.getAbsolutePath(); - } - } - - /* - * try system environment variable: MFLUX_CFG - */ - cfgFile = System.getenv(ENV_MFLUX_CFG); - if (cfgFile != null) { - File f = new File(cfgFile); - if (f.exists()) { - loadFromConfigFile(f); - return f.getAbsolutePath(); - } - } + public MFConfigurationBuilder setToken(String token) { + _token = token; + return this; + } - /* - * try default location: $HOME/.Arcitecta/mflux.cfg - */ - cfgFile = DEFAULT_MFLUX_CFG_FILE; - if (cfgFile != null) { - File f = new File(cfgFile); - if (f.exists()) { - loadFromConfigFile(f); - return f.getAbsolutePath(); - } - } - return null; + public MFConfigurationBuilder setTransport(String transport) throws Exception { + parseTransport(transport); + return this; } - /** - * Load the specified Mediaflux configuration file. If the specified file is - * null or the file is not found. Try finding and loading the file specified - * in 1) system property; 2) system environment variable 3) default - * location: $HOME/.Arcitecta/mflux.cfg - * - * @param configFile - * @throws Throwable - */ - public String loadFromConfigFileOrFind(String configFile) throws Throwable { - if (configFile != null) { - File cfgFile = new File(configFile); - if (cfgFile.exists()) { - loadFromConfigFile(cfgFile); - return cfgFile.getAbsolutePath(); - } - } - return findAndLoadFromConfigFile(); + public MFConfigurationBuilder setUser(String user) { + _user = user; + return this; } - public List<String> parseArgs(String[] args) throws Throwable { - return parseArgs(args, 0, args.length); + public MFConfigurationBuilder setUserCredentials(String domain, String user, String password) { + _domain = domain; + _user = user; + _password = password; + return this; } - public List<String> parseArgs(String[] args, int offset, int length) throws Throwable { + public String token() { + return _token; + } - List<String> remainArgs = new ArrayList<String>(); - for (int i = offset; i < offset + length;) { - if ("--mf.config".equalsIgnoreCase(args[i])) { - try { - loadFromConfigFile(args[i + 1]); - } catch (Throwable e) { - throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); - } - i += 2; - } else if ("--mf.host".equalsIgnoreCase(args[i])) { - setServerHost(args[i + 1]); - i += 2; - } else if ("--mf.port".equalsIgnoreCase(args[i])) { - setServerPort(Integer.parseInt(args[i + 1])); - i += 2; - } else if ("--mf.transport".equalsIgnoreCase(args[i])) { - setServerTransport(args[i + 1]); - i += 2; - } else if ("--mf.auth".equalsIgnoreCase(args[i])) { - String auth = args[i + 1]; - String[] parts = auth.split(","); - if (parts == null || parts.length != 3) { - throw new IllegalArgumentException("Invalid mf.auth: " + auth); - } - setUserCredentials(parts[0], parts[1], parts[2]); - i += 2; - } else if ("--mf.token".equalsIgnoreCase(args[i])) { - setToken(args[i + 1]); - i += 2; - } else { - remainArgs.add(args[i]); - i++; - } + public String transport() { + if (_useHttp) { + return _encrypt ? "HTTPS" : "HTTP"; + } else { + return "TCP_IP"; } + } - return remainArgs; + public boolean useHttp() { + return _useHttp; + } + + public String user() { + return _user; } } diff --git a/src/main/java/unimelb/mf/client/session/MFRequest.java b/src/main/java/unimelb/mf/client/session/MFRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..131e46bb84956cb4418d77a21abfbed74e2c76fd --- /dev/null +++ b/src/main/java/unimelb/mf/client/session/MFRequest.java @@ -0,0 +1,34 @@ +package unimelb.mf.client.session; + +import java.util.List; + +import arc.mf.client.RequestOptions; +import arc.mf.client.ServerClient; +import arc.mf.client.ServerRoute; +import arc.xml.XmlDoc; + +public interface MFRequest { + + ServerRoute route(); + + String service(); + + String args(); + + List<ServerClient.Input> inputs(); + + ServerClient.Output output(); + + RequestOptions options(); + + default XmlDoc.Element execute(MFSession session) throws Throwable { + return session.execute(route(), service(), args(), inputs(), output(), options()); + } + + void abort() throws Throwable; + + public static MFRequest create(ServerRoute route, String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, RequestOptions options) { + return new MFRequestBuilder().build(route, service, args, inputs, output, options); + } +} diff --git a/src/main/java/unimelb/mf/client/session/MFRequestBuilder.java b/src/main/java/unimelb/mf/client/session/MFRequestBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..b8a06756dba901390eb811f1df5f72698b3c35f4 --- /dev/null +++ b/src/main/java/unimelb/mf/client/session/MFRequestBuilder.java @@ -0,0 +1,113 @@ +package unimelb.mf.client.session; + +import java.util.ArrayList; +import java.util.List; + +import arc.mf.client.RequestOptions; +import arc.mf.client.ServerClient; +import arc.mf.client.ServerRoute; +import arc.mf.client.ServiceSequenceListener; +import arc.mf.client.ServiceStatusHandler; +import arc.utils.AbortableOperationHandler; + +public class MFRequestBuilder { + + private ServerRoute _route; + private String _service; + private String _args; + private List<ServerClient.Input> _inputs; + private ServerClient.Output _output; + private RequestOptions _options; + + public MFRequestBuilder() { + _options = new RequestOptions(); + } + + public MFRequestBuilder setRoute(ServerRoute route) { + _route = route; + return this; + } + + public MFRequestBuilder setService(String service) { + _service = service; + return this; + } + + public MFRequestBuilder setArgs(String args) { + _args = args; + return this; + } + + public MFRequestBuilder setInputs(List<ServerClient.Input> inputs) { + if (inputs == null || inputs.isEmpty()) { + _inputs = null; + } else { + _inputs = new ArrayList<ServerClient.Input>(inputs); + } + return this; + } + + public MFRequestBuilder addInput(ServerClient.Input input) { + if (_inputs == null) { + _inputs = new ArrayList<ServerClient.Input>(); + } + _inputs.add(input); + return this; + } + + public MFRequestBuilder setOutput(ServerClient.Output output) { + _output = output; + return this; + } + + public MFRequestBuilder setOptions(RequestOptions options) { + _options = options == null ? new RequestOptions() : options; + return this; + } + + public MFRequestBuilder setAbortHandler(AbortableOperationHandler ah) { + _options.setAbortHandler(ah); + return this; + } + + public MFRequestBuilder setBackground(boolean background) { + _options.setBackground(background); + return this; + } + + public MFRequestBuilder setDescription(String description) { + _options.setDescription(description); + return this; + } + + public MFRequestBuilder setKey(String key) { + _options.setKey(key); + return this; + } + + public MFRequestBuilder setRetainHours(int retainHours) { + _options.setRetainHours(retainHours); + return this; + } + + public MFRequestBuilder setSequenceListener(ServiceSequenceListener sequenceListener) { + _options.setSequenceListener(sequenceListener); + return this; + } + + public MFRequestBuilder setStatusHandler(ServiceStatusHandler statusHandler, int waitTime) { + _options.setStatusHandler(statusHandler, waitTime); + return this; + } + + public MFRequest build() { + return new MFRequestImpl(_route, _service, _args, _inputs, _output, _options); + } + + public MFRequest build(ServerRoute route, String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, RequestOptions options) { + return setRoute(route).setService(service).setArgs(args).setInputs(inputs).setOutput(output).setOptions(options) + .build(); + } + +} diff --git a/src/main/java/unimelb/mf/client/session/MFRequestImpl.java b/src/main/java/unimelb/mf/client/session/MFRequestImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..7de530a2a8b4d81bf8abcd7c50b9d0f41308d86e --- /dev/null +++ b/src/main/java/unimelb/mf/client/session/MFRequestImpl.java @@ -0,0 +1,116 @@ +package unimelb.mf.client.session; + +import java.util.Collections; +import java.util.List; + +import arc.mf.client.RequestOptions; +import arc.mf.client.ServerClient; +import arc.mf.client.ServerRoute; +import arc.utils.AbortableOperationHandler; +import arc.utils.CanAbort; + +public class MFRequestImpl implements MFRequest { + + private ServerRoute _route; + private String _service; + private String _args; + private List<ServerClient.Input> _inputs; + private ServerClient.Output _output; + private RequestOptions _ops; + private CanAbort _ca; + + protected MFRequestImpl(ServerRoute route, String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, RequestOptions options) { + _route = route; + _service = service; + _args = args; + _inputs = inputs; + _output = output; + _ops = copy(options); + if (_ops == null) { + _ops = new RequestOptions(); + } + final AbortableOperationHandler ah = _ops.abortHandler(); + _ops.setAbortHandler(new AbortableOperationHandler() { + + @Override + public void finished(CanAbort ca) { + _ca = null; + if (ah != null) { + ah.finished(ca); + } + } + + @Override + public void started(CanAbort ca) { + _ca = ca; + if (ah != null) { + ah.started(ca); + } + } + }); + } + + @Override + public ServerRoute route() { + return _route; + } + + @Override + public String service() { + return _service; + } + + @Override + public String args() { + return _args; + } + + @Override + public List<ServerClient.Input> inputs() { + if (_inputs == null) { + return null; + } else { + return Collections.unmodifiableList(_inputs); + } + } + + @Override + public ServerClient.Output output() { + return _output; + } + + @Override + public RequestOptions options() { + if (_ops == null) { + return null; + } else { + // Make a copy to guarantee immutability. + return copy(_ops); + } + } + + @Override + public void abort() throws Throwable { + if (_ca != null) { + _ca.abort(); + _ca = null; + } + } + + public static RequestOptions copy(RequestOptions options) { + if (options == null) { + return null; + } + RequestOptions ops = new RequestOptions(); + ops.setAbortHandler(options.abortHandler()); + ops.setBackground(options.background()); + ops.setDescription(options.description()); + ops.setKey(options.key()); + ops.setRetainHours(options.retainHours()); + ops.setSequenceListener(options.sequenceListener()); + ops.setStatusHandler(options.statusHandler(), 1000); + return ops; + } + +} diff --git a/src/main/java/unimelb/mf/client/session/MFService.java b/src/main/java/unimelb/mf/client/session/MFService.java deleted file mode 100644 index 324d3206d9b0eb219b17db835979028ebd74bc0b..0000000000000000000000000000000000000000 --- a/src/main/java/unimelb/mf/client/session/MFService.java +++ /dev/null @@ -1,49 +0,0 @@ -package unimelb.mf.client.session; - -import java.util.List; - -import arc.mf.client.ServerClient; -import arc.xml.XmlDoc; -import arc.xml.XmlStringWriter; -import arc.xml.XmlWriter; - -public interface MFService { - - String name(); - - void serviceArgs(XmlWriter w) throws Throwable; - - default void validateArgs() throws IllegalArgumentException { - - } - - default List<ServerClient.Input> inputs() { - return null; - } - - default ServerClient.Output output() { - return null; - } - - default long executeBackground(MFSession session) throws Throwable { - validateArgs(); - XmlStringWriter w = new XmlStringWriter(); - w.add("background", true); - w.push("service", new String[] { "name", name() }); - serviceArgs(w); - w.pop(); - return session.execute("service.execute", w.document(), inputs(), output()).longValue("id"); - } - - default XmlDoc.Element execute(MFSession session) throws Throwable { - validateArgs(); - return session.execute(name(), serviceArgs(), inputs(), output()); - } - - default String serviceArgs() throws Throwable { - XmlStringWriter w = new XmlStringWriter(); - serviceArgs(w); - return w.document(); - } - -} diff --git a/src/main/java/unimelb/mf/client/session/MFSession.java b/src/main/java/unimelb/mf/client/session/MFSession.java index 658414b626516d991675cbaa0304db6bbccb267e..38ba94dd3ff60ab32cb8364c357e5363a78eb63d 100644 --- a/src/main/java/unimelb/mf/client/session/MFSession.java +++ b/src/main/java/unimelb/mf/client/session/MFSession.java @@ -7,14 +7,14 @@ import java.util.Timer; import java.util.TimerTask; import arc.mf.client.AuthenticationDetails; +import arc.mf.client.ConnectionDetails; import arc.mf.client.RemoteServer; import arc.mf.client.RequestOptions; import arc.mf.client.ServerClient; import arc.mf.client.ServerClient.Input; +import arc.mf.client.ServerRoute; import arc.utils.AbortableOperationHandler; -import arc.utils.CanAbort; import arc.xml.XmlDoc; -import unimelb.mf.client.util.HasAbortableOperation; public class MFSession { @@ -23,195 +23,181 @@ public class MFSession { public static final int DEFAULT_EXECUTE_RETRY_TIMES = 1; public static final int DEFAULT_EXECUTE_RETRY_INTERVAL = 0; - private MFConnectionSettings _settings; - private RemoteServer _rs; - private AuthenticationDetails _auth; - private String _sessionId; + private AuthenticationDetails _ad; + private String _sessionKey; + + private int _connectRetryTimes = DEFAULT_CONNECT_RETRY_TIMES; + private int _connectRetryInterval = DEFAULT_CONNECT_RETRY_INTERVAL; + private int _executeRetryTimes = DEFAULT_EXECUTE_RETRY_TIMES; + private int _executeRetryInterval = DEFAULT_EXECUTE_RETRY_INTERVAL; + private Timer _timer; - public MFSession(MFConnectionSettings settings) { - _settings = settings; + protected MFSession(RemoteServer rs, AuthenticationDetails ad, String sessionKey, int connectRetryTimes, + int connectRetryInterval, int executeRetryTimes, int executeRetryInterval) { + _rs = rs; + _ad = ad; + _sessionKey = sessionKey; + + _connectRetryTimes = connectRetryTimes; + _connectRetryInterval = connectRetryInterval; + _executeRetryTimes = executeRetryTimes; + _executeRetryInterval = executeRetryInterval; } - public synchronized String sessionId() { - return _sessionId; + public void authenticate(AuthenticationDetails authenticationDetails) throws Throwable { + ServerClient.Connection cxn = null; + try { + cxn = connect(_rs.connectionDetails(), authenticationDetails); + } finally { + if (cxn != null) { + cxn.close(_rs.usingConnectionPooling() ? false : true); + } + } } - private synchronized void setSessionId(String sessionId) { - _sessionId = sessionId; + public ServerClient.Connection connect(ConnectionDetails connectionDetails, + AuthenticationDetails authenticationDetails) throws Throwable { + return connect(connectionDetails, authenticationDetails, _connectRetryTimes); } public ServerClient.Connection connect() throws Throwable { - return connect(_settings.connectRetryTimes()); + return connect(_rs.connectionDetails(), _ad, _connectRetryTimes); } - private synchronized ServerClient.Connection connect(int retryTimes) throws Throwable { - if (_rs == null) { - _rs = new RemoteServer(_settings.serverHost(), _settings.serverPort(), _settings.useHttp(), - _settings.encrypt()); - _rs.setConnectionPooling(_settings.connectionPooling()); - _rs.enableConnectionPooling(); + private synchronized ServerClient.Connection connect(ConnectionDetails connectionDetails, + AuthenticationDetails authenticationDetails, int retryTimes) throws Throwable { + if (!_rs.connectionDetails().equals(connectionDetails)) { + boolean connectionPooling = _rs.usingConnectionPooling(); + _rs.discard(); + + _rs = new RemoteServer(connectionDetails); + _rs.setConnectionPooling(connectionPooling); } ServerClient.Connection cxn = null; try { cxn = _rs.open(); - String sessionId = sessionId(); - if (sessionId != null) { - cxn.reconnect(sessionId); + if (_sessionKey != null && AuthenticationDetailsUtils.equals(_ad, authenticationDetails)) { + cxn.reconnect(_sessionKey); } else { - setSessionId(cxn.connect(_auth == null ? _settings.authenticationDetails() : _auth)); + _sessionKey = cxn.connect(authenticationDetails); + _ad = authenticationDetails; } - _auth = cxn.authenticationDetails(); return cxn; } catch (java.net.ConnectException ce) { if (retryTimes > 0) { ce.printStackTrace(); System.out.println( "Failed to connect Mediaflux server: " + _rs.host() + ":" + _rs.port() + ". Retrying ..."); - if (_settings.connectRetryInterval() > 0) { - Thread.sleep(_settings.connectRetryInterval()); + if (_connectRetryInterval > 0) { + Thread.sleep(_connectRetryInterval); } - return connect(--retryTimes); + return connect(connectionDetails, authenticationDetails, --retryTimes); } else { throw ce; } } } - public XmlDoc.Element execute(String service, String args, ServerClient.Input input, ServerClient.Output output, - HasAbortableOperation abortable) throws Throwable { - return execute(service, args, input == null ? null : Arrays.asList(input), output, abortable); + public XmlDoc.Element execute(ServerRoute serverRoute, String service, String args, ServerClient.Input input, + ServerClient.Output output, RequestOptions options) throws Throwable { + return execute(serverRoute, service, args, input == null ? null : Arrays.asList(input), output, options); } - public XmlDoc.Element execute(String service, String args, List<ServerClient.Input> inputs, - ServerClient.Output output, HasAbortableOperation abortable) throws Throwable { - ServerClient.Connection cxn = connect(); - try { - return execute(cxn, service, args, inputs, output, abortable, _settings.executeRetryTimes()); - } finally { - // If connection pooling is enabled, do not release resources so - // that the connection is kept in the pool to be reused. - cxn.close(_rs.usingConnectionPooling() ? false : true); - } + public XmlDoc.Element execute(ServerRoute serverRoute, String service, String args, ServerClient.Input input, + ServerClient.Output output, AbortableOperationHandler abortHandler) throws Throwable { + return execute(serverRoute, service, args, input == null ? null : Arrays.asList(input), output, abortHandler); } - public void testAuthentication() throws Throwable { - ServerClient.Connection cxn = null; - try { - cxn = connect(); - } finally { - if (cxn != null) { - cxn.close(_rs.usingConnectionPooling() ? false : true); - } + public XmlDoc.Element execute(ServerRoute serverRoute, String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, AbortableOperationHandler abortHandler) throws Throwable { + RequestOptions options = null; + if (abortHandler != null) { + options = new RequestOptions(); + options.setAbortHandler(abortHandler); } + return execute(MFRequest.create(serverRoute, service, args, inputs, output, options)); } - public void doConsoleLogon() throws Throwable { - Console console = System.console(); - if (console == null) { - throw new UnsupportedOperationException("Failed to open system console"); - } - if (_settings.serverHost() == null) { - _settings.readServerHostFromConsole(console); - } else { - console.printf("Host: %s%n", _settings.serverHost()); - } - if (_settings.serverPort() <= 0) { - _settings.readServerPortFromConsole(console); - } else { - console.printf("Port: %d%n", _settings.serverPort()); - } - if (_settings.serverTransport() == null) { - _settings.readServerTransportFromConsole(console); - } else { - console.printf("Transport: %s%n", _settings.serverTransport()); - } - if (_settings.domain() == null) { - _settings.readDomainFromConsole(console); - } else { - console.printf("Domain: %s%n", _settings.domain()); - } - if (_settings.user() == null) { - _settings.readUserFromConsole(console); - } else { - console.printf("User: %s%n", _settings.user()); - } - _settings.readPasswordFromConsole(console); + public XmlDoc.Element execute(ServerRoute serverRoute, String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, RequestOptions options) throws Throwable { + return execute(MFRequest.create(serverRoute, service, args, inputs, output, options)); + } + public XmlDoc.Element execute(MFRequest request) throws Throwable { + ServerClient.Connection cxn = connect(); try { - testAuthentication(); - } catch (Throwable e) { - console.printf("%n"); - console.printf("Error: %s%n", e.getMessage()); - console.printf("%n"); - doConsoleLogon(); + return execute(cxn, request, _executeRetryTimes); + } finally { + // If connection pooling is enabled, do not release resources so + // that the connection is kept in the pool to be reused. + cxn.close(_rs.usingConnectionPooling() ? false : true); } } - protected XmlDoc.Element execute(ServerClient.Connection cxn, String service, String args, - List<ServerClient.Input> inputs, ServerClient.Output output, HasAbortableOperation abortable, - int retryTimes) throws Throwable { + protected XmlDoc.Element execute(ServerClient.Connection cxn, MFRequest request, int retryTimes) throws Throwable { try { - RequestOptions ops = new RequestOptions(); - ops.setAbortHandler(new AbortableOperationHandler() { - - @Override - public void finished(CanAbort ca) { - if (abortable != null) { - abortable.setAbortableOperation(null); - } - } - - @Override - public void started(CanAbort ca) { - if (abortable != null) { - abortable.setAbortableOperation(ca); - } - } - }); - return cxn.executeMultiInput(null, service, args, inputs, output, ops); + return cxn.executeMultiInput(request.route(), request.service(), request.args(), request.inputs(), + request.output(), request.options()); } catch (ServerClient.ExSessionInvalid si) { - if (_auth != null && retryTimes > 0) { + if (retryTimes > 0) { System.out.println("Session invalid. Try re-authenticating..."); - if (_settings.executeRetryInterval() > 0) { - Thread.sleep(_settings.executeRetryInterval()); + if (_executeRetryInterval > 0) { + Thread.sleep(_executeRetryInterval); + } + synchronized (this) { + _sessionKey = cxn.connect(_ad); } - setSessionId(cxn.connect(_auth)); - return execute(cxn, service, args, inputs, output, abortable, --retryTimes); + return execute(cxn, request, --retryTimes); } throw si; } } - public XmlDoc.Element execute(String service, String args, List<ServerClient.Input> inputs, + public XmlDoc.Element execute(ServerRoute route, String service, String args, List<ServerClient.Input> inputs, ServerClient.Output output) throws Throwable { - return execute(service, args, inputs, output, null); + return execute(route, service, args, inputs, output, (RequestOptions) null); } public XmlDoc.Element execute(String service, String args, List<ServerClient.Input> inputs) throws Throwable { - return execute(service, args, inputs, null, null); + return execute(null, service, args, inputs, null, (RequestOptions) null); } public XmlDoc.Element execute(String service, String args, ServerClient.Input input, ServerClient.Output output) throws Throwable { - return execute(service, args, input, output, null); + return execute(null, service, args, input, output, (RequestOptions) null); } public XmlDoc.Element execute(String service, String args, ServerClient.Input input) throws Throwable { - return execute(service, args, input, null, null); + return execute(null, service, args, input, null, (RequestOptions) null); } public XmlDoc.Element execute(String service, String args, ServerClient.Output output) throws Throwable { - return execute(service, args, (List<Input>) null, output, null); + return execute(null, service, args, (List<Input>) null, output, (RequestOptions) null); } public XmlDoc.Element execute(String service, String args) throws Throwable { - return execute(service, args, (List<Input>) null, null, null); + return execute(null, service, args, (List<Input>) null, null, (RequestOptions) null); } public XmlDoc.Element execute(String service) throws Throwable { - return execute(service, null, (List<Input>) null, null, null); + return execute(null, service, null, (List<Input>) null, null, (RequestOptions) null); + } + + public XmlDoc.Element execute(String service, String args, List<ServerClient.Input> inputs, + ServerClient.Output output, AbortableOperationHandler abortHandler) throws Throwable { + return execute(null, service, args, inputs, output, abortHandler); + } + + public XmlDoc.Element execute(String service, String args, ServerClient.Input input, + AbortableOperationHandler abortHandler) throws Throwable { + return execute(null, service, args, input == null ? null : Arrays.asList(input), null, abortHandler); + } + + public XmlDoc.Element execute(String service, String args, ServerClient.Output output, + AbortableOperationHandler abortHandler) throws Throwable { + return execute(null, service, args, (List<ServerClient.Input>) null, output, abortHandler); } public void discard() { @@ -250,8 +236,84 @@ public class MFSession { } } - public String serverHost() { - return _settings.serverHost(); + public static MFSession create(MFConfigurationBuilder config) throws Throwable { + if (config.hasMissingArgument()) { + if (!config.consoleLogon()) { + throw new IllegalArgumentException("Missing Mediaflux server or user details."); + } + Console console = System.console(); + if (console == null) { + throw new UnsupportedOperationException("Failed to open system console"); + } + if (config.host() == null) { + config.readServerHostFromConsole(console); + } else { + console.printf("Host: %s%n", config.host()); + } + if (config.port() <= 0) { + config.readServerPortFromConsole(console); + } else { + console.printf("Port: %d%n", config.port()); + } + if (config.transport() == null) { + config.readServerTransportFromConsole(console); + } else { + console.printf("Transport: %s%n", config.transport()); + } + if (config.domain() == null) { + config.readDomainFromConsole(console); + } else { + console.printf("Domain: %s%n", config.domain()); + } + if (config.user() == null) { + config.readUserFromConsole(console); + } else { + console.printf("User: %s%n", config.user()); + } + config.readPasswordFromConsole(console); + RemoteServer rs = null; + ServerClient.Connection c = null; + try { + rs = new RemoteServer(config.connectionDetails()); + rs.setConnectionPooling(config.connectionPooling()); + c = rs.open(); + try { + String session = c.connect(config.authenticationDetails()); + return new MFSession(rs, c.authenticationDetails(), session, config.connectRetryTimes(), + config.connectRetryInterval(), config.executeRetryTimes(), config.executeRetryInterval()); + } finally { + c.close(rs.usingConnectionPooling() ? false : true); + } + } catch (Throwable e) { + console.printf("%n"); + console.printf("Error: %s%n", e.getMessage()); + console.printf("%n"); + if (c != null) { + try { + c.closeAndDiscard(); + } catch (Throwable t) { + } + } + if (rs != null) { + try { + rs.discard(); + } catch (Throwable t) { + } + } + return create(config); + } + } else { + RemoteServer rs = new RemoteServer(config.connectionDetails()); + rs.setConnectionPooling(config.connectionPooling()); + ServerClient.Connection c = rs.open(); + try { + String session = c.connect(config.authenticationDetails()); + return new MFSession(rs, c.authenticationDetails(), session, config.connectRetryTimes(), + config.connectRetryInterval(), config.executeRetryTimes(), config.executeRetryInterval()); + } finally { + c.close(rs.usingConnectionPooling() ? false : true); + } + } } } diff --git a/src/main/java/unimelb/mf/client/ssh/AbstractSSHService.java b/src/main/java/unimelb/mf/client/ssh/AbstractSSHService.java deleted file mode 100644 index b452807fa659a07afd1520102f9fa228047e7014..0000000000000000000000000000000000000000 --- a/src/main/java/unimelb/mf/client/ssh/AbstractSSHService.java +++ /dev/null @@ -1,101 +0,0 @@ -package unimelb.mf.client.ssh; - -import arc.xml.XmlWriter; - -public abstract class AbstractSSHService implements SSHService { - - protected SSHConnectionSettings sshSettings; - protected boolean stopOnError = true; - protected int retryOnError = 0; - - protected AbstractSSHService() { - this.sshSettings = new SSHConnectionSettings(); - } - - @Override - public void serviceArgs(XmlWriter w) throws Throwable { - w.add("host", this.sshSettings.host()); - w.add("port", this.sshSettings.port()); - w.add("user", this.sshSettings.username()); - if (this.sshSettings.password() != null) { - w.add("password", this.sshSettings.password()); - } - if (this.sshSettings.privateKey() != null) { - w.add("private-key", this.sshSettings.privateKey()); - } - if (this.sshSettings.passphrase() != null) { - w.add("passphrase", this.sshSettings.passphrase()); - } - if (!this.stopOnError || this.retryOnError > 0) { - w.add("on-error", new String[] { "retry", Integer.toString(this.retryOnError) }, - this.stopOnError ? "stop" : "continue"); - } - - } - - @Override - public void setStopOnError(boolean stopOnError) { - this.stopOnError = stopOnError; - } - - @Override - public void setSSHServerHost(String sshServerHost) { - this.sshSettings.setServerHost(sshServerHost); - } - - @Override - public void setSSHServerPort(int sshServerPort) { - this.sshSettings.setServerPort(sshServerPort); - } - - @Override - public void setSSHUsername(String username) { - this.sshSettings.setUsername(username); - } - - @Override - public void setSSHPassword(String password) { - this.sshSettings.setPassword(password); - } - - @Override - public void setSSHBaseDirectory(String baseDir) { - this.sshSettings.setBaseDirectory(baseDir); - } - - @Override - public void setSSHPrivateKey(String privateKey) { - this.sshSettings.setPrivateKey(privateKey); - } - - @Override - public void setSSHPassphrase(String passphrase) { - this.sshSettings.setPassphrase(passphrase); - } - - @Override - public final int retryOnError() { - return this.retryOnError; - } - - @Override - public final void setRetryOnError(int retryOnError) { - this.retryOnError = retryOnError; - } - - @Override - public void validateArgs() throws IllegalArgumentException { - this.sshSettings.validate(); - } - - @Override - public boolean stopOnError() { - return this.stopOnError; - } - - @Override - public boolean continueOnError() { - return !this.stopOnError; - } - -} diff --git a/src/main/java/unimelb/mf/client/ssh/SCPGetService.java b/src/main/java/unimelb/mf/client/ssh/SCPGetService.java index 1650884a037a0563b1ab8ce8b4ddf6bea61acc65..632fde23b8037cf6d11c5360e80302ed1154fb19 100644 --- a/src/main/java/unimelb/mf/client/ssh/SCPGetService.java +++ b/src/main/java/unimelb/mf/client/ssh/SCPGetService.java @@ -2,19 +2,15 @@ package unimelb.mf.client.ssh; public class SCPGetService extends SSHGetService { - @Override - public final String name() { - return "unimelb.scp.get"; - } + public static final String SERVICE_NAME = "unimelb.scp.get"; - @Override - public final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SCP; + public SCPGetService(SSHGetConfiguration cfg) { + super(cfg); } @Override - public final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.GET; + public final String service() { + return SERVICE_NAME; } } diff --git a/src/main/java/unimelb/mf/client/ssh/SCPPutService.java b/src/main/java/unimelb/mf/client/ssh/SCPPutService.java index 2e12d9c9f623a3ac35ef073a16d3e915780c9888..6be3920b86b7a852d63b185d6c2becd8a186e91a 100644 --- a/src/main/java/unimelb/mf/client/ssh/SCPPutService.java +++ b/src/main/java/unimelb/mf/client/ssh/SCPPutService.java @@ -2,18 +2,15 @@ package unimelb.mf.client.ssh; public class SCPPutService extends SSHPutService { - @Override - public final String name() { - return "unimelb.scp.put"; - } + public static final String SERVICE_NAME = "unimelb.scp.put"; - @Override - public final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SCP; + public SCPPutService(SSHPutConfiguration cfg) { + super(cfg); } @Override - public final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.PUT; + public final String service() { + return SERVICE_NAME; } + } diff --git a/src/main/java/unimelb/mf/client/ssh/SFTPGetService.java b/src/main/java/unimelb/mf/client/ssh/SFTPGetService.java index 8bd947b1a263c4160595c81ba04b5508821ed850..c63db3999c0d6f63bde3124363be27398b6b79f5 100644 --- a/src/main/java/unimelb/mf/client/ssh/SFTPGetService.java +++ b/src/main/java/unimelb/mf/client/ssh/SFTPGetService.java @@ -2,18 +2,15 @@ package unimelb.mf.client.ssh; public class SFTPGetService extends SSHGetService { - @Override - public final String name() { - return "unimelb.sftp.get"; - } + public static final String SERVICE_NAME = "unimelb.sftp.get"; - @Override - public final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SFTP; + public SFTPGetService(SSHGetConfiguration cfg) { + super(cfg); } @Override - public final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.GET; + public final String service() { + return SERVICE_NAME; } + } diff --git a/src/main/java/unimelb/mf/client/ssh/SFTPPutService.java b/src/main/java/unimelb/mf/client/ssh/SFTPPutService.java index 9d0d1d898021e48af84d7dff49b686f9ee72dc8a..fc24d4dcdc99c60c047cb474c6e5ea468c7d7a1e 100644 --- a/src/main/java/unimelb/mf/client/ssh/SFTPPutService.java +++ b/src/main/java/unimelb/mf/client/ssh/SFTPPutService.java @@ -2,18 +2,14 @@ package unimelb.mf.client.ssh; public class SFTPPutService extends SSHPutService { - @Override - public String name() { - return "unimelb.sftp.put"; - } + public static final String SERVICE_NAME = "unimelb.sftp.put"; - @Override - public final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SFTP; + public SFTPPutService(SSHPutConfiguration cfg) { + super(cfg); } @Override - public final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.PUT; + public final String service() { + return SERVICE_NAME; } } diff --git a/src/main/java/unimelb/mf/client/ssh/SSHConfiguration.java b/src/main/java/unimelb/mf/client/ssh/SSHConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..d2434fe18de229022e41e7840baa30d44aa783d4 --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHConfiguration.java @@ -0,0 +1,91 @@ +package unimelb.mf.client.ssh; + +import arc.xml.XmlWriter; + +public abstract class SSHConfiguration { + + public static enum Action { + GET, PUT + } + + private String _host; + private int _port = 22; + private String _username; + private String _password; + private String _privateKey; + private String _passphrase; + private String _baseDir; + private boolean _stopOnError = true; + private int _retries = 0; + + SSHConfiguration(String host, int port, String username, String password, String privateKey, String passphrase, + String baseDir, boolean stopOnError, int retries) { + _host = host; + _port = port; + _username = username; + _password = password; + _privateKey = privateKey; + _passphrase = passphrase; + _baseDir = baseDir; + _stopOnError = stopOnError; + _retries = retries; + } + + public String host() { + return _host; + } + + public int port() { + return _port; + } + + public String username() { + return _username; + } + + public String password() { + return _password; + } + + public String privateKey() { + return _privateKey; + } + + public String passphrase() { + return _passphrase; + } + + public String baseDirectory() { + return _baseDir; + } + + public int retries() { + return _retries; + } + + public boolean stopOnError() { + return _stopOnError; + } + + public void save(XmlWriter w) throws Throwable { + w.add("host", host()); + w.add("port", port()); + w.add("user", username()); + if (password() != null) { + w.add("password", password()); + } + if (privateKey() != null) { + w.add("private-key", privateKey()); + } + if (passphrase() != null) { + w.add("passphrase", passphrase()); + } + if (!stopOnError() || retries() > 0) { + w.add("on-error", new String[] { "retry", Integer.toString(retries()) }, + stopOnError() ? "stop" : "continue"); + } + } + + protected abstract Action action(); + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHConfigurationBuilder.java b/src/main/java/unimelb/mf/client/ssh/SSHConfigurationBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..614ee70f86196d0fafee397b12513b74d453a7dc --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHConfigurationBuilder.java @@ -0,0 +1,92 @@ +package unimelb.mf.client.ssh; + +import unimelb.mf.client.ssh.SSHConfiguration.Action; + +@SuppressWarnings("unchecked") +public abstract class SSHConfigurationBuilder<T extends SSHConfiguration, B extends SSHConfigurationBuilder<T, B>> { + + protected String host; + protected int port = 22; + protected String username; + protected String password; + protected String privateKey; + protected String passphrase; + protected String baseDirectory; + protected boolean stopOnError = true;; + protected int retries = 0; + + protected SSHConfigurationBuilder() { + + } + + public B setHost(String host) { + this.host = host; + return (B) this; + } + + public B setPort(int port) { + this.port = port; + return (B) this; + } + + public B setUsername(String username) { + this.username = username; + return (B) this; + } + + public B setPassword(String password) { + this.password = password; + return (B) this; + } + + public B setPrivateKey(String privateKey, String passphrase) { + this.privateKey = privateKey; + this.passphrase = passphrase; + return (B) this; + } + + public B setPrivateKey(String privateKey) { + this.privateKey = privateKey; + return (B) this; + } + + public B setPassphrase(String passphrase) { + this.passphrase = passphrase; + return (B) this; + } + + public B setBaseDirectory(String baseDirectory) { + this.baseDirectory = baseDirectory; + return (B) this; + } + + public B setStopOnError(boolean stopOnError) { + this.stopOnError = stopOnError; + return (B) this; + } + + public B setRetries(int retries) { + this.retries = retries > 0 ? retries : 0; + return (B) this; + } + + public void validate() throws IllegalArgumentException { + if (this.host == null) { + throw new IllegalArgumentException("Missing SSH server host."); + } + if (this.port <= 0 || this.port > 65535) { + throw new IllegalArgumentException("Invalid SSH server port: " + this.port); + } + if (this.username == null) { + throw new IllegalArgumentException("Missing SSH username."); + } + if (this.password == null && this.privateKey == null) { + throw new IllegalArgumentException("Missing SSH password or private key. Expects at least one."); + } + } + + public abstract Action action(); + + public abstract T build(); + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHConnectionSettings.java b/src/main/java/unimelb/mf/client/ssh/SSHConnectionSettings.java deleted file mode 100644 index ab7b0e47145b8371d5de189c374332f741f7cd34..0000000000000000000000000000000000000000 --- a/src/main/java/unimelb/mf/client/ssh/SSHConnectionSettings.java +++ /dev/null @@ -1,101 +0,0 @@ -package unimelb.mf.client.ssh; - -public class SSHConnectionSettings { - - private String _host; - private int _port = 22; - private String _username; - private String _password; - private String _privateKey; - private String _passphrase; - private String _baseDir; - - public SSHConnectionSettings() { - - } - - public SSHConnectionSettings setServerHost(String host) { - _host = host; - return this; - } - - public SSHConnectionSettings setServerPort(int port) { - _port = port; - return this; - } - - public SSHConnectionSettings setUsername(String username) { - _username = username; - return this; - } - - public SSHConnectionSettings setPassword(String password) { - _password = password; - return this; - } - - public SSHConnectionSettings setPrivateKey(String privateKey, String passphrase) { - _privateKey = privateKey; - _passphrase = passphrase; - return this; - } - - public SSHConnectionSettings setPrivateKey(String privateKey) { - _privateKey = privateKey; - return this; - } - - public SSHConnectionSettings setPassphrase(String passphrase) { - _passphrase = passphrase; - return this; - } - - public SSHConnectionSettings setBaseDirectory(String baseDirectory) { - _baseDir = baseDirectory; - return this; - } - - public String host() { - return _host; - } - - public int port() { - return _port; - } - - public String username() { - return _username; - } - - public String password() { - return _password; - } - - public String privateKey() { - return _privateKey; - } - - public String passphrase() { - return _passphrase; - } - - public String baseDirectory() { - return _baseDir; - } - - public void validate() throws IllegalArgumentException { - if (_host == null) { - throw new IllegalArgumentException("Missing SSH server host."); - } - if (_port <= 0 || _port > 65535) { - throw new IllegalArgumentException("Invalid SSH server port: " + _port); - } - if (_username == null) { - throw new IllegalArgumentException("Missing SSH username."); - } - if (_password == null && _privateKey == null) { - throw new IllegalArgumentException("Missing SSH password or private key. Expects at least one."); - } - } - -} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHGetConfiguration.java b/src/main/java/unimelb/mf/client/ssh/SSHGetConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..76b288a0bc2a3dfcc3c9708ed3c407e9f1681da2 --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHGetConfiguration.java @@ -0,0 +1,74 @@ +package unimelb.mf.client.ssh; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import arc.xml.XmlWriter; +import unimelb.mf.model.asset.worm.Worm; + +public class SSHGetConfiguration extends SSHConfiguration { + + private Boolean _readOnly = null; + private Worm _worm = null; + private Set<String> _srcPaths; + private String _dstNamespace = null; + + SSHGetConfiguration(String host, int port, String username, String password, String privateKey, String passphrase, + String baseDir, boolean stopOnError, int retries, Collection<String> srcPaths, String dstNamespace, + Boolean readOnly, Worm worm) { + super(host, port, username, password, privateKey, passphrase, baseDir, stopOnError, retries); + _srcPaths = new LinkedHashSet<String>(); + if (srcPaths != null) { + _srcPaths.addAll(srcPaths); + } + _dstNamespace = dstNamespace; + _readOnly = readOnly; + + } + + @Override + public final Action action() { + return Action.GET; + } + + public String dstNamespace() { + return _dstNamespace; + } + + public Collection<String> srcPaths() { + return Collections.unmodifiableSet(_srcPaths); + } + + public Boolean readOnly() { + return _readOnly; + } + + public Worm worm() { + return _worm; + } + + @Override + public void save(XmlWriter w) throws Throwable { + super.save(w); + if (readOnly() != null) { + w.add("read-only", readOnly()); + } + if (worm() != null) { + w.push("worm"); + worm().save(w); + w.pop(); + } + if (dstNamespace() != null) { + w.add("namespace", dstNamespace()); + } + Collection<String> srcPaths = srcPaths(); + if (srcPaths != null) { + for (String srcPath : srcPaths) { + w.add("path", srcPath); + } + } + } + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHGetConfigurationBuilder.java b/src/main/java/unimelb/mf/client/ssh/SSHGetConfigurationBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..aad62851f169fc82cc7292335da14a6172d49904 --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHGetConfigurationBuilder.java @@ -0,0 +1,87 @@ +package unimelb.mf.client.ssh; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import unimelb.mf.client.ssh.SSHConfiguration.Action; +import unimelb.mf.model.asset.worm.Worm; + +public class SSHGetConfigurationBuilder + extends SSHConfigurationBuilder<SSHGetConfiguration, SSHGetConfigurationBuilder> { + + protected Boolean readOnly = null; + protected Worm worm = null; + protected Set<String> srcPaths; + protected String dstNamespace = null; + + public SSHGetConfigurationBuilder() { + this.srcPaths = new LinkedHashSet<String>(); + } + + public void validate() throws IllegalArgumentException { + super.validate(); + if (this.srcPaths.isEmpty()) { + throw new IllegalArgumentException("Missing path on the remote SSH server."); + } + if (this.dstNamespace == null) { + throw new IllegalArgumentException("Missing namespace path on the Mediaflux server."); + } + } + + @Override + public SSHGetConfiguration build() { + validate(); + return new SSHGetConfiguration(this.host, this.port, this.username, this.password, this.privateKey, + this.passphrase, this.baseDirectory, this.stopOnError, this.retries, this.srcPaths, this.dstNamespace, + this.readOnly, this.worm); + } + + public SSHGetConfigurationBuilder setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + return this; + } + + public Worm worm() { + return this.worm; + } + + public SSHGetConfigurationBuilder setWorm(Worm worm) { + this.worm = worm; + return this; + } + + public SSHGetConfigurationBuilder setSrcPath(String path) { + this.srcPaths.clear(); + if (path != null) { + this.srcPaths.add(path); + } + return this; + } + + public SSHGetConfigurationBuilder setSrcPaths(Collection<String> paths) { + this.srcPaths.clear(); + if (paths != null) { + this.srcPaths.addAll(paths); + } + return this; + } + + public SSHGetConfigurationBuilder addSrcPath(String path) { + if (path != null) { + this.srcPaths.add(path); + } + return this; + } + + public SSHGetConfigurationBuilder setDstNamespace(String namespace) { + this.dstNamespace = namespace; + return this; + } + + @Override + public final Action action() { + return Action.GET; + } + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHGetService.java b/src/main/java/unimelb/mf/client/ssh/SSHGetService.java index 8752f20bec05b0f36381796f2c00d9e6100b5811..a7eeb4b87b1e7da7d53322c04bdbae32056371f2 100644 --- a/src/main/java/unimelb/mf/client/ssh/SSHGetService.java +++ b/src/main/java/unimelb/mf/client/ssh/SSHGetService.java @@ -1,98 +1,8 @@ package unimelb.mf.client.ssh; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; +public abstract class SSHGetService extends SSHService<SSHGetConfiguration> { -import arc.xml.XmlWriter; -import unimelb.mf.model.asset.worm.Worm; - -public abstract class SSHGetService extends AbstractSSHService { - - protected Boolean readOnly = null; - protected Worm worm = null; - private Set<String> _srcPaths; - private String _dstNamespace = null; - - public SSHGetService() { - _srcPaths = new LinkedHashSet<String>(); - } - - @Override - public void validateArgs() throws IllegalArgumentException { - super.validateArgs(); - if (_srcPaths.isEmpty()) { - throw new IllegalArgumentException("Missing path on the remote SSH server."); - } - if (_dstNamespace == null) { - throw new IllegalArgumentException("Missing namespace path on the Mediaflux server."); - } - } - - @Override - public void serviceArgs(XmlWriter w) throws Throwable { - super.serviceArgs(w); - if (this.readOnly != null) { - w.add("read-only", this.readOnly); - } - if (this.worm != null) { - w.push("worm"); - this.worm.save(w); - w.pop(); - } - if (_dstNamespace != null) { - w.add("namespace", _dstNamespace); - } - if (_srcPaths != null) { - for (String srcPath : _srcPaths) { - w.add("path", srcPath); - } - } - } - - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - public void setWorm(Worm worm) { - this.worm = worm; - } - - public Set<String> srcPaths() { - return Collections.unmodifiableSet(_srcPaths); + protected SSHGetService(SSHGetConfiguration cfg) { + super(cfg); } - - public void setSrcPath(String path) { - _srcPaths.clear(); - if (path != null) { - _srcPaths.add(path); - } - } - - public void setSrcPaths(Collection<String> paths) { - _srcPaths.clear(); - if (paths != null) { - _srcPaths.addAll(paths); - } - } - - public void addSrcPath(String path) { - if (path != null) { - _srcPaths.add(path); - } - } - - public String dstNamespace() { - return _dstNamespace; - } - - public void setDstNamespace(String namespace) { - _dstNamespace = namespace; - } - - public Worm worm() { - return this.worm; - } - } diff --git a/src/main/java/unimelb/mf/client/ssh/SSHPutConfiguration.java b/src/main/java/unimelb/mf/client/ssh/SSHPutConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..ba12137847dc1af136efd3af19893135419593bf --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHPutConfiguration.java @@ -0,0 +1,78 @@ +package unimelb.mf.client.ssh; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import arc.xml.XmlWriter; + +public class SSHPutConfiguration extends SSHConfiguration { + private String _where; + private Set<String> _namespaces; + private Map<String, Boolean> _cids; + private Set<String> _assetIds; + private String _expr; + private Boolean _unarchive; + private String _directory; + + SSHPutConfiguration(String host, int port, String username, String password, String privateKey, String passphrase, + String baseDir, boolean stopOnError, int retries, String where, Collection<String> namespaces, + Map<String, Boolean> cids, Collection<String> assetIds, String expr, Boolean unarchive, String directory) { + super(host, port, username, password, privateKey, passphrase, baseDir, stopOnError, retries); + _where = where; + if (namespaces != null && !namespaces.isEmpty()) { + _namespaces = new LinkedHashSet<String>(); + _namespaces.addAll(namespaces); + } + if (cids != null && !cids.isEmpty()) { + _cids = new LinkedHashMap<String, Boolean>(); + _cids.putAll(cids); + } + if (assetIds != null && !assetIds.isEmpty()) { + _assetIds = new LinkedHashSet<String>(); + _assetIds.addAll(assetIds); + } + _expr = expr; + _unarchive = unarchive; + _directory = directory; + } + + @Override + public final Action action() { + return Action.PUT; + } + + @Override + public void save(XmlWriter w) throws Throwable { + super.save(w); + if (_cids != null && !_cids.isEmpty()) { + Set<String> cids = _cids.keySet(); + for (String cid : cids) { + w.add("cid", new String[] { "recursive", Boolean.toString(_cids.get(cid)) }, cid); + } + } + if (_assetIds != null && !_assetIds.isEmpty()) { + for (String assetId : _assetIds) { + w.add("id", assetId); + } + } + if (_namespaces != null && !_namespaces.isEmpty()) { + for (String namespace : _namespaces) { + w.add("namespace", namespace); + } + } + if (_where != null) { + w.add("where", _where); + } + if (_expr != null) { + w.add("expr", _expr); + } + if (_unarchive != null) { + w.add("unarchive", _unarchive); + } + w.add("directory", _directory); + } + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHPutConfigurationBuilder.java b/src/main/java/unimelb/mf/client/ssh/SSHPutConfigurationBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..0e713c34dace9877ae31720d7e1dcce8179a97f8 --- /dev/null +++ b/src/main/java/unimelb/mf/client/ssh/SSHPutConfigurationBuilder.java @@ -0,0 +1,135 @@ +package unimelb.mf.client.ssh; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import unimelb.mf.client.ssh.SSHConfiguration.Action; + +public class SSHPutConfigurationBuilder + extends SSHConfigurationBuilder<SSHPutConfiguration, SSHPutConfigurationBuilder> { + + protected String where; + protected Set<String> namespaces; + protected Map<String, Boolean> cids; + protected Set<String> assetIds; + protected String expr; + protected Boolean unarchive; + protected String directory; + + @Override + public SSHPutConfiguration build() { + validate(); + return new SSHPutConfiguration(this.host, this.port, this.username, this.password, this.privateKey, + this.passphrase, this.baseDirectory, this.stopOnError, this.retries, this.where, this.namespaces, + this.cids, this.assetIds, this.expr, this.unarchive, this.directory); + } + + @Override + public void validate() throws IllegalArgumentException { + super.validate(); + if (this.directory == null) { + throw new IllegalArgumentException("Missing destination directory on the remote SSH server."); + } + if (this.where == null && (this.namespaces == null || this.namespaces.isEmpty()) + && (this.cids == null || this.cids.isEmpty()) && (this.assetIds == null || this.assetIds.isEmpty())) { + throw new IllegalArgumentException("Missing source asset namespaces (or selection query)."); + } + } + + public void setCiteableIds(boolean recursive, String... cids) { + if (this.cids != null) { + this.cids.clear(); + } + if (cids != null) { + if (this.cids == null) { + this.cids = new LinkedHashMap<String, Boolean>(); + } + for (String cid : cids) { + this.cids.put(cid, recursive); + } + } + } + + public void addCiteableId(String cid, boolean recursive) { + if (cid != null) { + if (this.cids == null) { + this.cids = new LinkedHashMap<String, Boolean>(); + } + this.cids.put(cid, recursive); + } + } + + public void addCiteableId(String cid) { + addCiteableId(cid, true); + } + + public void setAssetIds(String... assetIds) { + if (this.assetIds != null) { + this.assetIds.clear(); + } + if (assetIds != null) { + if (this.assetIds == null) { + this.assetIds = new LinkedHashSet<String>(); + } + for (String assetId : assetIds) { + this.assetIds.add(assetId); + } + } + } + + public void addAssetId(String assetId) { + if (assetId != null) { + if (this.assetIds == null) { + this.assetIds = new LinkedHashSet<String>(); + } + this.assetIds.add(assetId); + } + } + + public void setNamespaces(String... namespaces) { + if (this.namespaces != null) { + this.namespaces.clear(); + } + if (namespaces != null) { + if (this.namespaces == null) { + this.namespaces = new LinkedHashSet<String>(); + } + for (String namespace : namespaces) { + this.namespaces.add(namespace); + } + } + } + + public void addNamespace(String namespace) { + if (namespace != null) { + if (this.namespaces == null) { + this.namespaces = new LinkedHashSet<String>(); + } + this.namespaces.add(namespace); + } + } + + public void setWhere(String where) { + this.where = where; + } + + public void setOutputPathExpression(String expr) { + this.expr = expr; + } + + public void setDstDirectory(String directory) { + this.directory = directory; + } + + public void setUnarchiveContents(Boolean unarchive) { + this.unarchive = unarchive; + } + + @Override + public final Action action() { + return Action.PUT; + } + +} diff --git a/src/main/java/unimelb/mf/client/ssh/SSHPutService.java b/src/main/java/unimelb/mf/client/ssh/SSHPutService.java index 37852ba2eb549af23db2d4dce9f5cb4f0f4a8ed4..bf624b4947f712a1083800e7d1c423c3d689b9b2 100644 --- a/src/main/java/unimelb/mf/client/ssh/SSHPutService.java +++ b/src/main/java/unimelb/mf/client/ssh/SSHPutService.java @@ -1,137 +1,9 @@ package unimelb.mf.client.ssh; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; +public abstract class SSHPutService extends SSHService<SSHPutConfiguration> { -import arc.xml.XmlWriter; - -public abstract class SSHPutService extends AbstractSSHService { - - private Map<String, Boolean> _cids; - private Set<String> _assetIds; - private Set<String> _namespaces; - private String _where; - private String _expr; - private Boolean _unarchive; - - private String _directory; - - public SSHPutService() { - _cids = new LinkedHashMap<String, Boolean>(); - _assetIds = new LinkedHashSet<String>(); - _namespaces = new LinkedHashSet<String>(); - _where = null; - } - - @Override - public void validateArgs() throws IllegalArgumentException { - super.validateArgs(); - if (_cids.isEmpty() && _assetIds.isEmpty() && _namespaces.isEmpty() && _where == null) { - throw new IllegalArgumentException( - "Missing source asset specifications, either id, cid, namespace or query must be specified."); - } - } - - @Override - public void serviceArgs(XmlWriter w) throws Throwable { - super.serviceArgs(w); - if (!_cids.isEmpty()) { - Set<String> cids = _cids.keySet(); - for (String cid : cids) { - w.add("cid", new String[] { "recursive", Boolean.toString(_cids.get(cid)) }, cid); - } - } - if (!_assetIds.isEmpty()) { - for (String assetId : _assetIds) { - w.add("id", assetId); - } - } - if (!_namespaces.isEmpty()) { - for (String namespace : _namespaces) { - w.add("namespace", namespace); - } - } - if (_where != null) { - w.add("where", _where); - } - if (_expr != null) { - w.add("expr", _expr); - } - if (_unarchive != null) { - w.add("unarchive", _unarchive); - } - w.add("directory", _directory); - } - - public void setCiteableIds(boolean recursive, String... cids) { - _cids.clear(); - if (cids != null) { - for (String cid : cids) { - _cids.put(cid, recursive); - } - } - } - - public void addCiteableId(String cid, boolean recursive) { - if (cid != null) { - _cids.put(cid, recursive); - } - } - - public void addCiteableId(String cid) { - addCiteableId(cid, true); - } - - public void setAssetIds(String... assetIds) { - _assetIds.clear(); - if (assetIds != null) { - for (String assetId : assetIds) { - _assetIds.add(assetId); - } - } - } - - public void addAssetId(String assetId) { - if (assetId != null) { - _assetIds.add(assetId); - } - } - - public void setNamespaces(String... namespaces) { - _namespaces.clear(); - if (namespaces != null) { - for (String namespace : namespaces) { - _assetIds.add(namespace); - } - } - } - - public void addNamespace(String namespace) { - if (namespace != null) { - _namespaces.add(namespace); - } - } - - public void setWhere(String where) { - _where = where; - } - - public void setOutputPathExpression(String expr) { - _expr = expr; - } - - public void setDstDirectory(String directory) { - _directory = directory; - } - - public String dstDirectory() { - return _directory; - } - - public void setUnarchiveContents(Boolean unarchive) { - _unarchive = unarchive; + protected SSHPutService(SSHPutConfiguration cfg) { + super(cfg); } } diff --git a/src/main/java/unimelb/mf/client/ssh/SSHService.java b/src/main/java/unimelb/mf/client/ssh/SSHService.java index 37626cf3e827ca105c90761afe521b77cc2f19d8..5eb04b03449de2c8877de8a7ce2816748c2544f3 100644 --- a/src/main/java/unimelb/mf/client/ssh/SSHService.java +++ b/src/main/java/unimelb/mf/client/ssh/SSHService.java @@ -1,37 +1,90 @@ package unimelb.mf.client.ssh; -import unimelb.mf.client.session.MFService; +import java.util.List; -public interface SSHService extends MFService { +import arc.mf.client.RequestOptions; +import arc.mf.client.ServerClient.Input; +import arc.mf.client.ServerClient.Output; +import arc.mf.client.ServerRoute; +import arc.utils.AbortableOperationHandler; +import arc.utils.CanAbort; +import arc.xml.XmlStringWriter; +import unimelb.mf.client.session.MFRequest; +import unimelb.mf.client.session.MFSession; - void setSSHServerHost(String sshServerHost); +public abstract class SSHService<T extends SSHConfiguration> implements MFRequest { - void setSSHServerPort(int sshServerPort); + private T _cfg; + private RequestOptions _ops; + private CanAbort _ca; - void setSSHUsername(String username); + protected SSHService(T cfg) { + _cfg = cfg; + _ops = new RequestOptions(); + _ops.setAbortHandler(new AbortableOperationHandler() { - void setSSHPassword(String password); + @Override + public void finished(CanAbort ca) { + _ca = null; + } - void setSSHBaseDirectory(String baseDir); + @Override + public void started(CanAbort ca) { + _ca = ca; + } + }); + _ops.setBackground(true); + } + + public T configuration() { + return _cfg; + } + + @Override + public ServerRoute route() { + return null; + } - void setSSHPrivateKey(String privateKey); + @Override + public String args() { + XmlStringWriter w = new XmlStringWriter(); + try { + _cfg.save(w); + return w.document(); + } catch (Throwable e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new RuntimeException(e); + } + } + } - void setSSHPassphrase(String passphrase); + @Override + public List<Input> inputs() { + return null; + } - void setStopOnError(boolean stopOnError); - - boolean stopOnError(); - - boolean continueOnError(); + @Override + public Output output() { + return null; + } - void setRetryOnError(int retryOnError); + @Override + public RequestOptions options() { + return _ops; + } - default int retryOnError() { - return 0; + @Override + public void abort() throws Throwable { + if (_ca != null) { + _ca.abort(); + _ca = null; + } } - SSHTransferProtocol sshTransferProtocol(); - - SSHTransferDirection sshTransferDirection(); + public long executeBackground(MFSession session) throws Throwable { + return execute(session).longValue("id"); + } } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SCPGetCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SCPGetCLI.java index 5a4a1a36dfb90e374fbb4b0ec333659e12362efb..11484724638155e8ab9e05b5eb3f7aa9e41da797 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SCPGetCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SCPGetCLI.java @@ -1,31 +1,32 @@ package unimelb.mf.client.ssh.cli; import unimelb.mf.client.ssh.SCPGetService; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHService; -public class SCPGetCLI extends SSHGetCLI<SCPGetService> { - - protected SCPGetCLI() { - super(new SCPGetService()); - } +public class SCPGetCLI extends SSHGetCLI { @Override - protected final String appName() { + public final String applicationName() { return "scp-get"; } - @Override - protected final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SCP; - } - public static void main(String[] args) throws Throwable { execute(new SCPGetCLI(), args); } @Override - protected String description() { + public String description() { return "Import files from remote SSH server to Mediaflux using scp."; } + @Override + protected SSHService<?> createService(Settings settings) { + return new SCPGetService(settings.config().build()); + } + + @Override + protected final String protocol() { + return "SSH"; + } + } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SCPPutCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SCPPutCLI.java index 4b32c983521d209b912171369dcd630c8b10a97a..e2463209a65f62bb0da55790b106f18e661fd1e6 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SCPPutCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SCPPutCLI.java @@ -1,31 +1,32 @@ package unimelb.mf.client.ssh.cli; import unimelb.mf.client.ssh.SCPPutService; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHService; -public class SCPPutCLI extends SSHPutCLI<SCPPutService> { - - protected SCPPutCLI() { - super(new SCPPutService()); - } +public class SCPPutCLI extends SSHPutCLI { @Override - protected final String appName() { + public final String applicationName() { return "scp-put"; } - @Override - protected final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SCP; - } - public static void main(String[] args) throws Throwable { execute(new SCPPutCLI(), args); } @Override - protected String description() { + public String description() { return "Export Mediaflux assets to remote SSH server using scp."; } + @Override + protected final String protocol() { + return "SSH"; + } + + @Override + protected SSHService<?> createService(Settings settings) { + return new SCPPutService(settings.config().build()); + } + } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SFTPGetCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SFTPGetCLI.java index baa03f1d7cf0d240d4815f024c2f6ba9de9b10f8..feea8a738fa62bcec67d449e319679116bc60270 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SFTPGetCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SFTPGetCLI.java @@ -1,30 +1,31 @@ package unimelb.mf.client.ssh.cli; import unimelb.mf.client.ssh.SFTPGetService; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHService; -public class SFTPGetCLI extends SSHGetCLI<SFTPGetService> { - - protected SFTPGetCLI() { - super(new SFTPGetService()); - } +public class SFTPGetCLI extends SSHGetCLI { @Override - protected final String appName() { + public final String applicationName() { return "sftp-get"; } - @Override - protected final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SFTP; - } - public static void main(String[] args) throws Throwable { execute(new SFTPGetCLI(), args); } @Override - protected String description() { + public String description() { return "Import files from remote SFTP server to Mediaflux using sftp."; } + + @Override + protected SSHService<?> createService(Settings settings) { + return new SFTPGetService(settings.config().build()); + } + + @Override + protected final String protocol() { + return "SFTP"; + } } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SFTPPutCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SFTPPutCLI.java index 04e51e54481ec3f510cf90e5d6328ac5565ce277..ee9493ba57421d853432cf3fe3d3a9bf2000f45d 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SFTPPutCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SFTPPutCLI.java @@ -1,31 +1,35 @@ package unimelb.mf.client.ssh.cli; import unimelb.mf.client.ssh.SFTPPutService; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHService; -public class SFTPPutCLI extends SSHPutCLI<SFTPPutService> { +public class SFTPPutCLI extends SSHPutCLI { protected SFTPPutCLI() { - super(new SFTPPutService()); + super(); } @Override - protected final String appName() { + public final String applicationName() { return "sftp-put"; } @Override - protected final SSHTransferProtocol sshTransferProtocol() { - return SSHTransferProtocol.SFTP; + public String description() { + return "Export Mediaflux assets to remote SFTP server using sftp."; } - public static void main(String[] args) throws Throwable { - execute(new SFTPPutCLI(), args); + @Override + protected SSHService<?> createService(Settings settings) { + return new SFTPPutService(settings.config().build()); } @Override - protected String description() { - return "Export Mediaflux assets to remote SFTP server using sftp."; + protected final String protocol() { + return "SFTP"; } + public static void main(String[] args) throws Throwable { + execute(new SFTPPutCLI(), args); + } } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SSHCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SSHCLI.java index 3c89a4b2c9d97c18bef195da8e5d9ec4b684f355..28c352bf8d94016d23175e12ab097c391af6591d 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SSHCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SSHCLI.java @@ -8,119 +8,156 @@ import java.util.TimerTask; import arc.mf.client.ServerClient; import arc.utils.ObjectUtil; import arc.xml.XmlDoc; -import unimelb.mf.client.session.MFConnectionSettings; import unimelb.mf.client.session.MFSession; +import unimelb.mf.client.ssh.SSHConfigurationBuilder; import unimelb.mf.client.ssh.SSHService; -import unimelb.mf.client.ssh.SSHTransferDirection; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.task.AbstractMFAppCLI; +import unimelb.mf.client.task.MFApp; +import unimelb.mf.client.util.LoggingUtils; import unimelb.mf.client.util.XmlUtils; import unimelb.mf.model.service.BackgroundService; import unimelb.mf.model.task.Task; -public abstract class SSHCLI<T extends SSHService> implements BackgroundService.StateListener { +@SuppressWarnings("rawtypes") +public abstract class SSHCLI<T extends SSHCLI.Settings> extends AbstractMFAppCLI<T> + implements BackgroundService.StateListener { - protected abstract String appName(); - - protected abstract String description(); - - protected abstract SSHTransferProtocol sshTransferProtocol(); - - protected abstract SSHTransferDirection sshTransferDirection(); - - protected T service; - - protected MFSession session; + public static abstract class Settings<C extends SSHConfigurationBuilder> implements MFApp.Settings { + public abstract C config(); + } - protected boolean async = false; + protected boolean _async = false; private Timer _timer; private String _currentActivity = null; - protected SSHCLI(T service) { - this.service = service; + protected SSHCLI(T settings) { + super(LoggingUtils.createConsoleLogger(), settings); + } - protected void execute(String[] args) throws Throwable { + protected abstract SSHService<?> createService(T settings); - MFConnectionSettings mfcs = new MFConnectionSettings(); - mfcs.findAndLoadFromConfigFile(); - mfcs.loadFromXmlFile(Applications.PROPERTIES_FILE.toFile()); - mfcs.setApp(Applications.APP_NAME); - for (int i = 0; i < args.length;) { - if ("--mf.config".equalsIgnoreCase(args[i])) { - try { - mfcs.loadFromConfigFile(args[i + 1]); - } catch (Throwable e) { - throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); - } + @Override + protected void parseSettings(MFSession session, List<String> args) throws Throwable { + int n = args == null ? 0 : args.size(); + for (int i = 0; i < n;) { + if (args.get(i).equals("--ssh.host")) { + settings().config().setHost(args.get(i + 1)); i += 2; - } else if (args[i].equals("--mf.host")) { - mfcs.setServerHost(args[i + 1]); + } else if (args.get(i).equals("--ssh.port")) { + settings().config().setPort(Integer.parseInt(args.get(i + 1))); i += 2; - } else if (args[i].equals("--mf.port")) { - mfcs.setServerPort(Integer.parseInt(args[i + 1])); + } else if (args.get(i).equals("--ssh.user")) { + settings().config().setUsername(args.get(i + 1)); i += 2; - } else if (args[i].equals("--mf.transport")) { - mfcs.setServerTransport(args[i + 1]); + } else if (args.get(i).equals("--ssh.password")) { + settings().config().setPassword(args.get(i + 1)); i += 2; - } else if (args[i].equals("--mf.auth")) { - String auth = args[i + 1]; - String[] parts = auth.split(","); - if (parts == null || parts.length != 3) { - throw new IllegalArgumentException("Invalid mf.auth: " + auth); - } - mfcs.setUserCredentials(parts[0], parts[1], parts[2]); + } else if (args.get(i).equals("--ssh.private-key")) { + settings().config().setPrivateKey(args.get(i + 1)); i += 2; - } else if (args[i].equals("--mf.token")) { - mfcs.setToken(args[i + 1]); + } else if (args.get(i).equals("--ssh.passphrase")) { + settings().config().setPassphrase(args.get(i + 1)); i += 2; - } else if (args[i].equals("--mf.async")) { - async = true; + } else if (args.get(i).equals("--async")) { + _async = true; i++; - } else if (args[i].equals("--ssh.host")) { - service.setSSHServerHost(args[i + 1]); - i += 2; - } else if (args[i].equals("--ssh.port")) { - service.setSSHServerPort(Integer.parseInt(args[i + 1])); - i += 2; - } else if (args[i].equals("--ssh.user")) { - service.setSSHUsername(args[i + 1]); - i += 2; - } else if (args[i].equals("--ssh.password")) { - service.setSSHPassword(args[i + 1]); - i += 2; - } else if (args[i].equals("--ssh.private-key")) { - service.setSSHPrivateKey(args[i + 1]); - i += 2; - } else if (args[i].equals("--ssh.passphrase")) { - service.setSSHPassphrase(args[i + 1]); - i += 2; } else { i = parseArgs(args, i); } } - // mfcs.checkMissingArguments(); - this.session = new MFSession(mfcs); - if (mfcs.hasMissingArgument()) { - this.session.doConsoleLogon(); - } else { - this.session.testAuthentication(); + } + + protected abstract int parseArgs(List<String> args, int idx); + + public void printUsage(PrintStream s) { + // @formatter:off + s.println(); + s.println("USAGE:"); + s.println(String.format(" %s <mediaflux-arguments> <%s-arguments>", applicationName(), protocol().toLowerCase())); + s.println(); + s.println("DESCRIPTION:"); + s.println(" " + description()); + s.println(); + s.println("MEDIAFLUX ARGUMENTS:"); + super.printMFArgs(s); + s.println(" --async Executes the job in the background. The background service can be checked by executing service.background.describe service in Mediaflux Aterm."); + s.println(); + s.println(String.format("%s ARGUMENTS:", protocol().toUpperCase())); + printSshArgs(s); + s.println(); + s.println("EXAMPLES:"); + printExamples(s); + // @formatter:on + } + + protected void printSshArgs(PrintStream s) { + //@formatter:off + s.println(String.format(" --ssh.host <host> %s server host.", protocol().toUpperCase())); + s.println(String.format(" --ssh.port <port> %s server port. Optional. Defaults to 22.", protocol().toUpperCase())); + s.println(String.format(" --ssh.user <username> %s user name.", protocol().toUpperCase())); + s.println(String.format(" --ssh.password <password> %s user's password.", protocol().toUpperCase())); + s.println(String.format(" --ssh.private-key <private-key> %s user's private key.", protocol().toUpperCase())); + s.println(String.format(" --ssh.passphrase <passphrase> Passphrase for the %s user's private key.", protocol().toUpperCase())); + //@formatter:on + } + + protected abstract String protocol(); + + protected abstract void printExamples(PrintStream s); + + private static String formatTime(double durationSeconds) { + long seconds = (long) durationSeconds; + long minutes = seconds / 60L; + seconds = seconds % 60L; + long hours = minutes / 60L; + minutes = minutes % 60L; + return String.format("%02d:%02d:%02d", hours, minutes, seconds); + } + + public static void execute(SSHCLI<?> cli, String[] args) throws Throwable { + try { + cli.execute(args); + } catch (Throwable e) { + e.printStackTrace(); + if (e instanceof IllegalArgumentException) { + System.err.println("Error: " + e.getMessage()); + cli.printUsage(System.out); + } + System.exit(1); + } + } + + @Override + public void execute(String[] args) throws Throwable { + if (args != null) { + for (String arg : args) { + if ("--async".equalsIgnoreCase(arg)) { + _async = true; + break; + } + } } - long id = this.service.executeBackground(this.session); - if (async) { + super.execute(args, _async); + } + + @Override + public void execute() throws Throwable { + long id = createService(settings()).executeBackground(session()); + if (_async) { System.out.println("Background service ID: " + id); System.out.println(); System.out.println("Run \n service.background.describe :id " + id + "\n to check its status."); - session.discard(); + session().discard(); } else { _timer = new Timer(); _timer.schedule(new TimerTask() { - @Override public void run() { try { - BackgroundService.describe(session, id, SSHCLI.this); + BackgroundService.describe(session(), id, SSHCLI.this); } catch (Throwable e) { e.printStackTrace(); } @@ -129,6 +166,7 @@ public abstract class SSHCLI<T extends SSHService> implements BackgroundService. } } + @Override public void updated(BackgroundService bs) throws Throwable { if (bs.finished()) { _timer.cancel(); @@ -154,11 +192,11 @@ public abstract class SSHCLI<T extends SSHService> implements BackgroundService. System.out.println(bs.state()); } - if (bs.state() == Task.State.COMPLETED && this.service.continueOnError()) { + if (bs.state() == Task.State.COMPLETED) { /* * completed */ - XmlDoc.Element re = bs.getResult(this.session); + XmlDoc.Element re = bs.getResult(session()); List<XmlDoc.Element> fes = re.elements(); if (fes != null) { for (XmlDoc.Element fe : fes) { @@ -168,7 +206,7 @@ public abstract class SSHCLI<T extends SSHService> implements BackgroundService. } if (bs.finished()) { - session.discard(); + session().discard(); } if (bs.failed()) { /* @@ -187,73 +225,4 @@ public abstract class SSHCLI<T extends SSHService> implements BackgroundService. } } - protected abstract int parseArgs(String[] args, int idx); - - public void printUsage(PrintStream s) { - s.println(); - s.println("USAGE:"); - s.println(String.format(" %s <mediaflux-arguments> <%s-arguments>", appName(), - sshTransferProtocol().toString())); - s.println(); - s.println("DESCRIPTION:"); - s.println(" " + description()); - s.println(); - s.println("MEDIAFLUX ARGUMENTS:"); - printMediafluxArgs(s); - s.println(); - s.println(String.format("%s ARGUMENTS:", sshTransferProtocol().toString().toUpperCase())); - printSshArgs(s); - s.println(); - s.println("EXAMPLES:"); - printExamples(s); - } - - protected void printMediafluxArgs(PrintStream s) { - //@formatter:off - s.println(" --mf.config <mflux.cfg> Path to the config file that contains Mediaflux server details and user credentials."); - s.println(" --mf.host <host> Mediaflux server host."); - s.println(" --mf.port <port> Mediaflux server port."); - s.println(" --mf.transport <https|http|tcp/ip> Mediaflux server transport, can be http, https or tcp/ip."); - s.println(" --mf.auth <domain,user,password> Mediaflux user credentials."); - s.println(" --mf.token <token> Mediaflux secure identity token."); - s.println(" --mf.async Executes the job in the background. The background service can be checked by executing service.background.describe service in Mediaflux Aterm."); - //@formatter:on - } - - protected void printSshArgs(PrintStream s) { - String protocol = sshTransferProtocol() == SSHTransferProtocol.SFTP ? "SFTP" : "SSH"; - //@formatter:off - s.println(String.format(" --ssh.host <host> %s server host.", protocol)); - s.println(String.format(" --ssh.port <port> %s server port. Optional. Defaults to 22.", protocol)); - s.println(String.format(" --ssh.user <username> %s user name.", protocol)); - s.println(String.format(" --ssh.password <password> %s user's password.", protocol)); - s.println(String.format(" --ssh.private-key <private-key> %s user's private key.", protocol)); - s.println(String.format(" --ssh.passphrase <passphrase> Passphrase for the %s user's private key.", protocol)); - //@formatter:on - } - - protected abstract void printExamples(PrintStream s); - - private static String formatTime(double durationSeconds) { - long seconds = (long) durationSeconds; - long minutes = seconds / 60L; - seconds = seconds % 60L; - long hours = minutes / 60L; - minutes = minutes % 60L; - return String.format("%02d:%02d:%02d", hours, minutes, seconds); - } - - public static <T extends SSHService> void execute(SSHCLI<T> cli, String[] args) throws Throwable { - try { - cli.execute(args); - } catch (Throwable e) { - e.printStackTrace(); - if (e instanceof IllegalArgumentException) { - System.err.println("Error: " + e.getMessage()); - cli.printUsage(System.out); - } - System.exit(1); - } - } - } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SSHGetCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SSHGetCLI.java index a3c76091392c7bec27c72cbd6b8f512f3163602c..f87f09cf11f7bf76b884544635c6348d4c034b2f 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SSHGetCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SSHGetCLI.java @@ -3,55 +3,65 @@ package unimelb.mf.client.ssh.cli; import java.io.PrintStream; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.List; -import unimelb.mf.client.ssh.SSHGetService; -import unimelb.mf.client.ssh.SSHTransferDirection; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHGetConfigurationBuilder; import unimelb.mf.model.asset.worm.Worm; -public abstract class SSHGetCLI<T extends SSHGetService> extends SSHCLI<T> { +public abstract class SSHGetCLI extends SSHCLI<SSHGetCLI.Settings> { - protected SSHGetCLI(T service) { - super(service); + protected SSHGetCLI() { + super(new SSHGetCLI.Settings()); } - @Override - protected final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.GET; + public static class Settings extends SSHCLI.Settings<SSHGetConfigurationBuilder> { + + private SSHGetConfigurationBuilder _config; + + public Settings() { + _config = new SSHGetConfigurationBuilder(); + } + + @Override + public SSHGetConfigurationBuilder config() { + return _config; + } + } - protected int parseArgs(String[] args, int i) { - if (args[i].equalsIgnoreCase("--mf.namespace")) { - this.service.setDstNamespace(args[i + 1]); + @Override + protected int parseArgs(List<String> args, int i) { + if (args.get(i).equalsIgnoreCase("--mf.namespace")) { + settings().config().setDstNamespace(args.get(i + 1)); return i + 2; - } else if (args[i].equalsIgnoreCase("--mf.readonly")) { - this.service.setReadOnly(true); + } else if (args.get(i).equalsIgnoreCase("--mf.readonly")) { + settings().config().setReadOnly(true); return i + 1; - } else if (args[i].equalsIgnoreCase("--mf.worm")) { - if (this.service.worm() == null) { - this.service.setWorm(new Worm()); + } else if (args.get(i).equalsIgnoreCase("--mf.worm")) { + if (settings().config().worm() == null) { + settings().config().setWorm(new Worm()); } return i + 1; - } else if (args[i].equalsIgnoreCase("--mf.worm.expiry")) { - if (this.service.worm() == null) { - this.service.setWorm(new Worm()); + } else if (args.get(i).equalsIgnoreCase("--mf.worm.expiry")) { + if (settings().config().worm() == null) { + settings().config().setWorm(new Worm()); } try { - this.service.worm().setExpiry(new SimpleDateFormat("d-MMM-yyyy").parse(args[i + 1])); + settings().config().worm().setExpiry(new SimpleDateFormat("d-MMM-yyyy").parse(args.get(i + 1))); } catch (ParseException pe) { - throw new IllegalArgumentException("Invalid date value for --mf.worm.expiry: " + args[i + 1], pe); + throw new IllegalArgumentException("Invalid date value for --mf.worm.expiry: " + args.get(i + 1), pe); } return i + 2; - } else if (args[i].equalsIgnoreCase("--ssh.path")) { - this.service.addSrcPath(args[i + 1]); + } else if (args.get(i).equalsIgnoreCase("--ssh.path")) { + settings().config().addSrcPath(args.get(i + 1)); return i + 2; } else { - throw new IllegalArgumentException("Unexpected argument: " + args[i]); + throw new IllegalArgumentException("Unexpected argument: " + args.get(i)); } } - protected void printMediafluxArgs(PrintStream s) { - super.printMediafluxArgs(s); + @Override + protected void printMFArgs(PrintStream s) { //@formatter:off s.println(" --mf.namespace <dst-namespace> Destination namespace on Mediaflux."); s.println(" --mf.readonly Set the assets to be read-only."); @@ -60,20 +70,19 @@ public abstract class SSHGetCLI<T extends SSHGetService> extends SSHCLI<T> { //@formatter:on } + @Override protected void printSshArgs(PrintStream s) { super.printSshArgs(s); - String protocol = sshTransferProtocol() == SSHTransferProtocol.SFTP ? "SFTP" : "SSH"; //@formatter:off - s.println(String.format(" --ssh.path <src-path> Source path on remote %s server.", protocol)); + s.println(String.format(" --ssh.path <src-path> Source path on remote %s server.", protocol().toUpperCase())); //@formatter:on } @Override protected void printExamples(PrintStream s) { //@formatter:off - s.println(String.format(" The command below imports files from %s server into the specified Mediaflux asset namespace:", sshTransferProtocol())); - s.println(String.format(" %s --mf.host mediaflux.your-domain.org --mf.port 443 --mf.transport 443 --mf.auth mf_domain,mf_user,MF_PASSWD --mf.namespace /path/to/dst-namespace --ssh.host ssh-server.your-domain.org --ssh.port 22 --ssh.user ssh_username --ssh.password SSH_PASSWD --ssh.path path/to/src-directory", appName())); - + s.println(String.format(" The command below imports files from %s server into the specified Mediaflux asset namespace:", protocol().toUpperCase())); + s.println(String.format(" %s --mf.host mediaflux.your-domain.org --mf.port 443 --mf.transport 443 --mf.auth mf_domain,mf_user,MF_PASSWD --mf.namespace /path/to/dst-namespace --ssh.host ssh-server.your-domain.org --ssh.port 22 --ssh.user ssh_username --ssh.password SSH_PASSWD --ssh.path path/to/src-directory", applicationName())); s.println(); //@formatter:on } diff --git a/src/main/java/unimelb/mf/client/ssh/cli/SSHPutCLI.java b/src/main/java/unimelb/mf/client/ssh/cli/SSHPutCLI.java index 19fbf9b34dd24aac31f29feea117907bf32c96ab..5163a39639e8243e359294c1dd914d463e52ab65 100644 --- a/src/main/java/unimelb/mf/client/ssh/cli/SSHPutCLI.java +++ b/src/main/java/unimelb/mf/client/ssh/cli/SSHPutCLI.java @@ -1,59 +1,69 @@ package unimelb.mf.client.ssh.cli; import java.io.PrintStream; +import java.util.List; -import unimelb.mf.client.ssh.SSHPutService; -import unimelb.mf.client.ssh.SSHTransferDirection; -import unimelb.mf.client.ssh.SSHTransferProtocol; +import unimelb.mf.client.ssh.SSHPutConfigurationBuilder; -public abstract class SSHPutCLI<T extends SSHPutService> extends SSHCLI<T> { +public abstract class SSHPutCLI extends SSHCLI<SSHPutCLI.Settings> { - protected SSHPutCLI(T service) { - super(service); + protected SSHPutCLI() { + super(new SSHPutCLI.Settings()); } - @Override - protected final SSHTransferDirection sshTransferDirection() { - return SSHTransferDirection.PUT; + public static class Settings extends SSHCLI.Settings<SSHPutConfigurationBuilder> { + + private SSHPutConfigurationBuilder _config; + + public Settings() { + _config = new SSHPutConfigurationBuilder(); + } + + @Override + public SSHPutConfigurationBuilder config() { + return _config; + } + } - protected int parseArgs(String[] args, int i) { - if (args[i].equalsIgnoreCase("--mf.namespace")) { - this.service.addNamespace(args[i + 1]); + @Override + protected int parseArgs(List<String> args, int i) { + if (args.get(i).equalsIgnoreCase("--mf.namespace")) { + settings().config().addNamespace(args.get(i + 1)); return i + 2; - } else if (args[i].equalsIgnoreCase("--mf.unarchive")) { - this.service.setUnarchiveContents(true); + } else if (args.get(i).equalsIgnoreCase("--mf.unarchive")) { + settings().config().setUnarchiveContents(true); return i + 1; - } else if (args[i].equalsIgnoreCase("--ssh.directory")) { - this.service.setDstDirectory(args[i + 1]); + } else if (args.get(i).equalsIgnoreCase("--ssh.directory")) { + settings().config().setDstDirectory(args.get(i + 1)); return i + 2; } else { - throw new IllegalArgumentException("Unexpected argument: " + args[i]); + throw new IllegalArgumentException("Unexpected argument: " + args.get(i)); } } - protected void printMediafluxArgs(PrintStream s) { - super.printMediafluxArgs(s); + @Override + protected void printMFArgs(PrintStream s) { + super.printMFArgs(s); //@formatter:off s.println(" --mf.namespace <src-namespace> Source namespace on Mediaflux."); s.println(" --mf.unarchive Unpack asset contents."); //@formatter:on } + @Override protected void printSshArgs(PrintStream s) { super.printSshArgs(s); - String protocol = sshTransferProtocol() == SSHTransferProtocol.SFTP ? "SFTP" : "SSH"; //@formatter:off - s.println(String.format(" --ssh.directory <dst-directory> Destination directory on remote %s server.", protocol)); + s.println(String.format(" --ssh.directory <dst-directory> Destination directory on remote %s server.", protocol().toUpperCase())); //@formatter:on } @Override protected void printExamples(PrintStream s) { //@formatter:off - s.println(String.format(" The command below exports assets from the specified Mediaflux asset namespace to remote %s server:", sshTransferProtocol())); - s.println(String.format(" %s --mf.host mediaflux.your-domain.org --mf.port 443 --mf.transport 443 --mf.auth mf_domain,mf_user,MF_PASSWD --mf.namespace /path/to/src-namespace --ssh.host ssh-server.your-domain.org --ssh.port 22 --ssh.user ssh_username --ssh.password SSH_PASSWD --ssh.directory path/to/dst-directory", appName())); - + s.println(String.format(" The command below exports assets from the specified Mediaflux asset namespace to remote %s server:", protocol().toUpperCase())); + s.println(String.format(" %s --mf.host mediaflux.your-domain.org --mf.port 443 --mf.transport 443 --mf.auth mf_domain,mf_user,MF_PASSWD --mf.namespace /path/to/src-namespace --ssh.host ssh-server.your-domain.org --ssh.port 22 --ssh.user ssh_username --ssh.password SSH_PASSWD --ssh.directory path/to/dst-directory", applicationName())); s.println(); //@formatter:on } diff --git a/src/main/java/unimelb/mf/client/sync/check/DefaultCheckHandler.java b/src/main/java/unimelb/mf/client/sync/check/DefaultCheckHandler.java index a65da82d81859a480f0dfc81edda966028cbe60a..c4f21932c2aed4afc4d5d220840b40e09f3bd946 100644 --- a/src/main/java/unimelb/mf/client/sync/check/DefaultCheckHandler.java +++ b/src/main/java/unimelb/mf/client/sync/check/DefaultCheckHandler.java @@ -34,11 +34,14 @@ public class DefaultCheckHandler implements CheckHandler { private Path _outputFile; - public DefaultCheckHandler(Path outputFile) throws Throwable { - this(outputFile.getParent(), outputFile.getFileName().toString()); + private boolean _detailedOutput = false;; + + public DefaultCheckHandler(Path outputFile, boolean detailedOutput) throws Throwable { + this(outputFile.getParent(), outputFile.getFileName().toString(), detailedOutput); } - public DefaultCheckHandler(Path outputDir, String fileName) throws Throwable { + public DefaultCheckHandler(Path outputDir, String fileName, boolean detailedOutput) throws Throwable { + _detailedOutput = detailedOutput; if (!Files.exists(outputDir)) { throw new IllegalArgumentException("Directory: '" + outputDir.toString() + "' does not exist.", new FileNotFoundException(outputDir.toString())); @@ -64,11 +67,6 @@ public class DefaultCheckHandler implements CheckHandler { _outputFile = Paths.get(outputDir.toString(), fileName); } - public DefaultCheckHandler(String outputCsvPath) throws Throwable { - this(Paths.get(PathUtils.getParentPath(PathUtils.toSystemIndependent(outputCsvPath))), - PathUtils.getFileName(PathUtils.toSystemIndependent(outputCsvPath))); - } - public void writeSummary() { _csvLogger.info(",,,,"); _csvLogger.info(",,,,"); @@ -118,6 +116,9 @@ public class DefaultCheckHandler implements CheckHandler { _nbFileChecked.getAndIncrement(); if (result.match()) { _nbFilePassed.getAndIncrement(); + if (_detailedOutput) { + result.log(_csvLogger); + } } else { _nbFileFailed.getAndIncrement(); if (!result.exists()) { diff --git a/src/main/java/unimelb/mf/client/sync/cli/MFCheck.java b/src/main/java/unimelb/mf/client/sync/cli/MFCheck.java index eb33b89b20f72fef4c606e5cb01964f50d4c0923..94bbc59fd40cc7a33b6301f76321d6f253225330 100644 --- a/src/main/java/unimelb/mf/client/sync/cli/MFCheck.java +++ b/src/main/java/unimelb/mf/client/sync/cli/MFCheck.java @@ -1,5 +1,6 @@ package unimelb.mf.client.sync.cli; +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -11,7 +12,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import unimelb.mf.client.session.MFConnectionSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; import unimelb.mf.client.session.MFSession; import unimelb.mf.client.sync.MFSyncApp; import unimelb.mf.client.sync.check.DefaultCheckHandler; @@ -24,10 +25,11 @@ public class MFCheck extends MFSyncApp { public static final String PROG = "unimelb-mf-check"; - private MFConnectionSettings _connectionSettings; + private MFConfigurationBuilder _mfconfig; private Map<Path, String> _dirNamespaces; private Action.Direction _direction; private Path _outputFile; + private boolean _detailedOutput = false; private DefaultCheckHandler _checkHandler; public MFCheck() { @@ -86,10 +88,10 @@ public class MFCheck extends MFSyncApp { } protected void parseArgs(String[] args) throws Throwable { - if (_connectionSettings == null) { - _connectionSettings = new MFConnectionSettings(); - _connectionSettings.findAndLoadFromConfigFile(); - _connectionSettings.setApp(applicationName()); + if (_mfconfig == null) { + _mfconfig = new MFConfigurationBuilder().setConsoleLogon(true); + _mfconfig.findAndLoadFromConfigFile(); + _mfconfig.setApp(applicationName()); } if (args != null) { try { @@ -140,12 +142,7 @@ public class MFCheck extends MFSyncApp { /* * test MF authentication */ - MFSession session = new MFSession(_connectionSettings); - if (_connectionSettings.hasMissingArgument()) { - session.doConsoleLogon(); - } else { - session.testAuthentication(); - } + MFSession session = MFSession.create(_mfconfig); /* * set MF session @@ -165,26 +162,26 @@ public class MFCheck extends MFSyncApp { settings().addJob(job); } - _checkHandler = new DefaultCheckHandler(_outputFile); + _checkHandler = new DefaultCheckHandler(_outputFile, _detailedOutput); settings().setCheckHandler(_checkHandler); } protected int parseMFOptions(String[] args, int i) throws Throwable { if ("--mf.config".equalsIgnoreCase(args[i])) { try { - _connectionSettings.loadFromConfigFile(args[i + 1]); + _mfconfig.loadFromConfigFile(args[i + 1]); } catch (Throwable e) { throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); } return 2; } else if ("--mf.host".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerHost(args[i + 1]); + _mfconfig.setHost(args[i + 1]); return 2; } else if ("--mf.port".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerPort(Integer.parseInt(args[i + 1])); + _mfconfig.setPort(Integer.parseInt(args[i + 1])); return 2; } else if ("--mf.transport".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerTransport(args[i + 1]); + _mfconfig.setTransport(args[i + 1]); return 2; } else if ("--mf.auth".equalsIgnoreCase(args[i])) { String auth = args[i + 1]; @@ -192,10 +189,10 @@ public class MFCheck extends MFSyncApp { if (parts == null || parts.length != 3) { throw new IllegalArgumentException("Invalid mf.auth: " + auth); } - _connectionSettings.setUserCredentials(parts[0], parts[1], parts[2]); + _mfconfig.setUserCredentials(parts[0], parts[1], parts[2]); return 2; } else if ("--mf.token".equalsIgnoreCase(args[i])) { - _connectionSettings.setToken(args[i + 1]); + _mfconfig.setToken(args[i + 1]); return 2; } else { return 0; @@ -211,12 +208,19 @@ public class MFCheck extends MFSyncApp { return 2; } else if ("--output".equalsIgnoreCase(args[i]) || "-o".equalsIgnoreCase(args[i])) { _outputFile = Paths.get(args[i + 1]); - Path dir = _outputFile.toAbsolutePath().getParent(); - if (!Files.exists(dir)) { - Files.createDirectories(dir); + if (args[i + 1].indexOf('/') < 0 || args[i + 1].indexOf(File.separatorChar) < 0) { + _outputFile = Paths.get(System.getProperty("user.dir"), args[i + 1]); + } else { + Path dir = _outputFile.toAbsolutePath().getParent(); + if (!Files.exists(dir)) { + Files.createDirectories(dir); + } } _outputFile = renameOutputCsvFile(_outputFile); return 2; + } else if ("--detailed-output".equalsIgnoreCase(args[i])) { + _detailedOutput = true; + return 1; } else if ("--no-csum-check".equalsIgnoreCase(args[i])) { settings().setCsumCheck(false); return 1; diff --git a/src/main/java/unimelb/mf/client/sync/cli/MFDownload.java b/src/main/java/unimelb/mf/client/sync/cli/MFDownload.java index 3c84fe7a967bcf6865cf74b0ecc63747a22b39e9..9783ce1e03d7dd8b9a26bfd210e5e358962571d7 100644 --- a/src/main/java/unimelb/mf/client/sync/cli/MFDownload.java +++ b/src/main/java/unimelb/mf/client/sync/cli/MFDownload.java @@ -8,7 +8,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import unimelb.mf.client.session.MFConnectionSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; import unimelb.mf.client.session.MFSession; import unimelb.mf.client.sync.MFSyncApp; import unimelb.mf.client.sync.settings.Action; @@ -21,7 +21,7 @@ public class MFDownload extends MFSyncApp { public static final String PROG = "unimelb-mf-download"; - private MFConnectionSettings _connectionSettings; + private MFConfigurationBuilder _mfconfig; private Set<String> _namespaces; private Path _rootDir; @@ -89,10 +89,10 @@ public class MFDownload extends MFSyncApp { } protected void parseArgs(String[] args) throws Throwable { - if (_connectionSettings == null) { - _connectionSettings = new MFConnectionSettings(); - _connectionSettings.findAndLoadFromConfigFile(); - _connectionSettings.setApp(applicationName()); + if (_mfconfig == null) { + _mfconfig = new MFConfigurationBuilder().setConsoleLogon(true); + _mfconfig.findAndLoadFromConfigFile(); + _mfconfig.setApp(applicationName()); } if (args != null) { try { @@ -129,12 +129,7 @@ public class MFDownload extends MFSyncApp { /* * test MF authentication */ - MFSession session = new MFSession(_connectionSettings); - if (_connectionSettings.hasMissingArgument()) { - session.doConsoleLogon(); - } else { - session.testAuthentication(); - } + MFSession session = MFSession.create(_mfconfig); /* * set MF session @@ -155,19 +150,19 @@ public class MFDownload extends MFSyncApp { protected int parseMFOptions(String[] args, int i) throws Throwable { if ("--mf.config".equalsIgnoreCase(args[i])) { try { - _connectionSettings.loadFromConfigFile(args[i + 1]); + _mfconfig.loadFromConfigFile(args[i + 1]); } catch (Throwable e) { throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); } return 2; } else if ("--mf.host".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerHost(args[i + 1]); + _mfconfig.setHost(args[i + 1]); return 2; } else if ("--mf.port".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerPort(Integer.parseInt(args[i + 1])); + _mfconfig.setPort(Integer.parseInt(args[i + 1])); return 2; } else if ("--mf.transport".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerTransport(args[i + 1]); + _mfconfig.setTransport(args[i + 1]); return 2; } else if ("--mf.auth".equalsIgnoreCase(args[i])) { String auth = args[i + 1]; @@ -175,10 +170,10 @@ public class MFDownload extends MFSyncApp { if (parts == null || parts.length != 3) { throw new IllegalArgumentException("Invalid mf.auth: " + auth); } - _connectionSettings.setUserCredentials(parts[0], parts[1], parts[2]); + _mfconfig.setUserCredentials(parts[0], parts[1], parts[2]); return 2; } else if ("--mf.token".equalsIgnoreCase(args[i])) { - _connectionSettings.setToken(args[i + 1]); + _mfconfig.setToken(args[i + 1]); return 2; } else { return 0; diff --git a/src/main/java/unimelb/mf/client/sync/cli/MFSync.java b/src/main/java/unimelb/mf/client/sync/cli/MFSync.java index fe9730750f342fdd4fc9b047da423b4f61f91b3b..dc240ae392b5ee10a9ea62380d0398c06e9c9987 100644 --- a/src/main/java/unimelb/mf/client/sync/cli/MFSync.java +++ b/src/main/java/unimelb/mf/client/sync/cli/MFSync.java @@ -10,7 +10,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import unimelb.mf.client.session.MFConnectionSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; import unimelb.mf.client.session.MFSession; import unimelb.mf.client.sync.MFSyncApp; import unimelb.mf.client.sync.settings.Action; @@ -23,7 +23,7 @@ public class MFSync extends MFSyncApp { public static final String PROG = "unimelb-mf-sync"; - private MFConnectionSettings _connectionSettings; + private MFConfigurationBuilder _mfconfig; private Map<Path, String> _dirNss; private Map<String, Path> _nsDirs; @@ -86,10 +86,10 @@ public class MFSync extends MFSyncApp { } protected void parseArgs(String[] args) throws Throwable { - if (_connectionSettings == null) { - _connectionSettings = new MFConnectionSettings(); - _connectionSettings.findAndLoadFromConfigFile(); - _connectionSettings.setApp(applicationName()); + if (_mfconfig == null) { + _mfconfig = new MFConfigurationBuilder().setConsoleLogon(true); + _mfconfig.findAndLoadFromConfigFile(); + _mfconfig.setApp(applicationName()); } if (args != null) { try { @@ -132,12 +132,7 @@ public class MFSync extends MFSyncApp { /* * test MF authentication */ - MFSession session = new MFSession(_connectionSettings); - if (_connectionSettings.hasMissingArgument()) { - session.doConsoleLogon(); - } else { - session.testAuthentication(); - } + MFSession session = MFSession.create(_mfconfig); /* * set MF session @@ -167,19 +162,19 @@ public class MFSync extends MFSyncApp { protected int parseMFOptions(String[] args, int i) throws Throwable { if ("--mf.config".equalsIgnoreCase(args[i])) { try { - _connectionSettings.loadFromConfigFile(args[i + 1]); + _mfconfig.loadFromConfigFile(args[i + 1]); } catch (Throwable e) { throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); } return 2; } else if ("--mf.host".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerHost(args[i + 1]); + _mfconfig.setHost(args[i + 1]); return 2; } else if ("--mf.port".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerPort(Integer.parseInt(args[i + 1])); + _mfconfig.setPort(Integer.parseInt(args[i + 1])); return 2; } else if ("--mf.transport".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerTransport(args[i + 1]); + _mfconfig.setTransport(args[i + 1]); return 2; } else if ("--mf.auth".equalsIgnoreCase(args[i])) { String auth = args[i + 1]; @@ -187,10 +182,10 @@ public class MFSync extends MFSyncApp { if (parts == null || parts.length != 3) { throw new IllegalArgumentException("Invalid mf.auth: " + auth); } - _connectionSettings.setUserCredentials(parts[0], parts[1], parts[2]); + _mfconfig.setUserCredentials(parts[0], parts[1], parts[2]); return 2; } else if ("--mf.token".equalsIgnoreCase(args[i])) { - _connectionSettings.setToken(args[i + 1]); + _mfconfig.setToken(args[i + 1]); return 2; } else { return 0; diff --git a/src/main/java/unimelb/mf/client/sync/cli/MFUpload.java b/src/main/java/unimelb/mf/client/sync/cli/MFUpload.java index 6cdd47d12a9225cfa5c4ee2d06dfc64b4a2127c9..f17ddfb1b95620e125b44bf295c1f446bf5396fa 100644 --- a/src/main/java/unimelb/mf/client/sync/cli/MFUpload.java +++ b/src/main/java/unimelb/mf/client/sync/cli/MFUpload.java @@ -9,7 +9,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import unimelb.mf.client.session.MFConnectionSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; import unimelb.mf.client.session.MFSession; import unimelb.mf.client.sync.MFSyncApp; import unimelb.mf.client.sync.settings.Action; @@ -21,7 +21,7 @@ public class MFUpload extends MFSyncApp { public static final String PROG = "unimelb-mf-upload"; - private MFConnectionSettings _connectionSettings; + private MFConfigurationBuilder _mfconfig; private Set<Path> _dirs; private String _rootNS; @@ -86,10 +86,10 @@ public class MFUpload extends MFSyncApp { } protected void parseArgs(String[] args) throws Throwable { - if (_connectionSettings == null) { - _connectionSettings = new MFConnectionSettings(); - _connectionSettings.findAndLoadFromConfigFile(); - _connectionSettings.setApp(applicationName()); + if (_mfconfig == null) { + _mfconfig = new MFConfigurationBuilder().setConsoleLogon(true); + _mfconfig.findAndLoadFromConfigFile(); + _mfconfig.setApp(applicationName()); } if (args != null) { try { @@ -133,12 +133,7 @@ public class MFUpload extends MFSyncApp { /* * test MF authentication */ - MFSession session = new MFSession(_connectionSettings); - if (_connectionSettings.hasMissingArgument()) { - session.doConsoleLogon(); - } else { - session.testAuthentication(); - } + MFSession session = MFSession.create(_mfconfig); /* * set MF session @@ -159,19 +154,19 @@ public class MFUpload extends MFSyncApp { protected int parseMFOptions(String[] args, int i) throws Throwable { if ("--mf.config".equalsIgnoreCase(args[i])) { try { - _connectionSettings.loadFromConfigFile(args[i + 1]); + _mfconfig.loadFromConfigFile(args[i + 1]); } catch (Throwable e) { throw new IllegalArgumentException("Invalid --mf.config: " + args[i + 1], e); } return 2; } else if ("--mf.host".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerHost(args[i + 1]); + _mfconfig.setHost(args[i + 1]); return 2; } else if ("--mf.port".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerPort(Integer.parseInt(args[i + 1])); + _mfconfig.setPort(Integer.parseInt(args[i + 1])); return 2; } else if ("--mf.transport".equalsIgnoreCase(args[i])) { - _connectionSettings.setServerTransport(args[i + 1]); + _mfconfig.setTransport(args[i + 1]); return 2; } else if ("--mf.auth".equalsIgnoreCase(args[i])) { String auth = args[i + 1]; @@ -179,10 +174,10 @@ public class MFUpload extends MFSyncApp { if (parts == null || parts.length != 3) { throw new IllegalArgumentException("Invalid mf.auth: " + auth); } - _connectionSettings.setUserCredentials(parts[0], parts[1], parts[2]); + _mfconfig.setUserCredentials(parts[0], parts[1], parts[2]); return 2; } else if ("--mf.token".equalsIgnoreCase(args[i])) { - _connectionSettings.setToken(args[i + 1]); + _mfconfig.setToken(args[i + 1]); return 2; } else { return 0; diff --git a/src/main/java/unimelb/mf/client/sync/task/AssetDownloadTask.java b/src/main/java/unimelb/mf/client/sync/task/AssetDownloadTask.java index ae7db81c127985c59c43c200411571ab3d4d8dff..8418b0aa985cbd2ccea25e2f5849992d850a53a4 100644 --- a/src/main/java/unimelb/mf/client/sync/task/AssetDownloadTask.java +++ b/src/main/java/unimelb/mf/client/sync/task/AssetDownloadTask.java @@ -7,7 +7,6 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; import java.util.logging.Logger; import arc.archive.ArchiveInput; @@ -167,7 +166,7 @@ public class AssetDownloadTask extends AbstractMFTask { XmlStringWriter w = new XmlStringWriter(); w.add("id", _assetId != null ? _assetId : ("path=" + _assetPath)); - session().execute("asset.get", w.document(), (List<ServerClient.Input>) null, output, this); + session().execute("asset.get", w.document(), output, this); } private boolean needToUnarchive(XmlDoc.Element ae) throws Throwable { diff --git a/src/main/java/unimelb/mf/client/sync/task/FileUploadTask.java b/src/main/java/unimelb/mf/client/sync/task/FileUploadTask.java index a42ffbd6f489b09a410c64be0df8bf4b399e73ce..04a6b1598cde2537740239a22c594af348a30a42 100644 --- a/src/main/java/unimelb/mf/client/sync/task/FileUploadTask.java +++ b/src/main/java/unimelb/mf/client/sync/task/FileUploadTask.java @@ -132,7 +132,8 @@ public class FileUploadTask extends AbstractMFTask { setCurrentOperation("Uploading file: '" + _file + "' to asset: '" + _assetPath + "'"); logInfo("Uploading file: '" + _file + "' to asset: '" + _assetPath + "'"); - XmlDoc.Element re = session().execute("service.execute", w2.document(), input, null, this); + + XmlDoc.Element re = session().execute("service.execute", w2.document(), input, this); if (_csumCheck) { XmlDoc.Element ae = re.element("reply[@service='asset.get']/response/asset"); _assetId = re.value("id"); diff --git a/src/main/java/unimelb/mf/client/task/AbstractMFAppCLI.java b/src/main/java/unimelb/mf/client/task/AbstractMFAppCLI.java index 4b80226a7d7b0ee867ccf5d8ba97a2e28b2042ed..a571585102bf7216ad4dbcd59fbc51c865ae9638 100644 --- a/src/main/java/unimelb/mf/client/task/AbstractMFAppCLI.java +++ b/src/main/java/unimelb/mf/client/task/AbstractMFAppCLI.java @@ -4,7 +4,7 @@ import java.io.PrintStream; import java.util.List; import java.util.logging.Logger; -import unimelb.mf.client.session.MFConnectionSettings; +import unimelb.mf.client.session.MFConfigurationBuilder; import unimelb.mf.client.session.MFSession; import unimelb.mf.client.util.LoggingUtils; @@ -12,12 +12,13 @@ public abstract class AbstractMFAppCLI<T extends MFApp.Settings> extends Abstrac private T _settings; - protected AbstractMFAppCLI(Logger logger) { + protected AbstractMFAppCLI(Logger logger, T settings) { if (logger == null) { setLogger(LoggingUtils.createConsoleLogger()); } else { setLogger(logger); } + _settings = settings; } @Override @@ -27,25 +28,26 @@ public abstract class AbstractMFAppCLI<T extends MFApp.Settings> extends Abstrac @Override public void execute(String[] args) throws Throwable { + execute(args, true); + } + + protected void execute(String[] args, boolean discardSession) throws Throwable { try { - MFConnectionSettings cxnSettings = new MFConnectionSettings(); - cxnSettings.findAndLoadFromConfigFile(); - cxnSettings.setApp(applicationName()); - List<String> remainArgs = cxnSettings.parseArgs(args); - MFSession session = new MFSession(cxnSettings); - try { - if (cxnSettings.hasMissingArgument()) { - session.doConsoleLogon(); - } else { - session.testAuthentication(); - } - setSession(session); - _settings = parseSettings(session, remainArgs); + MFConfigurationBuilder config = new MFConfigurationBuilder().setConsoleLogon(true); + config.findAndLoadFromConfigFile(); + config.setApp(applicationName()); + List<String> remainArgs = config.parseArgs(args); - execute(); + MFSession session = MFSession.create(config); + setSession(session); + try { + parseSettings(session, remainArgs); + execute(); } finally { - session.discard(); + if (discardSession) { + session.discard(); + } } } catch (IllegalArgumentException iae) { iae.printStackTrace(); @@ -55,31 +57,17 @@ public abstract class AbstractMFAppCLI<T extends MFApp.Settings> extends Abstrac } } - protected void printMFArgs(PrintStream ps, int indent) { - String indentStr = ""; - if (indent > 0) { - indentStr = new String(new char[indent]).replace("\0", " "); - } + protected void printMFArgs(PrintStream ps) { // @formatter:off - ps.print(indentStr); - ps.println("--mf.config <mflux.cfg> Path to the config file that contains Mediaflux server details and user credentials."); - ps.print(indentStr); - ps.println("--mf.host <host> Mediaflux server host."); - ps.print(indentStr); - ps.println("--mf.port <port> Mediaflux server port."); - ps.print(indentStr); - ps.println("--mf.transport <https|http|tcp/ip> Mediaflux server transport, can be http, https or tcp/ip."); - ps.print(indentStr); - ps.println("--mf.auth <domain,user,password> Mediaflux user credentials."); - ps.print(indentStr); - ps.println("--mf.token <token> Mediaflux secure identity token."); + ps.println(" --mf.config <mflux.cfg> Path to the config file that contains Mediaflux server details and user credentials."); + ps.println(" --mf.host <host> Mediaflux server host."); + ps.println(" --mf.port <port> Mediaflux server port."); + ps.println(" --mf.transport <https|http|tcp/ip> Mediaflux server transport, can be http, https or tcp/ip."); + ps.println(" --mf.auth <domain,user,password> Mediaflux user credentials."); + ps.println(" --mf.token <token> Mediaflux secure identity token."); // @formatter:on } - protected void printMFArgs(PrintStream ps) { - printMFArgs(ps, 4); - } - - protected abstract T parseSettings(MFSession session, List<String> args) throws Throwable; + protected abstract void parseSettings(MFSession session, List<String> args) throws Throwable; } diff --git a/src/main/java/unimelb/mf/client/task/AbstractMFTask.java b/src/main/java/unimelb/mf/client/task/AbstractMFTask.java index ffe2bdb978a4c6adee8d371a7c4acb0c807510a3..9d4d25dcfb175073a218195bdfea13a3cc36d20e 100644 --- a/src/main/java/unimelb/mf/client/task/AbstractMFTask.java +++ b/src/main/java/unimelb/mf/client/task/AbstractMFTask.java @@ -31,13 +31,15 @@ public abstract class AbstractMFTask implements MFTask { } @Override - public void setAbortableOperation(CanAbort ca) { + public void started(CanAbort ca) { _ca = ca; } @Override - public CanAbort abortableOperation() { - return _ca; + public void finished(CanAbort ca) { + if (_ca != null && _ca.equals(ca)) { + _ca = null; + } } @Override @@ -84,10 +86,9 @@ public abstract class AbstractMFTask implements MFTask { logError(e); if (e instanceof InterruptedException) { Thread.currentThread().interrupt(); - CanAbort ca = abortableOperation(); - if (ca != null) { + if (_ca != null) { try { - ca.abort(); + _ca.abort(); } catch (Throwable e1) { logError("Fail to abort service call.", e1); } diff --git a/src/main/java/unimelb/mf/client/task/MFTask.java b/src/main/java/unimelb/mf/client/task/MFTask.java index 2906427111d5f4a342ffe21a643e423759db435b..b5eb499ad463a73f9b10f844dddae841b0d08208 100644 --- a/src/main/java/unimelb/mf/client/task/MFTask.java +++ b/src/main/java/unimelb/mf/client/task/MFTask.java @@ -2,12 +2,12 @@ package unimelb.mf.client.task; import java.util.concurrent.Callable; +import arc.utils.AbortableOperationHandler; import unimelb.mf.client.session.HasMFSession; -import unimelb.mf.client.util.HasAbortableOperation; import unimelb.mf.client.util.HasProgress; import unimelb.mf.client.util.Loggable; -public interface MFTask extends Callable<Void>, Loggable, HasMFSession, HasAbortableOperation, HasProgress { +public interface MFTask extends Callable<Void>, Loggable, HasMFSession, AbortableOperationHandler, HasProgress { void execute() throws Throwable; } diff --git a/src/main/java/unimelb/mf/client/terminal/MFTerminal.java b/src/main/java/unimelb/mf/client/terminal/MFTerminal.java index f92e1370b68d6184f017a33e87a09d8223a1f3f3..cad75e3ea5f6d79ed7a057c90b71db6ded1d98de 100644 --- a/src/main/java/unimelb/mf/client/terminal/MFTerminal.java +++ b/src/main/java/unimelb/mf/client/terminal/MFTerminal.java @@ -297,7 +297,7 @@ public class MFTerminal extends AbstractMFAppCLI<MFTerminal.Settings> { private Logger _termLogger; public MFTerminal() throws Throwable { - super(Logger.getLogger("org.jline")); + super(Logger.getLogger("org.jline"), new Settings()); _dir = Paths.get(System.getProperty("user.dir")).toAbsolutePath(); this.logger().setLevel(Level.FINE); _termLogger = Logger.getLogger(APP_NAME); @@ -502,17 +502,15 @@ public class MFTerminal extends AbstractMFAppCLI<MFTerminal.Settings> { } @Override - protected Settings parseSettings(MFSession session, List<String> args) throws Throwable { - Settings settings = new Settings(); + protected void parseSettings(MFSession session, List<String> args) throws Throwable { for (int i = 0; i < args.size();) { if ("-h".equalsIgnoreCase(args.get(i)) || "--help".equalsIgnoreCase(args.get(i))) { - settings.setShowHelp(true); + settings().setShowHelp(true); i++; } else { throw new IllegalArgumentException("Unexpected argument: " + args.get(i)); } } - return settings; } @Override @@ -582,4 +580,5 @@ public class MFTerminal extends AbstractMFAppCLI<MFTerminal.Settings> { } } + } diff --git a/src/main/java/unimelb/mf/client/util/AssetUtils.java b/src/main/java/unimelb/mf/client/util/AssetUtils.java index b8bce1a02d9ceb84772b87254407b6aa3e1515af..8fb9887e370552b57516a8c47e99ac81d94981ae 100644 --- a/src/main/java/unimelb/mf/client/util/AssetUtils.java +++ b/src/main/java/unimelb/mf/client/util/AssetUtils.java @@ -123,4 +123,10 @@ public class AssetUtils { } } + public static boolean assetExists(MFSession session, String assetId) throws Throwable { + XmlStringWriter w = new XmlStringWriter(); + w.add("id", assetId); + return session.execute("asset.exists", w.document()).booleanValue("exists"); + } + } diff --git a/src/main/java/unimelb/mf/client/util/LoggingUtils.java b/src/main/java/unimelb/mf/client/util/LoggingUtils.java index c158840ca40dc8e217729ebfb44d93d7457f1880..cf385c0dbc881c1a7c8ebe7b29341415b6880d2e 100644 --- a/src/main/java/unimelb/mf/client/util/LoggingUtils.java +++ b/src/main/java/unimelb/mf/client/util/LoggingUtils.java @@ -25,7 +25,7 @@ public class LoggingUtils { public static FileHandler createFileHandler(Path dir, String name, int logFileSizeLimit, int logFileCount, Level level, Formatter formatter) throws Throwable { - String logFileNamePattern = dir.toString() + File.separatorChar + name + "." + "%g.log"; + String logFileNamePattern = dir.toString() + File.separatorChar + name + "." + "%u.%g.log"; FileHandler fileHandler = new FileHandler(logFileNamePattern, logFileSizeLimit, logFileCount, true); if (formatter != null) { fileHandler.setFormatter(formatter); diff --git a/src/main/scripts/unix/aterm b/src/main/scripts/unix/aterm index c25e59b5a82f63341a473d410de329309417fed7..963c88ceed95e695422b7b4ab174651f8db15654 100755 --- a/src/main/scripts/unix/aterm +++ b/src/main/scripts/unix/aterm @@ -1,7 +1,7 @@ #!/bin/bash # where to download aterm.jar? -ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar # where to save aterm.jar? ATERM_HOME=$HOME/.Arcitecta diff --git a/src/main/scripts/unix/aterm-download b/src/main/scripts/unix/aterm-download index 97334b8dbf1d0612ba17de955d7b51c4e17b5ef0..13d2a7d5688d8964abb41cf3e539778cc2a051ac 100755 --- a/src/main/scripts/unix/aterm-download +++ b/src/main/scripts/unix/aterm-download @@ -1,7 +1,7 @@ #!/bin/bash # where to download aterm.jar? -ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar # where to save aterm.jar? ATERM_HOME=$HOME/.Arcitecta diff --git a/src/main/scripts/unix/aterm-gui b/src/main/scripts/unix/aterm-gui index dd9b3f67caee2db6761d7ca751651dba8e7516ac..9bb64dd79ac1869029535e007c41d61ba6d6afde 100644 --- a/src/main/scripts/unix/aterm-gui +++ b/src/main/scripts/unix/aterm-gui @@ -1,7 +1,7 @@ #!/bin/bash # where to download aterm.jar? -ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar # where to save aterm.jar? ATERM_HOME=$HOME/.Arcitecta diff --git a/src/main/scripts/unix/aterm-import b/src/main/scripts/unix/aterm-import index fb0ea56d6848ab6dec369470307e2c332fe5c804..2ab07ebc3b455326e58733d13eb721e675c2fee6 100755 --- a/src/main/scripts/unix/aterm-import +++ b/src/main/scripts/unix/aterm-import @@ -1,7 +1,7 @@ #!/bin/bash # where to download aterm.jar? -ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar # where to save aterm.jar? ATERM_HOME=$HOME/.Arcitecta diff --git a/src/main/scripts/unix/mexplorer b/src/main/scripts/unix/mexplorer index 572efd433363959164b9c2934a1a3dfcf9d063d2..3aeb939ee73d3d84ddf74c29da4aaeda17f7fa97 100644 --- a/src/main/scripts/unix/mexplorer +++ b/src/main/scripts/unix/mexplorer @@ -1,23 +1,29 @@ #!/bin/bash - -# check if java exists -[[ -z $(which java) ]] && echo "Error: cannot find java." 1>&2 && exit 1 +# ${ROOT}/bin/ +BIN=$(dirname ${BASH_SOURCE[0]}) + +# current directory CWD=$(pwd) -BIN=$(dirname ${BASH_SOURCE[0]}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) -LIB=$(cd ${BIN}/../../lib && pwd) +# ${ROOT}/lib/ +LIB=${ROOT}/lib -cd $LIB +# ${ROOT}/lib/mexplorer.jar +JAR=${LIB}/mexplorer.jar -for f in $(ls -d mexplorer-*.jar) -do - JAR=$f -done +# check if mexplorer.jar exists +[[ ! -f $JAR ]] && echo "Error: cannot find ${JAR}." >&2 && exit 2 -[[ -z ${JAR} ]] && echo "Error: cannot find mexplorer-*.jar in ${LIB}" && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Error: cannot find java." 1>&2 && exit 1 -cd $CWD +# +java -Xmx1024m -jar ${JAR} -java -jar ${LIB}/${JAR} \ No newline at end of file diff --git a/src/main/scripts/unix/scp-get b/src/main/scripts/unix/scp-get index 33547ad627ccaaf05ea19e7a30ffd6fb6eb2fe6c..d9a3d184ce0ffbd4996839906163a2f18f93cc8b 100644 --- a/src/main/scripts/unix/scp-get +++ b/src/main/scripts/unix/scp-get @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.ssh.cli.SCPGetCLI ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.ssh.cli.SCPGetCLI ${1+"$@"} diff --git a/src/main/scripts/unix/scp-put b/src/main/scripts/unix/scp-put index 1fe8e4ba6c6617ca57791dde9aa79f5948fe7c01..b891b369331126d3a236cec6134b044fcd865864 100644 --- a/src/main/scripts/unix/scp-put +++ b/src/main/scripts/unix/scp-put @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.ssh.cli.SCPPutCLI ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.ssh.cli.SCPPutCLI ${1+"$@"} diff --git a/src/main/scripts/unix/sftp-get b/src/main/scripts/unix/sftp-get index ef71fdbb268b91d542ef8d2e08d7b8d818c56760..c2417711697d4cb9954d31e194982daa2828df47 100644 --- a/src/main/scripts/unix/sftp-get +++ b/src/main/scripts/unix/sftp-get @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.ssh.cli.SFTPGetCLI ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.ssh.cli.SFTPGetCLI ${1+"$@"} diff --git a/src/main/scripts/unix/sftp-put b/src/main/scripts/unix/sftp-put index d842bf2888c64d496b8c9d4237b13aaf03c1cca0..d9bf51bc74348c6e5f7c392d8a92cf851037af80 100644 --- a/src/main/scripts/unix/sftp-put +++ b/src/main/scripts/unix/sftp-put @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.ssh.cli.SFTPPutCLI ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.ssh.cli.SFTPPutCLI ${1+"$@"} diff --git a/src/main/scripts/unix/unimelb-mf-archive b/src/main/scripts/unix/unimelb-mf-archive index 7271637fba36dc9929461090a4eac3011b004368..32abc05885f6692f6e6234ec00a355c14bc57199 100644 --- a/src/main/scripts/unix/unimelb-mf-archive +++ b/src/main/scripts/unix/unimelb-mf-archive @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.archive.cli.MFArchiveCLI ${1+"$@"} \ No newline at end of file +java -Xmx200m -cp "${JAR}" unimelb.mf.client.archive.cli.MFArchiveCLI ${1+"$@"} \ No newline at end of file diff --git a/src/main/scripts/unix/unimelb-mf-check b/src/main/scripts/unix/unimelb-mf-check index 88c4ec998f0ce74d76447a0977d2519da85926a7..a72dca3c5d9541ce4850150a50a9d2bfe3d25e3b 100644 --- a/src/main/scripts/unix/unimelb-mf-check +++ b/src/main/scripts/unix/unimelb-mf-check @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.sync.cli.MFCheck ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.sync.cli.MFCheck ${1+"$@"} diff --git a/src/main/scripts/unix/unimelb-mf-download b/src/main/scripts/unix/unimelb-mf-download index a8e053ea4aa3373cfa5fb01706a2e712c9f3e108..6be8beb9c0b9864e856c6533d1affc236376b520 100644 --- a/src/main/scripts/unix/unimelb-mf-download +++ b/src/main/scripts/unix/unimelb-mf-download @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.sync.cli.MFDownload ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.sync.cli.MFDownload ${1+"$@"} diff --git a/src/main/scripts/unix/unimelb-mf-perf b/src/main/scripts/unix/unimelb-mf-perf new file mode 100644 index 0000000000000000000000000000000000000000..bb4c41a0e0618749fb498d94370c37128dbeb74c --- /dev/null +++ b/src/main/scripts/unix/unimelb-mf-perf @@ -0,0 +1,28 @@ +#!/bin/bash + +# ${ROOT}/bin/ +BIN=$(dirname ${BASH_SOURCE[0]}) + +# current directory +CWD=$(pwd) + +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib + +# ${ROOT}/lib/unimelb-mf-clients.jar +JAR=${LIB}/unimelb-mf-clients.jar + +# check if unimelb-mf-clients.jar exists +[[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 + +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + +# execute the command +java -Xmx200m -cp "${JAR}" unimelb.mf.client.perf.cli.MFPerfCLI ${1+"$@"} \ No newline at end of file diff --git a/src/main/scripts/unix/unimelb-mf-sync b/src/main/scripts/unix/unimelb-mf-sync index 00f60290c7a57128b2fb2f777fccd964d4fa19e4..4913a1478ab87450f034c8d726b3227f44c0de24 100644 --- a/src/main/scripts/unix/unimelb-mf-sync +++ b/src/main/scripts/unix/unimelb-mf-sync @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.sync.cli.MFSync ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.sync.cli.MFSync ${1+"$@"} diff --git a/src/main/scripts/unix/unimelb-mf-upload b/src/main/scripts/unix/unimelb-mf-upload index bd097ef72cf065349cbbd7d112ba2d8b6736491a..b82ac386214c41ac0db619ed74a8d96b5f871ad2 100644 --- a/src/main/scripts/unix/unimelb-mf-upload +++ b/src/main/scripts/unix/unimelb-mf-upload @@ -1,22 +1,28 @@ #!/bin/bash -# check if java exists -[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 - -# unimelb-mf-clients/bin +# ${ROOT}/bin/ BIN=$(dirname ${BASH_SOURCE[0]}) # current directory CWD=$(pwd) -# unimelb-mf-clients/lib -LIB=$(cd ${BIN}/../../lib && pwd && cd ${CWD}) +# ${ROOT}/ +ROOT=$(cd ${BIN}/../../ && pwd && cd ${CWD}) + +# ${ROOT}/lib/ +LIB=${ROOT}/lib -# unimelb-mf-clients/lib/unimelb-mf-clients.jar +# ${ROOT}/lib/unimelb-mf-clients.jar JAR=${LIB}/unimelb-mf-clients.jar # check if unimelb-mf-clients.jar exists [[ ! -f $JAR ]] && echo "${JAR} is not found." >&2 && exit 2 +#export JAVA_HOME=${ROOT}/@JAVA_HOME@ +#export PATH=${JAVA_HOME}/bin:${PATH} + +# check if java exists +[[ -z $(which java) ]] && echo "Java is not found." >&2 && exit 1 + # execute the command -java -cp "${JAR}" unimelb.mf.client.sync.cli.MFUpload ${1+"$@"} +java -Xmx200m -cp "${JAR}" unimelb.mf.client.sync.cli.MFUpload ${1+"$@"} diff --git a/src/main/scripts/windows/aterm-download.cmd b/src/main/scripts/windows/aterm-download.cmd index 107c92767a0b45dacfc3fcbe2722218405ad1c9f..412163040c8fdc5f5ac26f17bc28067bff2073cb 100644 --- a/src/main/scripts/windows/aterm-download.cmd +++ b/src/main/scripts/windows/aterm-download.cmd @@ -1,7 +1,7 @@ @echo off REM where to download aterm.jar -SET ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +SET ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM where to save aterm.jar SET ATERM_HOME=%USERPROFILE%\.Arcitecta diff --git a/src/main/scripts/windows/aterm-gui.cmd b/src/main/scripts/windows/aterm-gui.cmd index e4e726bb3801bf000d1bea45f027bd32c1ac83a8..3bac8eccc2d815162bb63cb4767c52cda96f627b 100644 --- a/src/main/scripts/windows/aterm-gui.cmd +++ b/src/main/scripts/windows/aterm-gui.cmd @@ -1,7 +1,7 @@ @echo off REM where to download aterm.jar -SET ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +SET ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM where to save aterm.jar SET ATERM_HOME=%USERPROFILE%\.Arcitecta diff --git a/src/main/scripts/windows/aterm-import.cmd b/src/main/scripts/windows/aterm-import.cmd index f578603660f91e0a76fb6ab91078c9b946aa3c13..8eec6432ba14596e41e93dc03ecf9d6da820cda6 100644 --- a/src/main/scripts/windows/aterm-import.cmd +++ b/src/main/scripts/windows/aterm-import.cmd @@ -2,7 +2,7 @@ REM where to download aterm.jar -SET ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +SET ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM where to save aterm.jar SET ATERM_HOME=%USERPROFILE%\.Arcitecta diff --git a/src/main/scripts/windows/aterm.cmd b/src/main/scripts/windows/aterm.cmd index 06f66de4ec999feefdc2db1272b9db4618ba6380..794790bdda52f51b52bd55513fa79bef48107c08 100644 --- a/src/main/scripts/windows/aterm.cmd +++ b/src/main/scripts/windows/aterm.cmd @@ -1,7 +1,7 @@ @echo off REM where to download aterm.jar -SET ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +SET ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM where to save aterm.jar SET ATERM_HOME=%USERPROFILE%\.Arcitecta diff --git a/src/main/scripts/windows/cryo-em/cryoem-download-aterm-script-url-create.cmd b/src/main/scripts/windows/cryo-em/cryoem-download-aterm-script-url-create.cmd index 49abea14bee33cb16e92afac7ba127eb8f2997fa..2439557727987cb06a841832c6222d496f12db9d 100644 --- a/src/main/scripts/windows/cryo-em/cryoem-download-aterm-script-url-create.cmd +++ b/src/main/scripts/windows/cryo-em/cryoem-download-aterm-script-url-create.cmd @@ -12,7 +12,7 @@ REM script file name set PROG=%~0 REM aterm.jar download url -set ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +set ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM aterm.jar location if [%MFLUX_ATERM%]==[] set "MFLUX_ATERM=%~dp0..\..\..\lib\aterm.jar" diff --git a/src/main/scripts/windows/cryo-em/cryoem-download-shell-script-url-create.cmd b/src/main/scripts/windows/cryo-em/cryoem-download-shell-script-url-create.cmd index f1e1b35a6b267752adfc037c68634ff2e0b88802..7f7093adc99f3325c598f054522851afbcdf7180 100644 --- a/src/main/scripts/windows/cryo-em/cryoem-download-shell-script-url-create.cmd +++ b/src/main/scripts/windows/cryo-em/cryoem-download-shell-script-url-create.cmd @@ -12,7 +12,7 @@ REM script file name set PROG=%~0 REM aterm.jar download url -set ATERM_URL=https://mediaflux.vicnode.org.au/mflux/aterm.jar +set ATERM_URL=https://mediaflux.researchsoftware.unimelb.edu.au/mflux/aterm.jar REM aterm.jar location if [%MFLUX_ATERM%]==[] set "MFLUX_ATERM=%~dp0..\..\..\lib\aterm.jar" diff --git a/src/main/scripts/windows/mexplorer.cmd b/src/main/scripts/windows/mexplorer.cmd index db3c8241d58898477f86a2abbd4db2614f422eca..7cd5bca06d63a279581ade921103a24fd55297fa 100644 --- a/src/main/scripts/windows/mexplorer.cmd +++ b/src/main/scripts/windows/mexplorer.cmd @@ -1,9 +1,12 @@ @echo off -pushd %~dp0..\..\lib -set LIB=%cd% -for %%# in ("mexplorer-*.jar") do ( - set JAR=%%~# -) +pushd %~dp0..\..\ +set ROOT=%cd% popd -java -jar %LIB%\%JAR% %* + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\mexplorer.jar + +java -Xmx1024m -jar %JAR% %* diff --git a/src/main/scripts/windows/scp-get.cmd b/src/main/scripts/windows/scp-get.cmd index ee1f548995cd5a68b2f7856ee4357a38b0ddd480..f7ea2284ec70226524951dc9f86e7856b83c5b2a 100644 --- a/src/main/scripts/windows/scp-get.cmd +++ b/src/main/scripts/windows/scp-get.cmd @@ -1,5 +1,14 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.ssh.cli.SCPGetCLI %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.ssh.cli.SCPGetCLI %* diff --git a/src/main/scripts/windows/scp-put.cmd b/src/main/scripts/windows/scp-put.cmd index 1eb56cfd73fe358cb11bbec1c110273a5696ef75..123edff4ec33bc70ad055c4fd26f46152cfbcc64 100644 --- a/src/main/scripts/windows/scp-put.cmd +++ b/src/main/scripts/windows/scp-put.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.ssh.cli.SCPPutCLI %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.ssh.cli.SCPPutCLI %* diff --git a/src/main/scripts/windows/sftp-get.cmd b/src/main/scripts/windows/sftp-get.cmd index 34b615bc9021373a2192638a4cccaea1a2fa3914..fd9b3aa26a215065ccb453894b2f79545185cef3 100644 --- a/src/main/scripts/windows/sftp-get.cmd +++ b/src/main/scripts/windows/sftp-get.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.ssh.cli.SFTPGetCLI %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.ssh.cli.SFTPGetCLI %* diff --git a/src/main/scripts/windows/sftp-put.cmd b/src/main/scripts/windows/sftp-put.cmd index a2d31df078c1138b5f74973663f2d3cd70f89845..614aabe0ef3573df561a9a7599dc4cd0f4f762b0 100644 --- a/src/main/scripts/windows/sftp-put.cmd +++ b/src/main/scripts/windows/sftp-put.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.ssh.cli.SFTPPutCLI %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.ssh.cli.SFTPPutCLI %* diff --git a/src/main/scripts/windows/unimelb-mf-archive.cmd b/src/main/scripts/windows/unimelb-mf-archive.cmd index 50c86653c228b1c67974733ccdc8433d4cb29a36..e898767abc2af0b0a5012515b9fb25cad012d53e 100644 --- a/src/main/scripts/windows/unimelb-mf-archive.cmd +++ b/src/main/scripts/windows/unimelb-mf-archive.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.archive.cli.MFArchiveCLI %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.archive.cli.MFArchiveCLI %* diff --git a/src/main/scripts/windows/unimelb-mf-check.cmd b/src/main/scripts/windows/unimelb-mf-check.cmd index e3d5a8a9fe7ac583e9b8af379eb17fbd1f14b29b..7956a1d6134cd75cc7ec89659c23ab5bb5c2b062 100644 --- a/src/main/scripts/windows/unimelb-mf-check.cmd +++ b/src/main/scripts/windows/unimelb-mf-check.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.sync.cli.MFCheck %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.sync.cli.MFCheck %* diff --git a/src/main/scripts/windows/unimelb-mf-download.cmd b/src/main/scripts/windows/unimelb-mf-download.cmd index ba23f927f1f5625abb56d980823c48556e09077e..bce97c26f12b50a4cf03f15f4c9f67d0fef3fa23 100644 --- a/src/main/scripts/windows/unimelb-mf-download.cmd +++ b/src/main/scripts/windows/unimelb-mf-download.cmd @@ -1,3 +1,11 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.sync.cli.MFDownload %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar +java -Xmx200m -cp %JAR% unimelb.mf.client.sync.cli.MFDownload %* diff --git a/src/main/scripts/windows/unimelb-mf-perf.cmd b/src/main/scripts/windows/unimelb-mf-perf.cmd new file mode 100644 index 0000000000000000000000000000000000000000..db817c8cfd4b22323174eeeaeb1182d70f323e3f --- /dev/null +++ b/src/main/scripts/windows/unimelb-mf-perf.cmd @@ -0,0 +1,11 @@ +@echo off + +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar +java -Xmx200m -cp %JAR% unimelb.mf.client.perf.cli.MFPerfCLI %* \ No newline at end of file diff --git a/src/main/scripts/windows/unimelb-mf-sync.cmd b/src/main/scripts/windows/unimelb-mf-sync.cmd index 9cd21a5b30d593c55dfff2e081c2eb22ebd8520e..fee85fc389fce8c3a0900b75112f9dfc87c7955d 100644 --- a/src/main/scripts/windows/unimelb-mf-sync.cmd +++ b/src/main/scripts/windows/unimelb-mf-sync.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.sync.cli.MFSync %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.sync.cli.MFSync %* diff --git a/src/main/scripts/windows/unimelb-mf-upload.cmd b/src/main/scripts/windows/unimelb-mf-upload.cmd index 58267744af355f511de6511fbc0f1b181f082669..6271708149d63c8505fc516bb5843d2098c90393 100644 --- a/src/main/scripts/windows/unimelb-mf-upload.cmd +++ b/src/main/scripts/windows/unimelb-mf-upload.cmd @@ -1,3 +1,12 @@ @echo off -cmd /k java -cp "%~dp0..\..\lib\unimelb-mf-clients.jar" unimelb.mf.client.sync.cli.MFUpload %* +pushd %~dp0..\..\ +set ROOT=%cd% +popd + +@REM set JAVA_HOME=%ROOT%\@JAVA_HOME@ +@REM set PATH=%JAVA_HOME%\bin;%PATH% + +set JAR=%ROOT%\lib\unimelb-mf-clients.jar + +java -Xmx200m -cp %JAR% unimelb.mf.client.sync.cli.MFUpload %* diff --git a/src/test/java/unimelb/mf/client/AppTest.java b/src/test/java/unimelb/mf/client/AppTest.java deleted file mode 100644 index d88e7020a804937c1222a904a63d46a5de131158..0000000000000000000000000000000000000000 --- a/src/test/java/unimelb/mf/client/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package unimelb.mf.client; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -/** - * Unit test for simple App. - */ -public class AppTest - extends TestCase -{ - /** - * Create the test case - * - * @param testName name of the test case - */ - public AppTest( String testName ) - { - super( testName ); - } - - /** - * @return the suite of tests being tested - */ - public static Test suite() - { - return new TestSuite( AppTest.class ); - } - - /** - * Rigourous Test :-) - */ - public void testApp() - { - assertTrue( true ); - } -} diff --git a/src/test/java/unimelb/mf/client/SCPTest.java b/src/test/java/unimelb/mf/client/SCPTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e56078c2a04cdd3ffbbc9ee31cd2088bf4ce28a5 --- /dev/null +++ b/src/test/java/unimelb/mf/client/SCPTest.java @@ -0,0 +1,24 @@ +package unimelb.mf.client; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class SCPTest { + + @Before + public void setup() { + + } + + @Test + public void test() { + + } + + @After + public void cleanup() { + + } + +} diff --git a/src/test/java/unimelb/mf/client/TestUtils.java b/src/test/java/unimelb/mf/client/TestUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..8ec38e1d369fa184d4599abcd89984e501da5d44 --- /dev/null +++ b/src/test/java/unimelb/mf/client/TestUtils.java @@ -0,0 +1,41 @@ +package unimelb.mf.client; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +public class TestUtils { + + public static final String PROPERTIES_FILE = System.getProperty("user.home") + + "/.junit/unimelb-mf-clients-ssh-test.properties"; + + public static final String MFLUX_CONFIG_FILE = System.getProperty("user.home") + "/.Arcitecta/mflux.cfg.local"; + + public static final Properties properties = new Properties(); + + static { + try { + Reader r = new BufferedReader(new FileReader(new File(PROPERTIES_FILE))); + try { + properties.load(r); + } finally { + r.close(); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public static final List<String> putArgs = new ArrayList<String>(); + + public static final List<String> getArgs = new ArrayList<String>(); + + static { + + } + +}