summaryrefslogtreecommitdiffstats
path: root/scripting/examples/java/debugger
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /scripting/examples/java/debugger
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--scripting/examples/java/debugger/DebugRunner.java87
-rw-r--r--scripting/examples/java/debugger/OOBeanShellDebugger.java393
-rw-r--r--scripting/examples/java/debugger/OORhinoDebugger.java97
-rw-r--r--scripting/examples/java/debugger/OOScriptDebugger.java27
-rw-r--r--scripting/examples/java/debugger/parcel-descriptor.xml34
5 files changed, 638 insertions, 0 deletions
diff --git a/scripting/examples/java/debugger/DebugRunner.java b/scripting/examples/java/debugger/DebugRunner.java
new file mode 100644
index 000000000..a3b4869fe
--- /dev/null
+++ b/scripting/examples/java/debugger/DebugRunner.java
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package org.libreoffice.example.java_scripts;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLDecoder;
+
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.script.framework.provider.PathUtils;
+import com.sun.star.script.provider.XScriptContext;
+
+public class DebugRunner {
+
+ private static final String FILE_URL_PREFIX =
+ System.getProperty("os.name").startsWith("Windows") == true ?
+ "file:///" : "file://";
+
+ public void go(final XScriptContext xsctxt, String language, String uri,
+ String filename) {
+
+ OOScriptDebugger debugger;
+ String path = "";
+
+ if (language.equals("JavaScript")) {
+ debugger = new OORhinoDebugger();
+ } else if (language.equals("BeanShell")) {
+ debugger = new OOBeanShellDebugger();
+ } else {
+ return;
+ }
+
+ if (uri.startsWith(FILE_URL_PREFIX)) {
+ uri = URLDecoder.decode(uri);
+ String s = uri.substring(FILE_URL_PREFIX.length());
+ File f = new File(s);
+
+ if (f.exists()) {
+ if (f.isDirectory()) {
+ if (!filename.equals("")) {
+ path = new File(f, filename).getAbsolutePath();
+ }
+ } else {
+ path = f.getAbsolutePath();
+ }
+ }
+
+ debugger.go(xsctxt, path);
+ } else {
+ if (!uri.endsWith("/")) {
+ uri += "/";
+ }
+
+ String script = uri + filename;
+ InputStream is;
+
+ try {
+ is = PathUtils.getScriptFileStream(
+ script, xsctxt.getComponentContext());
+
+ if (is != null) {
+ debugger.go(xsctxt, is);
+ }
+ } catch (IOException ioe) {
+ System.out.println("Error loading script: " + script);
+ }
+ }
+ }
+}
diff --git a/scripting/examples/java/debugger/OOBeanShellDebugger.java b/scripting/examples/java/debugger/OOBeanShellDebugger.java
new file mode 100644
index 000000000..68a508784
--- /dev/null
+++ b/scripting/examples/java/debugger/OOBeanShellDebugger.java
@@ -0,0 +1,393 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package org.libreoffice.example.java_scripts;
+
+import javax.swing.JFrame;
+import javax.swing.JTextArea;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.text.Document;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.DocumentEvent;
+
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.Dimension;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import com.sun.star.script.provider.XScriptContext;
+import bsh.Interpreter;
+
+public class OOBeanShellDebugger implements OOScriptDebugger, ActionListener,
+ DocumentListener {
+
+ private JFrame frame;
+ private JTextArea ta;
+ private GlyphGutter gg;
+ private XScriptContext context;
+ private int currentPosition = -1;
+ private int linecount;
+ private Interpreter sessionInterpreter;
+ private Thread execThread = null;
+ private String filename = null;
+
+ /* Entry point for script execution */
+ public void go(XScriptContext context, String filename) {
+ if (filename != null && filename != "") {
+ try {
+ FileInputStream fis = new FileInputStream(filename);
+ this.filename = filename;
+ go(context, fis);
+ } catch (IOException ioe) {
+ JOptionPane.showMessageDialog(frame,
+ "Error loading file: " + ioe.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /* Entry point for script execution */
+ public void go(XScriptContext context, InputStream in) {
+ this.context = context;
+ initUI();
+
+ if (in != null) {
+ try {
+ loadFile(in);
+ } catch (IOException ioe) {
+ JOptionPane.showMessageDialog(frame,
+ "Error loading stream: " + ioe.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ public void loadFile(InputStream in) throws IOException {
+
+ /* Remove ourselves as a DocumentListener while loading the file
+ so we don't get a storm of DocumentEvents during loading */
+ ta.getDocument().removeDocumentListener(this);
+
+ byte[] contents = new byte[1024];
+ int len = 0, pos = 0;
+
+ while ((len = in.read(contents, 0, 1024)) != -1) {
+ ta.insert(new String(contents, 0, len), pos);
+ pos += len;
+ }
+
+ try {
+ in.close();
+ } catch (IOException ignore) {
+ }
+
+ /* Update the GlyphGutter and add back the DocumentListener */
+ gg.update();
+ ta.getDocument().addDocumentListener(this);
+ }
+
+ private void initUI() {
+ frame = new JFrame("BeanShell Debug Window");
+ ta = new JTextArea();
+ ta.setRows(15);
+ ta.setColumns(40);
+ ta.setLineWrap(false);
+ linecount = ta.getLineCount();
+
+ gg = new GlyphGutter(this);
+
+ final JScrollPane sp = new JScrollPane();
+ sp.setViewportView(ta);
+ sp.setRowHeaderView(gg);
+
+ ta.getDocument().addDocumentListener(this);
+ String[] labels = {"Run", "Clear", "Save", "Close"};
+ JPanel p = new JPanel();
+ p.setLayout(new FlowLayout());
+
+ for (int i = 0; i < labels.length; i++) {
+ JButton b = new JButton(labels[i]);
+ b.addActionListener(this);
+ p.add(b);
+
+ if (labels[i].equals("Save") && filename == null) {
+ b.setEnabled(false);
+ }
+ }
+
+ frame.getContentPane().add(sp, "Center");
+ frame.getContentPane().add(p, "South");
+ frame.pack();
+ frame.show();
+ }
+
+ /* Implementation of DocumentListener interface */
+ public void insertUpdate(DocumentEvent e) {
+ doChanged(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ doChanged(e);
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ doChanged(e);
+ }
+
+ /* If the number of lines in the JTextArea has changed then update the
+ GlyphGutter */
+ public void doChanged(DocumentEvent e) {
+ if (linecount != ta.getLineCount()) {
+ gg.update();
+ linecount = ta.getLineCount();
+ }
+ }
+
+ private void startExecution() {
+ execThread = new Thread() {
+ public void run() {
+ Interpreter interpreter = new Interpreter();
+ interpreter.getNameSpace().clear();
+
+ // reset position and repaint gutter so no red arrow appears
+ currentPosition = -1;
+ gg.repaint();
+
+ try {
+ interpreter.set("context", context);
+ interpreter.eval(ta.getText());
+ } catch (bsh.EvalError err) {
+ currentPosition = err.getErrorLineNumber() - 1;
+
+ try {
+ // scroll to line of the error
+ int line = ta.getLineStartOffset(currentPosition);
+ Rectangle rect = ta.modelToView(line);
+ ta.scrollRectToVisible(rect);
+ } catch (Exception e) {
+ // couldn't scroll to line, do nothing
+ }
+
+ gg.repaint();
+
+ JOptionPane.showMessageDialog(frame, "Error at line " +
+ String.valueOf(err.getErrorLineNumber()) +
+ "\n\n: " + err.getErrorText(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(frame,
+ "Error: " + e.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ };
+ execThread.start();
+ }
+
+ private void promptForSaveName() {
+ JFileChooser chooser = new JFileChooser();
+ chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
+ public boolean accept(File f) {
+ if (f.isDirectory() || f.getName().endsWith(".bsh")) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public String getDescription() {
+ return ("BeanShell files: *.bsh");
+ }
+ });
+
+ int ret = chooser.showSaveDialog(frame);
+
+ if (ret == JFileChooser.APPROVE_OPTION) {
+ filename = chooser.getSelectedFile().getAbsolutePath();
+
+ if (!filename.endsWith(".bsh")) {
+ filename += ".bsh";
+ }
+ }
+
+ }
+
+ private void saveTextArea() {
+ if (filename == null) {
+ promptForSaveName();
+ }
+
+ FileOutputStream fos = null;
+
+ if (filename != null) {
+ try {
+ File f = new File(filename);
+ fos = new FileOutputStream(f);
+ String s = ta.getText();
+ fos.write(s.getBytes(), 0, s.length());
+ } catch (IOException ioe) {
+ JOptionPane.showMessageDialog(frame,
+ "Error saving file: " + ioe.getMessage(),
+ "Error", JOptionPane.ERROR_MESSAGE);
+ } finally {
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+ }
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("Run")) {
+ startExecution();
+ } else if (e.getActionCommand().equals("Close")) {
+ frame.dispose();
+ } else if (e.getActionCommand().equals("Save")) {
+ saveTextArea();
+ } else if (e.getActionCommand().equals("Clear")) {
+ ta.setText("");
+ }
+ }
+
+ public JTextArea getTextArea() {
+ return ta;
+ }
+
+ public int getCurrentPosition() {
+ return currentPosition;
+ }
+}
+
+class GlyphGutter extends JComponent {
+
+ private OOBeanShellDebugger debugger;
+ private final String DUMMY_STRING = "99";
+
+ GlyphGutter(OOBeanShellDebugger debugger) {
+ this.debugger = debugger;
+ update();
+ }
+
+ public void update() {
+ JTextArea textArea = debugger.getTextArea();
+ Font font = textArea.getFont();
+ setFont(font);
+
+ FontMetrics metrics = getFontMetrics(font);
+ int h = metrics.getHeight();
+ int lineCount = textArea.getLineCount() + 1;
+
+ String dummy = Integer.toString(lineCount);
+
+ if (dummy.length() < 2) {
+ dummy = DUMMY_STRING;
+ }
+
+ Dimension d = new Dimension();
+ d.width = metrics.stringWidth(dummy) + 16;
+ d.height = lineCount * h + 100;
+ setPreferredSize(d);
+ setSize(d);
+ }
+
+ public void paintComponent(Graphics g) {
+ JTextArea textArea = debugger.getTextArea();
+
+ Font font = textArea.getFont();
+ g.setFont(font);
+
+ FontMetrics metrics = getFontMetrics(font);
+ Rectangle clip = g.getClipBounds();
+
+ g.setColor(getBackground());
+ g.fillRect(clip.x, clip.y, clip.width, clip.height);
+
+ int ascent = metrics.getMaxAscent();
+ int h = metrics.getHeight();
+ int lineCount = textArea.getLineCount() + 1;
+
+ int startLine = clip.y / h;
+ int endLine = (clip.y + clip.height) / h + 1;
+ int width = getWidth();
+
+ if (endLine > lineCount) {
+ endLine = lineCount;
+ }
+
+ for (int i = startLine; i < endLine; i++) {
+ String text;
+ text = Integer.toString(i + 1) + " ";
+ int w = metrics.stringWidth(text);
+ int y = i * h;
+ g.setColor(Color.blue);
+ g.drawString(text, 0, y + ascent);
+ int x = width - ascent;
+
+ // if currentPosition is not -1 then a red arrow will be drawn
+ if (i == debugger.getCurrentPosition()) {
+ drawArrow(g, ascent, x, y);
+ }
+ }
+ }
+
+ private void drawArrow(Graphics g, int ascent, int x, int y) {
+ Polygon arrow = new Polygon();
+ int dx = x;
+ y += ascent - 10;
+ int dy = y;
+ arrow.addPoint(dx, dy + 3);
+ arrow.addPoint(dx + 5, dy + 3);
+
+ for (x = dx + 5; x <= dx + 10; x++, y++) {
+ arrow.addPoint(x, y);
+ }
+
+ for (x = dx + 9; x >= dx + 5; x--, y++) {
+ arrow.addPoint(x, y);
+ }
+
+ arrow.addPoint(dx + 5, dy + 7);
+ arrow.addPoint(dx, dy + 7);
+
+ g.setColor(Color.red);
+ g.fillPolygon(arrow);
+ g.setColor(Color.black);
+ g.drawPolygon(arrow);
+ }
+};
+
diff --git a/scripting/examples/java/debugger/OORhinoDebugger.java b/scripting/examples/java/debugger/OORhinoDebugger.java
new file mode 100644
index 000000000..5144637ac
--- /dev/null
+++ b/scripting/examples/java/debugger/OORhinoDebugger.java
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package org.libreoffice.example.java_scripts;
+
+import javax.swing.SwingUtilities;
+import java.io.InputStream;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.ImporterTopLevel;
+import org.mozilla.javascript.tools.debugger.Main;
+import org.mozilla.javascript.tools.debugger.ScopeProvider;
+
+import com.sun.star.script.provider.XScriptContext;
+
+public class OORhinoDebugger implements OOScriptDebugger {
+
+ public void go(final XScriptContext xsctxt, String filename) {
+ Main sdb = initUI(xsctxt);
+
+ // This is the method we've added to open a file when starting
+ // the Rhino debugger
+ sdb.openFile(filename);
+ }
+
+ public void go(final XScriptContext xsctxt, InputStream in) {
+ Main sdb = initUI(xsctxt);
+
+ // Open a stream in the debugger
+ sdb.openStream(in);
+ }
+
+ // This code is based on the main method of the Rhino Debugger Main class
+ // We pass in the XScriptContext in the global scope for script execution
+ private Main initUI(final XScriptContext xsctxt) {
+ try {
+ final Main sdb = new Main("Rhino JavaScript Debugger");
+ swingInvoke(new Runnable() {
+ public void run() {
+ sdb.pack();
+ sdb.setSize(640, 640);
+ sdb.setVisible(true);
+ }
+ });
+ sdb.setExitAction(new Runnable() {
+ public void run() {
+ sdb.dispose();
+ }
+ });
+ Context.addContextListener(sdb);
+ sdb.setScopeProvider(new ScopeProvider() {
+ public Scriptable getScope() {
+ Context ctxt = Context.enter();
+ ImporterTopLevel scope = new ImporterTopLevel(ctxt);
+ Scriptable jsArgs = Context.toObject(xsctxt, scope);
+ scope.put("XSCRIPTCONTEXT", scope, jsArgs);
+ Context.exit();
+ return scope;
+ }
+ });
+ return sdb;
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+
+ return null;
+ }
+
+ static void swingInvoke(Runnable f) {
+ if (SwingUtilities.isEventDispatchThread()) {
+ f.run();
+ return;
+ }
+
+ try {
+ SwingUtilities.invokeAndWait(f);
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ }
+}
diff --git a/scripting/examples/java/debugger/OOScriptDebugger.java b/scripting/examples/java/debugger/OOScriptDebugger.java
new file mode 100644
index 000000000..61fdbe73d
--- /dev/null
+++ b/scripting/examples/java/debugger/OOScriptDebugger.java
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package org.libreoffice.example.java_scripts;
+
+import java.io.InputStream;
+import com.sun.star.script.provider.XScriptContext;
+
+public interface OOScriptDebugger {
+ public void go(XScriptContext ctxt, String filename);
+ public void go(XScriptContext ctxt, InputStream in);
+}
diff --git a/scripting/examples/java/debugger/parcel-descriptor.xml b/scripting/examples/java/debugger/parcel-descriptor.xml
new file mode 100644
index 000000000..93fbeabbe
--- /dev/null
+++ b/scripting/examples/java/debugger/parcel-descriptor.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<parcel language="Java">
+
+ <script language="Java">
+ <locale lang="en">
+ <displayname value="Scripting Framework Debugger" />
+ <description>Script that starts debuggers for JavaScript and BeanShell
+ </description>
+ </locale>
+ <logicalname value="org.libreoffice.example.java_scripts._$DebugRunner.Debug" />
+ <functionname value="DebugRunner.go" />
+ <languagedepprops>
+ <prop name="classpath" value="debugger.jar"/>
+ </languagedepprops>
+ </script>
+</parcel>
+