From 579836f2cf1d9c60f1f60bc107e1fff869b8c6a0 Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Mon, 19 Aug 2019 09:08:46 +0300 Subject: [PATCH] Safe SCL cast for Java objects gitlab #28 Change-Id: I7e8fa4b9bfc6bf3803c8dbfb5c65eb2d631a968b --- org.simantics.g3d/META-INF/MANIFEST.MF | 3 +- org.simantics.g3d/scl/g3d/SCLUtil.scl | 7 ++ .../src/org/simantics/g3d/scl/SCLUtil.java | 79 +++++++++++++++++++ .../scl/plant3d/utils/Loader.scl | 4 - 4 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 org.simantics.g3d/scl/g3d/SCLUtil.scl create mode 100644 org.simantics.g3d/src/org/simantics/g3d/scl/SCLUtil.java diff --git a/org.simantics.g3d/META-INF/MANIFEST.MF b/org.simantics.g3d/META-INF/MANIFEST.MF index c479403d..97772dc1 100644 --- a/org.simantics.g3d/META-INF/MANIFEST.MF +++ b/org.simantics.g3d/META-INF/MANIFEST.MF @@ -18,7 +18,8 @@ Require-Bundle: org.eclipse.core.runtime, gnu.trove3;bundle-version="3.0.0", org.simantics.objmap2;bundle-version="1.0.0", org.eclipse.nebula.widgets.tablecombo;bundle-version="1.0.0", - org.simantics.ui;bundle-version="1.0.0" + org.simantics.ui;bundle-version="1.0.0", + org.simantics.scl.osgi;bundle-version="1.0.4" Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Export-Package: org.simantics.g3d, diff --git a/org.simantics.g3d/scl/g3d/SCLUtil.scl b/org.simantics.g3d/scl/g3d/SCLUtil.scl new file mode 100644 index 00000000..3a30a95d --- /dev/null +++ b/org.simantics.g3d/scl/g3d/SCLUtil.scl @@ -0,0 +1,7 @@ + +importJava "org.simantics.g3d.scl.SCLUtil" where + + javaSafeCoerce :: Typeable b => a -> Maybe b + javaIsInstanceOf :: Typeable b => a -> Boolean + + diff --git a/org.simantics.g3d/src/org/simantics/g3d/scl/SCLUtil.java b/org.simantics.g3d/src/org/simantics/g3d/scl/SCLUtil.java new file mode 100644 index 00000000..99563462 --- /dev/null +++ b/org.simantics.g3d/src/org/simantics/g3d/scl/SCLUtil.java @@ -0,0 +1,79 @@ +package org.simantics.g3d.scl; + +import java.util.HashMap; +import java.util.Map; + +import org.cojen.classfile.TypeDesc; +import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; +import org.simantics.scl.compiler.errors.Failable; +import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; +import org.simantics.scl.compiler.module.Module; +import org.simantics.scl.compiler.module.repository.ImportFailureException; +import org.simantics.scl.compiler.runtime.RuntimeEnvironment; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.osgi.SCLOsgi; + +public class SCLUtil { + + static Map> typeMap = new HashMap>(); + // copied from org.simantics.scl.db.SCLFunctions + public static Class possibleFromDynamic(Type expectedType, String moduleName) { + + try { + + + Failable failable = SCLOsgi.MODULE_REPOSITORY.getModule(moduleName); + Module module = failable.getResult(); + + RuntimeEnvironment env = SCLOsgi.MODULE_REPOSITORY.createRuntimeEnvironment( + EnvironmentSpecification.of(moduleName, ""), module.getParentClassLoader()); + + JavaTypeTranslator tr = new JavaTypeTranslator(env.getEnvironment()); + TypeDesc desc = tr.toTypeDesc(expectedType); + String className = desc.getFullName(); + Class clazz = env.getMutableClassLoader().loadClass(className); + return clazz; + } catch (ImportFailureException e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } + } + + public static Class possibleClass(TCon type) { + Class clazz = typeMap.get(type); + if (clazz == null) { + clazz = possibleFromDynamic(type, type.module); + typeMap.put(type, clazz); + } + return clazz; + } + + public static boolean javaIsInstanceOf(org.simantics.scl.compiler.types.Type t, Object o) { + if (t instanceof TCon) { + Class clazz = possibleClass((TCon)t); + if (clazz == null) + return false; + if (!clazz.isAssignableFrom(o.getClass())) + return false; + + return true; + } + return false; + } + + public static Object javaSafeCoerce(org.simantics.scl.compiler.types.Type t, Object o) { + if (t instanceof TCon) { + Class clazz = possibleClass((TCon)t); + if (clazz == null) + return null; + if (!clazz.isAssignableFrom(o.getClass())) + return null; + + return o; + } + return null; + } + +} diff --git a/org.simantics.plant3d/scl/plant3d/utils/Loader.scl b/org.simantics.plant3d/scl/plant3d/utils/Loader.scl index a039f7e7..6b2f2d99 100644 --- a/org.simantics.plant3d/scl/plant3d/utils/Loader.scl +++ b/org.simantics.plant3d/scl/plant3d/utils/Loader.scl @@ -1,13 +1,9 @@ import "Simantics/DB" import "plant3d/scenegraph/P3DRootNode" import "./P3DScriptNodeMap" -import "JavaBuiltin" importJava "org.simantics.plant3d.scl.SCLUtil" where loadReadOnly :: Resource -> P3DRootNode load :: Resource -> P3DScriptNodeMap -safeCoerce :: a -> Maybe b -safeCoerce a = do - (Just $ unsafeCoerce a) `catch` (\(_ :: Exception) -> Nothing) \ No newline at end of file -- 2.47.0