-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from fizzed/feature/windows-processes
dFeature/windows processes
- Loading branch information
Showing
20 changed files
with
581 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: MacOS arm64 | ||
|
||
on: | ||
push | ||
|
||
jobs: | ||
build: | ||
runs-on: macos-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Set up Azul JDK 11 | ||
uses: actions/setup-java@v3 | ||
with: | ||
java-version: 11 | ||
distribution: 'zulu' | ||
cache: 'maven' | ||
- name: Test in Maven | ||
run: mvn test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ blaze-lite/dependency-reduced-pom.xml | |
ssh/src/test/java/ssh.* | ||
*.iml | ||
examples/pom.xml | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
blaze-core/src/main/java/com/fizzed/blaze/util/ProcessHandleReflected.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package com.fizzed.blaze.util; | ||
|
||
import java.lang.reflect.Method; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* Uses reflection to allow for Java 8 compiled source to leverage Java 9+ process API. | ||
*/ | ||
public class ProcessHandleReflected { | ||
|
||
// reflected methods we'll store for faster access | ||
static private volatile boolean attempted = false; | ||
static private final Object lock = new Object(); | ||
static private Class<?> processHandleClass = null; | ||
static private Method processClassToHandleMethod; | ||
static private Method processHandleClassCurrentMethod; | ||
static private Method processHandleClassPidMethod; | ||
static private Method processHandleClassIsAliveMethod; | ||
static private Method processHandleClassDestroyMethod; | ||
static private Method processHandleClassDestroyForciblyMethod; | ||
static private Method processHandleClassDescendantsMethod; | ||
|
||
static public boolean isAvailable() { | ||
if (!attempted) { | ||
synchronized (lock) { | ||
if (!attempted) { | ||
try { | ||
processHandleClass = Class.forName("java.lang.ProcessHandle"); | ||
processClassToHandleMethod = Process.class.getMethod("toHandle"); | ||
processHandleClassCurrentMethod = processHandleClass.getMethod("current"); | ||
processHandleClassPidMethod = processHandleClass.getMethod("pid"); | ||
processHandleClassIsAliveMethod = processHandleClass.getMethod("isAlive"); | ||
processHandleClassDestroyMethod = processHandleClass.getMethod("destroy"); | ||
processHandleClassDestroyForciblyMethod = processHandleClass.getMethod("destroyForcibly"); | ||
processHandleClassDescendantsMethod = processHandleClass.getMethod("descendants"); | ||
} catch (Exception e) { | ||
processHandleClass = null; | ||
} | ||
attempted = true; | ||
} | ||
} | ||
} | ||
return processHandleClass != null; | ||
} | ||
|
||
private final Object instance; | ||
|
||
static public ProcessHandleReflected from(Process process) { | ||
if (!isAvailable()) { | ||
throw new UnsupportedOperationException("Process API is not available on this JVM (are you running Java 9+ ?)"); | ||
} | ||
|
||
try { | ||
final Object handle = processClassToHandleMethod.invoke(process); | ||
|
||
return new ProcessHandleReflected(handle); | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new UnsupportedOperationException(e); | ||
} | ||
} | ||
|
||
static public ProcessHandleReflected current() { | ||
if (!isAvailable()) { | ||
throw new UnsupportedOperationException("Process API is not available on this JVM (are you running Java 9+ ?)"); | ||
} | ||
|
||
try { | ||
final Object handle = processHandleClassCurrentMethod.invoke(null); | ||
|
||
return new ProcessHandleReflected(handle); | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new UnsupportedOperationException(e); | ||
} | ||
} | ||
|
||
public ProcessHandleReflected(Object instance) { | ||
this.instance = instance; | ||
} | ||
|
||
public long pid() { | ||
try { | ||
final Object value = processHandleClassPidMethod.invoke(this.instance); | ||
|
||
return (long) value; | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public boolean isAlive() { | ||
try { | ||
final Object value = processHandleClassIsAliveMethod.invoke(this.instance); | ||
|
||
return (boolean) value; | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public boolean destroy() { | ||
try { | ||
final Object value = processHandleClassDestroyMethod.invoke(this.instance); | ||
|
||
return (boolean) value; | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public boolean destroyForcibly() { | ||
try { | ||
final Object value = processHandleClassDestroyForciblyMethod.invoke(this.instance); | ||
|
||
return (boolean) value; | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
public List<ProcessHandleReflected> descendants() { | ||
try { | ||
final Stream<?> valueStream = (Stream<?>)processHandleClassDescendantsMethod.invoke(this.instance); | ||
|
||
return valueStream.map(ProcessHandleReflected::new).collect(Collectors.toList()); | ||
} catch (ReflectiveOperationException | SecurityException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
blaze-core/src/main/java/com/fizzed/blaze/util/ProcessHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.fizzed.blaze.util; | ||
|
||
public interface ProcessHelper { | ||
|
||
void destroy(Process process, long normalTerminationTimeoutMillis) throws InterruptedException; | ||
|
||
void destroyWithDescendants(Process process, long normalTerminationTimeoutMillis) throws InterruptedException; | ||
|
||
static ProcessHelper get() { | ||
if (ProcessHelper9.isAvailable()) { | ||
return new ProcessHelper9(); | ||
} else { | ||
return new ProcessHelper8(); | ||
} | ||
} | ||
|
||
} |
30 changes: 30 additions & 0 deletions
30
blaze-core/src/main/java/com/fizzed/blaze/util/ProcessHelper8.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.fizzed.blaze.util; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class ProcessHelper8 implements ProcessHelper { | ||
static private final Logger log = LoggerFactory.getLogger(ProcessHelper8.class); | ||
|
||
@Override | ||
public void destroy(Process process, long normalTerminationTimeoutMillis) throws InterruptedException { | ||
if (process.isAlive()) { | ||
log.debug("Destroying/killing process w/ normal termination {} (will wait {} ms)", process, normalTerminationTimeoutMillis); | ||
// try to destroy process normally, then wait till timeout | ||
process.destroy(); | ||
boolean killed = new WaitFor(() -> !process.isAlive()).await(normalTerminationTimeoutMillis, 100L); | ||
if (!killed) { | ||
log.debug("Normal termination timed out. Destroying/killing process {} forcibly", process); | ||
process.destroyForcibly(); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void destroyWithDescendants(Process process, long normalTerminationTimeoutMillis) throws InterruptedException { | ||
// this is not supported on java 8, so we'll only do the main process | ||
log.debug("Destroying processes with descendants is only supported on Java 9+ (so we will only destroy parent process instead)"); | ||
this.destroy(process, normalTerminationTimeoutMillis); | ||
} | ||
|
||
} |
Oops, something went wrong.