aboutsummaryrefslogtreecommitdiff
path: root/libraries/common-0
diff options
context:
space:
mode:
authorChristopher Vogt <oss.nsp@cvogt.org>2017-03-20 22:09:38 -0400
committerChristopher Vogt <oss.nsp@cvogt.org>2017-03-27 19:56:13 -0400
commitbba2abe7ee38b8903822a07578c46466923d13ed (patch)
treea357fb8def6f58a9ea9a37411f3f5640dcb525fe /libraries/common-0
parentd2f8cade709b7d55a93e18592b6e38247d648ca9 (diff)
downloadcbt-bba2abe7ee38b8903822a07578c46466923d13ed.tar.gz
cbt-bba2abe7ee38b8903822a07578c46466923d13ed.tar.bz2
cbt-bba2abe7ee38b8903822a07578c46466923d13ed.zip
start modularizing cbt into libraries
this extracts certain parts of cbt into stand-alone libraries, which can be published to maven and used outside of cbt. This also adds scalariform for these parts of the code. This slows down cbt’s own build a lot because of the number of projects involved! So we’ll follow this by a bunch of performance tweak commits.
Diffstat (limited to 'libraries/common-0')
-rw-r--r--libraries/common-0/ProxySecurityManager.java130
-rw-r--r--libraries/common-0/TrapSecurityManager.java88
-rw-r--r--libraries/common-0/TrapSystemExit.java35
-rw-r--r--libraries/common-0/build/build.scala7
-rw-r--r--libraries/common-0/build/build/build.scala5
5 files changed, 265 insertions, 0 deletions
diff --git a/libraries/common-0/ProxySecurityManager.java b/libraries/common-0/ProxySecurityManager.java
new file mode 100644
index 0000000..4669add
--- /dev/null
+++ b/libraries/common-0/ProxySecurityManager.java
@@ -0,0 +1,130 @@
+package cbt.reflect;
+
+import java.security.*;
+import java.io.FileDescriptor;
+import java.net.InetAddress;
+
+/*
+SecurityManager proxy that forwards all calls to the provided target if != null.
+Useful to replace a previously installed SecurityManager, overriding some methods
+but forwarding the rest.
+*/
+class ProxySecurityManager extends SecurityManager {
+ private SecurityManager target;
+
+ protected ProxySecurityManager(SecurityManager target) {
+ this.target = target;
+ }
+
+ public Object getSecurityContext() {
+ if (target != null) return target.getSecurityContext();
+ else return super.getSecurityContext();
+ }
+
+ public void checkPermission(Permission perm) {
+ if (target != null) target.checkPermission(perm);
+ }
+
+ public void checkPermission(Permission perm, Object context) {
+ if (target != null) target.checkPermission(perm, context);
+ }
+
+ public void checkCreateClassLoader() {
+ if (target != null) target.checkCreateClassLoader();
+ }
+
+ public void checkAccess(Thread t) {
+ if (target != null) target.checkAccess(t);
+ }
+
+ public void checkAccess(ThreadGroup g) {
+ if (target != null) target.checkAccess(g);
+ }
+
+ public void checkExit(int status) {
+ if (target != null) target.checkExit(status);
+ }
+
+ public void checkExec(String cmd) {
+ if (target != null) target.checkExec(cmd);
+ }
+
+ public void checkLink(String lib) {
+ if (target != null) target.checkLink(lib);
+ }
+
+ /*
+ public void checkRead(FileDescriptor fd) {
+ if (target != null) target.checkRead(fd);
+ }
+
+ public void checkRead(String file) {
+ if (target != null) target.checkRead(file);
+ }
+
+ public void checkRead(String file, Object context) {
+ if (target != null) target.checkRead(file, context);
+ }
+ */
+
+ public void checkWrite(FileDescriptor fd) {
+ if (target != null) target.checkWrite(fd);
+ }
+
+ public void checkWrite(String file) {
+ if (target != null) target.checkWrite(file);
+ }
+
+ public void checkDelete(String file) {
+ if (target != null) target.checkDelete(file);
+ }
+
+ public void checkConnect(String host, int port) {
+ if (target != null) target.checkConnect(host, port);
+ }
+
+ public void checkConnect(String host, int port, Object context) {
+ if (target != null) target.checkConnect(host, port, context);
+ }
+
+ public void checkListen(int port) {
+ if (target != null) target.checkListen(port);
+ }
+
+ public void checkAccept(String host, int port) {
+ if (target != null) target.checkAccept(host, port);
+ }
+
+ public void checkMulticast(InetAddress maddr) {
+ if (target != null) target.checkMulticast(maddr);
+ }
+
+ public void checkPropertiesAccess() {
+ if (target != null) target.checkPropertiesAccess();
+ }
+
+ public void checkPropertyAccess(String key) {
+ if (target != null) target.checkPropertyAccess(key);
+ }
+
+ public void checkPrintJobAccess() {
+ if (target != null) target.checkPrintJobAccess();
+ }
+
+ public void checkPackageAccess(String pkg) {
+ if (target != null) target.checkPackageAccess(pkg);
+ }
+
+ public void checkPackageDefinition(String pkg) {
+ if (target != null) target.checkPackageDefinition(pkg);
+ }
+
+ public void checkSetFactory() {
+ if (target != null) target.checkSetFactory();
+ }
+
+ public ThreadGroup getThreadGroup() {
+ if (target != null) return target.getThreadGroup();
+ else return super.getThreadGroup();
+ }
+}
diff --git a/libraries/common-0/TrapSecurityManager.java b/libraries/common-0/TrapSecurityManager.java
new file mode 100644
index 0000000..161b74f
--- /dev/null
+++ b/libraries/common-0/TrapSecurityManager.java
@@ -0,0 +1,88 @@
+package cbt.reflect;
+
+import java.security.*;
+/*
+When enabled, this SecurityManager turns System.exit(...) calls into exceptions that can be caught and handled.
+Installing a SecurityManager is a global side-effect and thus needs extra care in a persistent
+background process like CBT's. The current approach is install it once during JVM-startup.
+When disabled this delegates to the SecurityManager installed before if any, which
+would be Nailgun's if running on Nailgun. If we do not delegate to Nailgun, it seems we
+could in some cases kill the server process
+*/
+public class TrapSecurityManager extends ProxySecurityManager {
+ public static ThreadLocal<Boolean> trapExitCode() {
+ // storing the flag in the installed security manager
+ // instead of e.g. a static member is necessary because
+ // we run multiple versions of CBT with multiple TrapSecurityManager classes
+ // but we need to affect the installed one
+ SecurityManager sm = System.getSecurityManager();
+ if (sm instanceof TrapSecurityManager) {
+ return ((TrapSecurityManager) sm)._trapExitCode;
+ } else {
+ try {
+ @SuppressWarnings("unchecked")
+ ThreadLocal<Boolean> res =
+ (ThreadLocal<Boolean>) sm.getClass().getMethod("trapExitCode").invoke(null);
+ return res;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private final ThreadLocal<Boolean> _trapExitCode =
+ new ThreadLocal<Boolean>() {
+ @Override
+ protected Boolean initialValue() {
+ return false;
+ }
+ };
+
+ protected TrapSecurityManager(SecurityManager parent) {
+ super(parent);
+ }
+
+ public void checkPermission(Permission permission) {
+ /*
+ NOTE: is it actually ok, to just make these empty?
+ Calling .super leads to ClassNotFound exteption for a lambda.
+ Calling to the previous SecurityManager leads to a stack overflow
+ */
+ if (!TrapSecurityManager.trapExitCode().get()) {
+ super.checkPermission(permission);
+ }
+ }
+
+ public void checkPermission(Permission permission, Object context) {
+ /* Does this methods need to be overidden? */
+ if (!TrapSecurityManager.trapExitCode().get()) {
+ super.checkPermission(permission, context);
+ }
+ }
+
+ // FIXME: we should probably choose a more unique name for this
+ private static final String prefix = "[TrappedExit] ";
+
+ @Override
+ public void checkExit(int status) {
+ if (TrapSecurityManager.trapExitCode().get()) {
+ // using a RuntimeException and a prefix here instead of a custom
+ // exception type because this is thrown by the installed TrapSecurityManager
+ // but other versions of cbt need to be able to catch it, that do not have access
+ // to that version of the TrapSecurityManager class
+ throw new RuntimeException(prefix + status);
+ }
+ super.checkExit(status);
+ }
+
+ public static boolean isTrappedExit(Throwable t) {
+ return t instanceof RuntimeException
+ && t.getMessage() != null
+ && t.getMessage().startsWith(prefix);
+ }
+
+ public static int exitCode(Throwable t) {
+ assert (isTrappedExit(t));
+ return Integer.parseInt(t.getMessage().substring(prefix.length()));
+ }
+}
diff --git a/libraries/common-0/TrapSystemExit.java b/libraries/common-0/TrapSystemExit.java
new file mode 100644
index 0000000..86bc880
--- /dev/null
+++ b/libraries/common-0/TrapSystemExit.java
@@ -0,0 +1,35 @@
+package cbt.reflect;
+
+import java.security.*;
+import java.lang.reflect.InvocationTargetException;
+
+public abstract class TrapSystemExit<T> {
+ public static SecurityManager createSecurityManager(SecurityManager delegateTo) {
+ return new TrapSecurityManager(delegateTo);
+ }
+
+ public static <T> T run(TrapSystemExit<T> runnable) throws Throwable {
+ boolean trapExitCodeBefore = TrapSecurityManager.trapExitCode().get();
+ try {
+ TrapSecurityManager.trapExitCode().set(true);
+ return runnable.run();
+ } catch (InvocationTargetException exception) {
+ Throwable cause = exception.getCause();
+ if (TrapSecurityManager.isTrappedExit(cause)) {
+ return runnable.wrap(TrapSecurityManager.exitCode(cause));
+ }
+ throw exception;
+ } catch (Exception exception) {
+ if (TrapSecurityManager.isTrappedExit(exception)) {
+ return runnable.wrap(TrapSecurityManager.exitCode(exception));
+ }
+ throw exception;
+ } finally {
+ TrapSecurityManager.trapExitCode().set(trapExitCodeBefore);
+ }
+ }
+
+ public abstract T run() throws Throwable;
+
+ public abstract T wrap(int exitCode);
+}
diff --git a/libraries/common-0/build/build.scala b/libraries/common-0/build/build.scala
new file mode 100644
index 0000000..0a4e5cb
--- /dev/null
+++ b/libraries/common-0/build/build.scala
@@ -0,0 +1,7 @@
+package cbt_build.common_0
+import cbt._
+import cbt_internal._
+class Build(val context: Context) extends Library{
+ override def inceptionYear = 2017
+ override def description = "classes shared by multiple cbt libraries and needed in stage 0"
+}
diff --git a/libraries/common-0/build/build/build.scala b/libraries/common-0/build/build/build.scala
new file mode 100644
index 0000000..d3f98ce
--- /dev/null
+++ b/libraries/common-0/build/build/build.scala
@@ -0,0 +1,5 @@
+package cbt_build.reflect.build
+import cbt._
+class Build(val context: Context) extends BuildBuild with CbtInternal{
+ override def dependencies = super.dependencies :+ cbtInternal.library
+}