xapi.shell.impl.ShellServiceDefault Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-dev Show documentation
Show all versions of xapi-dev Show documentation
Everything needed to run a comprehensive dev environment.
Just type X_ and pick a service from autocomplete;
new dev modules will be added as they are built.
The only dev service not included in the uber jar is xapi-dev-maven,
as it includes all runtime dependencies of maven, adding ~4 seconds to build time,
and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).
The newest version!
package xapi.shell.impl;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import xapi.annotation.inject.InstanceDefault;
import xapi.annotation.inject.SingletonDefault;
import xapi.file.X_File;
import xapi.inject.X_Inject;
import xapi.io.api.LineReader;
import xapi.log.X_Log;
import xapi.shell.api.ShellCommand;
import xapi.shell.api.ShellSession;
import xapi.shell.service.ShellService;
import xapi.time.X_Time;
import xapi.time.api.Moment;
import xapi.util.X_GC;
import xapi.util.api.SuccessHandler;
@InstanceDefault(implFor = ShellService.class)
@SingletonDefault(implFor = ShellService.class)
public class ShellServiceDefault implements ShellService {
public ShellServiceDefault() {
}
@Override
public ShellCommand newCommand(String ... cmds) {
return X_Inject.instance(ShellCommand.class).commands(cmds);
}
static {
new Thread() {
{
Runtime.getRuntime().addShutdownHook(this);
}
public void run() {
while(!runningShells.isEmpty()){
runningShells.remove().destroy();
}
}
};
}
private static final Queue runningShells = new ConcurrentLinkedQueue<>();
// private static abstract class ScriptProvider extends SingletonProvider {
// abstract String getScriptName();
// public String getScriptLocation() {
// return X_File.getResourceMaybeUnzip(getScriptName(), Thread.currentThread().getContextClassLoader());
// }
// }
@Override
public ShellSession runInShell(final boolean keepAlive, LineReader stdOut, LineReader stdErr, final String ... cmds) {
final Moment start = X_Time.now();
final String[] commands;
if (keepAlive) {
final String sh = X_File.unzippedResourcePath("xapi/sh.sh", null);
commands = new String[]{"sh", "-ac", sh};
} else {
commands = cmds;
}
final ShellSession runningShell =
X_Inject.instance(ShellCommand.class)
.commands(commands)
.run(new SuccessHandler() {
@Override
public void onSuccess(ShellSession t) {
X_Log.trace(getClass(), "Shell still running?", t.isRunning());
}
}, null);
X_Log.debug(getClass(), "Time create shell command", X_Time.difference(start));
if (stdOut != null) {
runningShell.stdOut(stdOut);
}
if (stdErr != null) {
runningShell.stdErr(stdErr);
}
X_Time.runLater(new Runnable() {
@Override
public void run() {
if (keepAlive) {
for (String cmd : cmds) {
runningShell.stdIn(cmd);
}
}
X_Log.debug(getClass(), "Time to send shell command", X_Time.difference(start));
// release thread
X_Time.trySleep(0, 1000);
// periodically clean up trash object
runCleanup();
}
});
return runningShell;
}
protected void runCleanup() {
for (
Iterator iter = runningShells.iterator();
iter.hasNext(); ) {
ShellSession next = iter.next();
if (!next.isRunning()) {
X_Log.trace(getClass(), "Recycle shell that is no longer running", next);
X_GC.destroy(ShellSession.class, next);
iter.remove();
}
}
}
}