Add setCommands method to Shell.Builder

This commit is contained in:
vvb2060 2023-12-18 05:18:58 +08:00 committed by John Wu
parent 30da926945
commit 01570d643a
3 changed files with 48 additions and 20 deletions

View File

@ -405,6 +405,15 @@ public abstract class Shell implements Closeable {
@NonNull
public abstract Builder setTimeout(long timeout);
/**
* Set the commands that will be used to create a new {@code Shell}.
* @param commands commands that will be passed to {@link Runtime#exec(String[])} to create
* a new {@link Process}.
* @return this Builder object for chaining of calls.
*/
@NonNull
public abstract Builder setCommands(String... commands);
/**
* Set the {@link Context} to use when creating a shell.
* <p>
@ -426,11 +435,10 @@ public abstract class Shell implements Closeable {
}
/**
* Combine all of the options that have been set and build a new {@code Shell} instance
* with the default methods.
* Combine all of the options that have been set and build a new {@code Shell} instance.
* <p>
* There are 3 methods to construct a Unix shell; if any method fails, it will fallback to
* the next method:
* If not {@link #setCommands(String...)}, there are 3 methods to construct a Unix shell;
* if any method fails, it will fallback to the next method:
* <ol>
* <li>If {@link #FLAG_NON_ROOT_SHELL} is not set and {@link #FLAG_MOUNT_MASTER}
* is set, construct a Unix shell by calling {@code su --mount-master}.
@ -442,7 +450,11 @@ public abstract class Shell implements Closeable {
* conditions, but should it fail, it will throw {@link NoShellException}</li>
* </ol>
* The developer should check the status of the returned {@code Shell} with
* {@link #getStatus()} since it may be constructed with any of the 3 possible methods.
* {@link #getStatus()} since it may be constructed with calling {@code sh}.
* <p>
* If {@link #setCommands(String...)} is called, the provided commands will be used to
* create a new {@link Process} directly. If the process fails to create, or the process
* is not a valid shell, it will throw {@link NoShellException}.
* @return the created {@code Shell} instance.
* @throws NoShellException impossible to construct a {@link Shell} instance, or
* initialization failed when using the configured {@link Initializer}s.
@ -460,7 +472,9 @@ public abstract class Shell implements Closeable {
* initialization failed when using the configured {@link Initializer}s.
*/
@NonNull
public abstract Shell build(String... commands);
public final Shell build(String... commands) {
return setCommands(commands).build();
}
/**
* Combine all of the options that have been set and build a new {@code Shell} instance

View File

@ -38,6 +38,7 @@ public final class BuilderImpl extends Shell.Builder {
long timeout = 20;
private int flags = 0;
private Shell.Initializer[] initializers;
private String[] command;
boolean hasFlags(int mask) {
return (flags & mask) == mask;
@ -57,6 +58,13 @@ public final class BuilderImpl extends Shell.Builder {
return this;
}
@NonNull
@Override
public Shell.Builder setCommands(String... c) {
command = c;
return this;
}
public void setInitializersImpl(Class<? extends Shell.Initializer>[] clz) {
initializers = new Shell.Initializer[clz.length];
for (int i = 0; i < clz.length; ++i) {
@ -70,15 +78,13 @@ public final class BuilderImpl extends Shell.Builder {
}
}
@NonNull
@Override
public ShellImpl build() {
ShellImpl shell = null;
private Shell start() {
Shell shell = null;
// Root mount master
if (!hasFlags(FLAG_NON_ROOT_SHELL) && hasFlags(FLAG_MOUNT_MASTER)) {
try {
shell = build("su", "--mount-master");
shell = exec("su", "--mount-master");
if (!shell.isRoot())
shell = null;
} catch (NoShellException ignore) {}
@ -87,7 +93,7 @@ public final class BuilderImpl extends Shell.Builder {
// Normal root shell
if (shell == null && !hasFlags(FLAG_NON_ROOT_SHELL)) {
try {
shell = build("su");
shell = exec("su");
if (!shell.isRoot()) {
shell = null;
}
@ -99,15 +105,13 @@ public final class BuilderImpl extends Shell.Builder {
if (!hasFlags(FLAG_NON_ROOT_SHELL)) {
Utils.setConfirmedRootState(false);
}
shell = build("sh");
shell = exec("sh");
}
return shell;
}
@NonNull
@Override
public ShellImpl build(String... commands) {
private Shell exec(String... commands) {
try {
Utils.log(TAG, "exec " + TextUtils.join(" ", commands));
Process process = Runtime.getRuntime().exec(commands);
@ -120,7 +124,7 @@ public final class BuilderImpl extends Shell.Builder {
@NonNull
@Override
public ShellImpl build(Process process) {
public Shell build(Process process) {
ShellImpl shell;
try {
shell = new ShellImpl(this, process);
@ -140,4 +144,14 @@ public final class BuilderImpl extends Shell.Builder {
}
return shell;
}
@NonNull
@Override
public Shell build() {
if (command != null) {
return exec(command);
} else {
return start();
}
}
}

View File

@ -41,8 +41,8 @@ public final class MainShell {
private MainShell() {}
public static synchronized ShellImpl get() {
ShellImpl shell = getCached();
public static synchronized Shell get() {
Shell shell = getCached();
if (shell == null) {
isInitMain = true;
if (mainBuilder == null)
@ -76,7 +76,7 @@ public final class MainShell {
}
}
public static ShellImpl getCached() {
public static Shell getCached() {
synchronized (mainShell) {
ShellImpl s = mainShell[0];
if (s != null && s.getStatus() < 0)