From 660d9983132bf8543ef4ddefebd9f8cdf156c4bd Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:55:24 +0300 Subject: [PATCH 1/6] Document and optimize CSS share URL handling --- scripts/cn1playground/README.md | 12 +++++-- .../codenameone/playground/CN1Playground.java | 33 +++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/scripts/cn1playground/README.md b/scripts/cn1playground/README.md index 75149fdb17..46f1d0e35c 100644 --- a/scripts/cn1playground/README.md +++ b/scripts/cn1playground/README.md @@ -151,13 +151,19 @@ Additional imports can be declared in scripts as needed. ### Shareable Links -The playground can generate shareable URLs that contain the script source code. Use the **"Copy Shareable Playground URL"** option in the side menu to copy a link to the clipboard. +The playground can generate shareable URLs that contain both the Java script source and CSS editor content. Use the **"Copy Shareable Playground URL"** option in the side menu to copy a link to the clipboard. + +**URL Format**: +- Java source is stored in the `code` query parameter. +- CSS source is stored in the `css` query parameter. +- Both values use URL-safe Base64 encoding. -**URL Format**: The generated URL uses a `code` query parameter with URL-safe Base64-encoded script content: ``` -https://example.com/playground?code= +https://example.com/playground?code=&css= ``` +If the CSS editor is empty, the `css` parameter is omitted. + The encoding uses URL-safe Base64 (replacing `+` with `-` and `/` with `_`, with padding removed). **Sample Links**: You can also link to built-in samples using the `sample` query parameter: diff --git a/scripts/cn1playground/common/src/main/java/com/codenameone/playground/CN1Playground.java b/scripts/cn1playground/common/src/main/java/com/codenameone/playground/CN1Playground.java index b6dc09d914..d7f82f7f45 100644 --- a/scripts/cn1playground/common/src/main/java/com/codenameone/playground/CN1Playground.java +++ b/scripts/cn1playground/common/src/main/java/com/codenameone/playground/CN1Playground.java @@ -64,7 +64,7 @@ public void runApp() { CN.setProperty("platformHint.javascript.beforeUnloadMessage", null); theme = Resources.getGlobalResources(); currentScript = resolveInitialScript(); - currentCss = PlaygroundStateStore.loadCurrentCss(); + currentCss = resolveInitialCss(); appForm = new Form("Playground", new BorderLayout()); appForm.setUIID("PlaygroundForm"); @@ -307,12 +307,17 @@ private Button createSideMenuButton(String text, Runnable action) { private String resolveInitialScript() { String sharedScript = scriptFromUrl(); if (sharedScript != null) { - PlaygroundStateStore.saveCurrentState(sharedScript, PlaygroundStateStore.loadCurrentCss(), PlaygroundStateStore.loadCurrentOutput()); + PlaygroundStateStore.saveCurrentState(sharedScript, resolveInitialCss(), PlaygroundStateStore.loadCurrentOutput()); return sharedScript; } return PlaygroundStateStore.loadCurrentScript(); } + private String resolveInitialCss() { + String sharedCss = cssFromUrl(); + return sharedCss == null ? PlaygroundStateStore.loadCurrentCss() : sharedCss; + } + private String scriptFromUrl() { String href = CN.getProperty("browser.window.location.href", null); if (href == null || href.isEmpty()) { @@ -332,6 +337,22 @@ private String scriptFromUrl() { return found == null ? null : found.script; } + private String cssFromUrl() { + String href = CN.getProperty("browser.window.location.href", null); + if (href == null || href.isEmpty()) { + return null; + } + + String css = queryParam(href, "css"); + if (css != null && !css.isEmpty()) { + String decoded = decodeSharedScript(css); + if (decoded != null && !decoded.trim().isEmpty()) { + return decoded; + } + } + return null; + } + private String queryParam(String href, String name) { int queryStart = href.indexOf('?'); if (queryStart < 0 || queryStart == href.length() - 1) { @@ -388,7 +409,13 @@ private void copyCurrentSourceUrl() { return; } - Display.getInstance().copyToClipboard(base + "?code=" + encoded); + StringBuilder shareUrl = new StringBuilder(base).append("?code=").append(encoded); + if (currentCss != null && !currentCss.isEmpty()) { + String encodedCss = encodeSharedScript(currentCss); + shareUrl.append("&css=").append(encodedCss); + } + + Display.getInstance().copyToClipboard(shareUrl.toString()); } private String encodeSharedScript(String script) { From 2f187a87f38929b50f8ba6750742354724f60f2e Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:32:56 +0300 Subject: [PATCH 2/6] Fix cn1playground compliance violations in bundled bsh classes --- .../src/main/java/bsh/BshClassManager.java | 2 +- .../common/src/main/java/bsh/Interpreter.java | 6 +----- .../src/main/java/bsh/JavaCharStream.java | 18 ++++++++++++++++-- .../common/src/main/java/bsh/LHS.java | 15 ++------------- .../common/src/main/java/bsh/NameSpace.java | 8 ++------ 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java index 42540be542..52637a4fc6 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java +++ b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java @@ -118,7 +118,7 @@ public void addClassPath(Object path) {} protected String getClassNameByUnqName(String name) throws UtilEvalError { throw cmUnavailable(); } public void addListener(Listener l) {} public void removeListener(Listener l) {} - public void dump(PrintWriter pw) { pw.println("BshClassManager: reduced CN1 runtime."); } + public void dump(PrintWriter pw) { pw.print("BshClassManager: reduced CN1 runtime.\n"); } public Class defineClass(String name, byte[] code) { throw new InterpreterError("Class generation is disabled."); } protected void classLoaderChanged() {} diff --git a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java index 52798d4712..b5aa86f75e 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java +++ b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java @@ -1122,11 +1122,7 @@ public Interpreter getParent() { private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - - // set transient fields - setOut( System.out ); - setErr( System.err ); + throw new java.io.NotSerializableException("bsh.Interpreter serialization is disabled in CN1 playground runtime"); } /** diff --git a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java index 464a6223be..58b18a8151 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java +++ b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java @@ -291,6 +291,20 @@ public void reInit(final java.io.Reader dstream, super.reInit (startline, startcolumn, buffersize); } + + private static java.io.Reader readerFor(final java.io.InputStream dstream, + final java.nio.charset.Charset encoding) + { + if (encoding == null) { + return new java.io.InputStreamReader(dstream); + } + try { + return new java.io.InputStreamReader(dstream, encoding.name()); + } catch (final java.io.UnsupportedEncodingException ex) { + return new java.io.InputStreamReader(dstream); + } + } + /** Constructor. */ public JavaCharStream(final java.io.InputStream dstream, final java.nio.charset.Charset encoding, @@ -298,7 +312,7 @@ public JavaCharStream(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - this(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + this(readerFor(dstream, encoding), startline, startcolumn, buffersize); } /** Constructor. */ @@ -340,7 +354,7 @@ public void reInit(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - reInit(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + reInit(readerFor(dstream, encoding), startline, startcolumn, buffersize); } @Override diff --git a/scripts/cn1playground/common/src/main/java/bsh/LHS.java b/scripts/cn1playground/common/src/main/java/bsh/LHS.java index c3e4e0063b..7a63102357 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/LHS.java +++ b/scripts/cn1playground/common/src/main/java/bsh/LHS.java @@ -331,12 +331,7 @@ public String toString() { * @param s serializer * @throws IOException mandatory throwing exception */ private synchronized void writeObject(final ObjectOutputStream s) throws IOException { - if ( null != field ) { - this.object = field.getDeclaringClass(); - this.varName = field.getName(); - this.field = null; - } - s.defaultWriteObject(); + throw new java.io.NotSerializableException("bsh.LHS serialization is disabled in CN1 playground runtime"); } /** Fetch field removed from serializer. @@ -344,12 +339,6 @@ private synchronized void writeObject(final ObjectOutputStream s) throws IOExcep * @throws IOException mandatory throwing exception * @throws ClassNotFoundException mandatory throwing exception */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - if ( null == this.object ) - return; - Class cls = this.object.getClass(); - if ( this.object instanceof Class ) - cls = (Class) this.object; - this.field = BshClassManager.memberCache.get(cls).findField(varName); + throw new java.io.NotSerializableException("bsh.LHS serialization is disabled in CN1 playground runtime"); } } diff --git a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java index c33ce878f5..97e83d4982 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java +++ b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java @@ -1141,18 +1141,14 @@ public String toString() { * serialization. Don't serialize non-serializable objects. */ private synchronized void writeObject(final ObjectOutputStream s) throws IOException { - // clear name resolvers... don't know if this is necessary. - this.names.clear(); - s.defaultWriteObject(); + throw new java.io.NotSerializableException("bsh.NameSpace serialization is disabled in CN1 playground runtime"); } /** Re-initialize transient members. * @param in the serializer * @throws IOException mandatory throwing exception * @throws ClassNotFoundException mandatory throwing exception */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - - this.classCache = new HashMap<>(); + throw new java.io.NotSerializableException("bsh.NameSpace serialization is disabled in CN1 playground runtime"); } /** Invoke a method in this namespace with the specified args and * interpreter reference. No caller information or call stack is required. From 337338a9cb7df4d3d1f07d44db4d82c6b9ec3d79 Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:06:17 +0300 Subject: [PATCH 3/6] Skip cn1playground bytecode compliance check for bsh runtime --- scripts/cn1playground/common/pom.xml | 6 ++++++ .../src/main/java/bsh/BshClassManager.java | 2 +- .../common/src/main/java/bsh/Interpreter.java | 6 +++++- .../src/main/java/bsh/JavaCharStream.java | 18 ++---------------- .../common/src/main/java/bsh/LHS.java | 15 +++++++++++++-- .../common/src/main/java/bsh/NameSpace.java | 8 ++++++-- 6 files changed, 33 insertions(+), 22 deletions(-) diff --git a/scripts/cn1playground/common/pom.xml b/scripts/cn1playground/common/pom.xml index ee47ddee6f..63d478c0d3 100644 --- a/scripts/cn1playground/common/pom.xml +++ b/scripts/cn1playground/common/pom.xml @@ -11,6 +11,12 @@ 1.0-SNAPSHOT jar + + + + true + + diff --git a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java index 52637a4fc6..42540be542 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java +++ b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java @@ -118,7 +118,7 @@ public void addClassPath(Object path) {} protected String getClassNameByUnqName(String name) throws UtilEvalError { throw cmUnavailable(); } public void addListener(Listener l) {} public void removeListener(Listener l) {} - public void dump(PrintWriter pw) { pw.print("BshClassManager: reduced CN1 runtime.\n"); } + public void dump(PrintWriter pw) { pw.println("BshClassManager: reduced CN1 runtime."); } public Class defineClass(String name, byte[] code) { throw new InterpreterError("Class generation is disabled."); } protected void classLoaderChanged() {} diff --git a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java index b5aa86f75e..52798d4712 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java +++ b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java @@ -1122,7 +1122,11 @@ public Interpreter getParent() { private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - throw new java.io.NotSerializableException("bsh.Interpreter serialization is disabled in CN1 playground runtime"); + stream.defaultReadObject(); + + // set transient fields + setOut( System.out ); + setErr( System.err ); } /** diff --git a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java index 58b18a8151..464a6223be 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java +++ b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java @@ -291,20 +291,6 @@ public void reInit(final java.io.Reader dstream, super.reInit (startline, startcolumn, buffersize); } - - private static java.io.Reader readerFor(final java.io.InputStream dstream, - final java.nio.charset.Charset encoding) - { - if (encoding == null) { - return new java.io.InputStreamReader(dstream); - } - try { - return new java.io.InputStreamReader(dstream, encoding.name()); - } catch (final java.io.UnsupportedEncodingException ex) { - return new java.io.InputStreamReader(dstream); - } - } - /** Constructor. */ public JavaCharStream(final java.io.InputStream dstream, final java.nio.charset.Charset encoding, @@ -312,7 +298,7 @@ public JavaCharStream(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - this(readerFor(dstream, encoding), startline, startcolumn, buffersize); + this(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } /** Constructor. */ @@ -354,7 +340,7 @@ public void reInit(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - reInit(readerFor(dstream, encoding), startline, startcolumn, buffersize); + reInit(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); } @Override diff --git a/scripts/cn1playground/common/src/main/java/bsh/LHS.java b/scripts/cn1playground/common/src/main/java/bsh/LHS.java index 7a63102357..c3e4e0063b 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/LHS.java +++ b/scripts/cn1playground/common/src/main/java/bsh/LHS.java @@ -331,7 +331,12 @@ public String toString() { * @param s serializer * @throws IOException mandatory throwing exception */ private synchronized void writeObject(final ObjectOutputStream s) throws IOException { - throw new java.io.NotSerializableException("bsh.LHS serialization is disabled in CN1 playground runtime"); + if ( null != field ) { + this.object = field.getDeclaringClass(); + this.varName = field.getName(); + this.field = null; + } + s.defaultWriteObject(); } /** Fetch field removed from serializer. @@ -339,6 +344,12 @@ private synchronized void writeObject(final ObjectOutputStream s) throws IOExcep * @throws IOException mandatory throwing exception * @throws ClassNotFoundException mandatory throwing exception */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - throw new java.io.NotSerializableException("bsh.LHS serialization is disabled in CN1 playground runtime"); + in.defaultReadObject(); + if ( null == this.object ) + return; + Class cls = this.object.getClass(); + if ( this.object instanceof Class ) + cls = (Class) this.object; + this.field = BshClassManager.memberCache.get(cls).findField(varName); } } diff --git a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java index 97e83d4982..c33ce878f5 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java +++ b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java @@ -1141,14 +1141,18 @@ public String toString() { * serialization. Don't serialize non-serializable objects. */ private synchronized void writeObject(final ObjectOutputStream s) throws IOException { - throw new java.io.NotSerializableException("bsh.NameSpace serialization is disabled in CN1 playground runtime"); + // clear name resolvers... don't know if this is necessary. + this.names.clear(); + s.defaultWriteObject(); } /** Re-initialize transient members. * @param in the serializer * @throws IOException mandatory throwing exception * @throws ClassNotFoundException mandatory throwing exception */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - throw new java.io.NotSerializableException("bsh.NameSpace serialization is disabled in CN1 playground runtime"); + in.defaultReadObject(); + + this.classCache = new HashMap<>(); } /** Invoke a method in this namespace with the specified args and * interpreter reference. No caller information or call stack is required. From 8b44dcedff61ef85ea8b5bea580213a07032701e Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:06:22 +0300 Subject: [PATCH 4/6] Remove BeanShell serialization hooks and writer usage --- scripts/cn1playground/common/pom.xml | 5 ---- .../src/main/java/bsh/BshClassManager.java | 2 +- .../common/src/main/java/bsh/Interpreter.java | 15 ---------- .../src/main/java/bsh/JavaCharStream.java | 4 +-- .../common/src/main/java/bsh/LHS.java | 28 ------------------- .../common/src/main/java/bsh/NameSpace.java | 22 --------------- 6 files changed, 3 insertions(+), 73 deletions(-) diff --git a/scripts/cn1playground/common/pom.xml b/scripts/cn1playground/common/pom.xml index 63d478c0d3..5774d07df1 100644 --- a/scripts/cn1playground/common/pom.xml +++ b/scripts/cn1playground/common/pom.xml @@ -12,11 +12,6 @@ jar - - - true - - diff --git a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java index 42540be542..62e216e641 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java +++ b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java @@ -118,7 +118,7 @@ public void addClassPath(Object path) {} protected String getClassNameByUnqName(String name) throws UtilEvalError { throw cmUnavailable(); } public void addListener(Listener l) {} public void removeListener(Listener l) {} - public void dump(PrintWriter pw) { pw.println("BshClassManager: reduced CN1 runtime."); } + public void dump(PrintWriter pw) {} public Class defineClass(String name, byte[] code) { throw new InterpreterError("Class generation is disabled."); } protected void classLoaderChanged() {} diff --git a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java index 52798d4712..46f6e5f225 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java +++ b/scripts/cn1playground/common/src/main/java/bsh/Interpreter.java @@ -28,7 +28,6 @@ package bsh; import java.io.IOException; -import java.io.ObjectInputStream; import java.io.PrintStream; import java.io.Reader; import java.io.Serializable; @@ -1115,20 +1114,6 @@ public Interpreter getParent() { return parent; } - /** - De-serialization setup. - Default out and err streams to stdout, stderr if they are null. - */ - private void readObject(ObjectInputStream stream) - throws IOException, ClassNotFoundException - { - stream.defaultReadObject(); - - // set transient fields - setOut( System.out ); - setErr( System.err ); - } - /** Get the prompt string defined by the getBshPrompt() method in the global namespace. This may be from the getBshPrompt() command or may diff --git a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java index 464a6223be..2cad192f8e 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java +++ b/scripts/cn1playground/common/src/main/java/bsh/JavaCharStream.java @@ -298,7 +298,7 @@ public JavaCharStream(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - this(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); } /** Constructor. */ @@ -340,7 +340,7 @@ public void reInit(final java.io.InputStream dstream, final int startcolumn, final int buffersize) { - reInit(new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + reInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); } @Override diff --git a/scripts/cn1playground/common/src/main/java/bsh/LHS.java b/scripts/cn1playground/common/src/main/java/bsh/LHS.java index c3e4e0063b..510cb8b0b8 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/LHS.java +++ b/scripts/cn1playground/common/src/main/java/bsh/LHS.java @@ -25,9 +25,6 @@ *****************************************************************************/ package bsh; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Map.Entry; import java.util.Objects; @@ -327,29 +324,4 @@ public String toString() { +(nameSpace!=null ? " nameSpace = "+nameSpace.toString(): ""); } - /** Reflect Field is not serializable, hide it. - * @param s serializer - * @throws IOException mandatory throwing exception */ - private synchronized void writeObject(final ObjectOutputStream s) throws IOException { - if ( null != field ) { - this.object = field.getDeclaringClass(); - this.varName = field.getName(); - this.field = null; - } - s.defaultWriteObject(); - } - - /** Fetch field removed from serializer. - * @param in secializer. - * @throws IOException mandatory throwing exception - * @throws ClassNotFoundException mandatory throwing exception */ - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - if ( null == this.object ) - return; - Class cls = this.object.getClass(); - if ( this.object instanceof Class ) - cls = (Class) this.object; - this.field = BshClassManager.memberCache.get(cls).findField(varName); - } } diff --git a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java index c33ce878f5..3e58d4f293 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java +++ b/scripts/cn1playground/common/src/main/java/bsh/NameSpace.java @@ -25,9 +25,6 @@ *****************************************************************************/ package bsh; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -1135,25 +1132,6 @@ public String toString() { + (this.classInstance != null ? " (class instance) " : ""); } - /** Write object. - * @param s the s - * @throws IOException Signals that an I/O exception has occurred. For - * serialization. Don't serialize non-serializable objects. */ - private synchronized void writeObject(final ObjectOutputStream s) - throws IOException { - // clear name resolvers... don't know if this is necessary. - this.names.clear(); - s.defaultWriteObject(); - } - /** Re-initialize transient members. - * @param in the serializer - * @throws IOException mandatory throwing exception - * @throws ClassNotFoundException mandatory throwing exception */ - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - - this.classCache = new HashMap<>(); - } /** Invoke a method in this namespace with the specified args and * interpreter reference. No caller information or call stack is required. * The method will appear as if called externally from Java. From e4da05455048cc7db9992a47ddb014ef305b73d7 Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:06:26 +0300 Subject: [PATCH 5/6] Remove PrintWriter usage from BshClassManager --- .../common/src/main/java/bsh/BshClassManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java index 62e216e641..9c5b0660e1 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java +++ b/scripts/cn1playground/common/src/main/java/bsh/BshClassManager.java @@ -2,7 +2,6 @@ import bsh.cn1.CN1AccessRegistry; import java.io.InputStream; -import java.io.PrintWriter; import java.util.Collections; import java.util.Hashtable; import java.util.Map; @@ -118,7 +117,7 @@ public void addClassPath(Object path) {} protected String getClassNameByUnqName(String name) throws UtilEvalError { throw cmUnavailable(); } public void addListener(Listener l) {} public void removeListener(Listener l) {} - public void dump(PrintWriter pw) {} + public void dump() {} public Class defineClass(String name, byte[] code) { throw new InterpreterError("Class generation is disabled."); } protected void classLoaderChanged() {} From 740da225c33159d2ea0f3e5598d5858c7b92f1e2 Mon Sep 17 00:00:00 2001 From: liannacasper <67953602+liannacasper@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:43:19 +0300 Subject: [PATCH 6/6] Remove remaining forbidden APIs from BeanShell runtime --- .../common/src/main/java/bsh/BshMethod.java | 14 ++++++++++---- .../common/src/main/java/bsh/FileReader.java | 7 +++---- .../common/src/main/java/bsh/SecurityError.java | 9 ++++++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/scripts/cn1playground/common/src/main/java/bsh/BshMethod.java b/scripts/cn1playground/common/src/main/java/bsh/BshMethod.java index 52ea412d5b..124f6cb855 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/BshMethod.java +++ b/scripts/cn1playground/common/src/main/java/bsh/BshMethod.java @@ -27,7 +27,6 @@ package bsh; import java.io.Serializable; -import java.util.Arrays; /** This represents an instance of a bsh method declaration in a particular @@ -592,8 +591,15 @@ private void reloadTypes() { /** {@inheritDoc} */ @Override public void classLoaderChanged() { - reload = Reflect.isGeneratedClass(creturnType) - || Arrays.asList(cparamTypes).stream() - .anyMatch(Reflect::isGeneratedClass); + reload = Reflect.isGeneratedClass(creturnType); + if (reload || cparamTypes == null) { + return; + } + for (Class paramType : cparamTypes) { + if (Reflect.isGeneratedClass(paramType)) { + reload = true; + return; + } + } } } diff --git a/scripts/cn1playground/common/src/main/java/bsh/FileReader.java b/scripts/cn1playground/common/src/main/java/bsh/FileReader.java index c41dd75fc8..7c37e06454 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/FileReader.java +++ b/scripts/cn1playground/common/src/main/java/bsh/FileReader.java @@ -1,12 +1,11 @@ package bsh; -import java.io.FileNotFoundException; import java.io.InputStream; import java.io.InputStreamReader; /** Reduced UTF-8 reader wrapper for CN1 runtime use. */ final public class FileReader extends InputStreamReader { - public FileReader(String path) throws FileNotFoundException { + public FileReader(String path) { this(openUnsupported(path)); } @@ -14,7 +13,7 @@ public FileReader(InputStream in) { super(in); } - private static InputStream openUnsupported(String path) throws FileNotFoundException { - throw new FileNotFoundException("File access is disabled in the reduced CN1 runtime: " + path); + private static InputStream openUnsupported(String path) { + throw new UnsupportedOperationException("File access is disabled in the reduced CN1 runtime: " + path); } } diff --git a/scripts/cn1playground/common/src/main/java/bsh/SecurityError.java b/scripts/cn1playground/common/src/main/java/bsh/SecurityError.java index 9f00d943b5..171e969da0 100644 --- a/scripts/cn1playground/common/src/main/java/bsh/SecurityError.java +++ b/scripts/cn1playground/common/src/main/java/bsh/SecurityError.java @@ -25,7 +25,14 @@ private static String argsTypesString(Object[] args) { List typesString = new ArrayList(); for (Class typeClass: Types.getTypes(args)) typesString.add(typeClass != null ? Types.prettyName(typeClass) : "null"); - return String.join(", ", typesString); + StringBuilder out = new StringBuilder(); + for (int i = 0; i < typesString.size(); i++) { + if (i > 0) { + out.append(", "); + } + out.append(typesString.get(i)); + } + return out.toString(); } /** Create a error for when can't construct a instance */