Changeset 1078


Ignore:
Timestamp:
07/12/16 23:49:55 (8 years ago)
Author:
davidb
Message:

Refactoring to allow support for additional scriptable languages. In this case, Python being added in through Jythohn Java library

Location:
trunk
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/.classpath

    r1066 r1078  
    1212        <classpathentry kind="lib" path="releases/jars/JFreeCharts.jar"/>
    1313        <classpathentry kind="lib" path="releases/jars/js.jar"/>
     14        <classpathentry kind="lib" path="releases/jars/jython-standalone-2.7.0.jar"/>
    1415        <classpathentry kind="lib" path="releases/jars/lobo.jar"/>
    1516        <classpathentry kind="lib" path="releases/jars/lobo-pub.jar"/>
  • trunk/build.xml

    r1067 r1078  
    3535                <zipfileset excludes="META-INF/*.SF" src="releases/jars/JFreeCharts.jar"/>
    3636                <zipfileset excludes="META-INF/*.SF" src="releases/jars/js.jar"/>
     37                <zipfileset excludes="META-INF/*.SF" src="releases/jars/jython-standalone-2.7.0.jar"/>
    3738                <zipfileset excludes="META-INF/*.SF" src="releases/jars/lobo.jar"/>
    3839                <zipfileset excludes="META-INF/*.SF" src="releases/jars/lobo-pub.jar"/>
  • trunk/src/org/expeditee/actions/Javascript2.java

    r951 r1078  
    4848 * @author jts21
    4949 */
    50 public class Javascript2 {
     50public class Javascript2 extends ScriptBase {
    5151       
    52         public static final String ERROR_FRAMESET = "JavascriptErrors";
     52    protected void init() {
     53        ERROR_FRAMESET = "JavascriptErrors";
     54        scriptEngineManager = new ScriptEngineManager();
     55        scriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
     56        scriptEngine.put("invocable", (Invocable) scriptEngine);
     57    }
    5358       
    54         public static final ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
    55         public static final ScriptEngine scriptEngine = scriptEngineManager.getEngineByMimeType("application/javascript");
    56         static {
    57                 scriptEngine.put("invocable", (Invocable) scriptEngine);
     59    public static void printJSFrame(Item item) {
     60        if(item.getChild() == null) {
     61            // if the user clicked on the action without an item on their cursor
     62            if(item.hasAction()) {
     63                boolean isThis = false;
     64                for(String s : item.getAction()) {
     65                    if(s.equalsIgnoreCase("printJSFrame")) {
     66                        isThis = true;
     67                        break;
     68                    }
     69                }
     70                if(isThis) {
     71                    System.out.println(new Javascript2(item.getParentOrCurrentFrame(), true));
     72                    return;
     73                }
     74            }
     75            MessageBay.warningMessage("Requires either an item with a link to a frame, or no item (will run the current frame)");
     76        } else {
     77            System.out.println(new Javascript2(item.getChild(), true));
    5878        }
     79    }
    5980       
    60         public static void printJSFrame(Item item) {
    61                 if(item.getChild() == null) {
    62                         // if the user clicked on the action without an item on their cursor
    63                 if(item.hasAction()) {
    64                         boolean isThis = false;
    65                         for(String s : item.getAction()) {
    66                                 if(s.equalsIgnoreCase("runJSFrame")) {
    67                                         isThis = true;
    68                                         break;
    69                                 }
    70                         }
    71                         if(isThis) {
    72                                 System.out.println(new Javascript2(item.getParentOrCurrentFrame(), true));
    73                                 return;
    74                         }
    75                 }
    76                 MessageBay.warningMessage("Requires either an item with a link to a frame, or no item (will run the current frame)");
    77                 } else {
    78                         System.out.println(new Javascript2(item.getChild(), true));
     81    public static void runJSFrame(Item item) throws Exception {
     82        if(item.getChild() == null) {
     83            // if the user clicked on the action without an item on their cursor
     84            if(item.hasAction()) {
     85                boolean isThis = false;
     86                for(String s : item.getAction()) {
     87                    if(s.equalsIgnoreCase("runJSFrame")) {
     88                        isThis = true;
     89                        break;
     90                    }
    7991                }
     92                if(isThis) {
     93                    Javascript2.runFrameFollow(item.getParentOrCurrentFrame());
     94                    return;
     95                }
     96            }
     97            MessageBay.warningMessage("Requires either an item with a link to a frame, or no item (will run the current frame)");
     98        } else {
     99            Javascript2.runFrameFollow(item.getChild());
    80100        }
     101    }
    81102       
    82         public static void runJSFrame(Item item) throws Exception {
    83                 if(item.getChild() == null) {
    84                         // if the user clicked on the action without an item on their cursor
    85                 if(item.hasAction()) {
    86                         boolean isThis = false;
    87                         for(String s : item.getAction()) {
    88                                 if(s.equalsIgnoreCase("runJSFrame")) {
    89                                         isThis = true;
    90                                         break;
    91                                 }
    92                         }
    93                         if(isThis) {
    94                                 Javascript2.runFrame(item.getParentOrCurrentFrame(), true);
    95                                 return;
    96                         }
    97                 }
    98                 MessageBay.warningMessage("Requires either an item with a link to a frame, or no item (will run the current frame)");
    99                 } else {
    100                         Javascript2.runFrame(item.getChild(), true);
    101                 }
    102         }
    103103       
    104         public static Object eval(String code) {
    105                 try {
    106                 return scriptEngine.eval(code);
    107         } catch (ScriptException e) {
    108                 e.printStackTrace();
    109         }
    110                 return null;
    111         }
     104    private static synchronized void runFrameFollow(Frame frame) throws Exception {
     105        Javascript2 js = new Javascript2(frame, true);
     106        js.runFrame(frame,true);       
     107    }
    112108       
    113         private static synchronized void runFrame(Frame frame, boolean followLinks) throws Exception {
    114                 Javascript2 js = new Javascript2(frame, followLinks);
    115                 try {
    116                 try {
    117                 scriptEngine.eval(js.toString());
    118             } catch (ScriptException e) {
    119                         js.handleError(e.getMessage(), e.getLineNumber());
    120             } catch (RuntimeException e) {
    121                 // there doesn't seem to be a way to safely get the lineNumber on which the error occurred
    122                 // so as a workaround we just parse the exception
    123                 if(e.getCause() == null) {
    124                         throw e;
    125                 }
    126                 String detail = e.getCause().getStackTrace()[1].toString();
    127                 int lastColon = detail.lastIndexOf(':');
    128                 int lastBracket = detail.lastIndexOf(')');
    129                 int lineNumber;
    130                 if(lastColon == -1 || lastBracket == -1) {
    131                         lineNumber = -1;
    132                 } else {
    133                         lineNumber = Integer.parseInt(detail.substring(lastColon + 1, lastBracket));
    134                 }
    135                 js.handleError(e.getMessage(), lineNumber);
    136             }
    137                 } catch(Exception e) {
    138                         js.handleError(null, -1);
    139                         System.out.println(js.toString());
    140                         e.printStackTrace();
    141                 }
    142         }
    143        
    144         private static final class CodeLine {
    145                 public Text item;
    146                 public int line;
    147                 public String source;
    148                
    149                 public CodeLine(Text item, int line, String source) {
    150                         this.item = item;
    151                         this.line = line;
    152                         this.source = source;
    153                 }
    154                
    155                 public String toString() {
    156                         return line + ": " + source;
    157                 }
    158         }
    159        
    160         private List<Frame> seen = new LinkedList<Frame>();
    161         private List<CodeLine> lines = new LinkedList<CodeLine>();
    162         private StringBuffer sb = new StringBuffer();
    163         private Javascript2(Frame frame, boolean followLinks) {
    164                 this.parseFrame(frame, followLinks);
    165         }
    166        
    167         private void parseFrame(Frame frame, boolean followLinks) {
    168                 if(frame == null) {
    169                         return;
    170                 }
    171                
    172                 // make sure we don't get into an infinite loop
    173                 // TODO: find a smarter way to do this that allows reusing frames but still stops infinite loops?
    174                 seen.add(frame);
    175                
    176                 // get all items on the frame
    177                 List<Item> y_ordered_items = (List<Item>)frame.getItems();
    178                 // remove the title item
    179                 y_ordered_items.remove(frame.getTitleItem());
    180                
    181                 XGroupItem toplevel_xgroup = new XGroupItem(frame,y_ordered_items);
    182                 // ... following on from Steps 1 and 2 in the Constructor in XGroupItem ...
    183                
    184                 // Step 3: Reposition any 'out-of-flow' XGroupItems
    185                 toplevel_xgroup.repositionOutOfFlowGroups(toplevel_xgroup);
    186                
    187                 // Step 4: Now add in the remaining (nested) XGroupItems
    188                 List<XGroupItem> grouped_item_list = toplevel_xgroup.getGroupedItemList();
    189                 toplevel_xgroup.mapInXGroupItemsRecursive(grouped_item_list);
    190        
    191                 // Finally, retrieve linear list of all Items, (ordered, Y by X, allowing for overlap, nested-boxing, and arrow flow)
    192                 List<Item> overlapping_y_ordered_items = toplevel_xgroup.getYXOverlappingItemList(true);       
    193                
    194                 // Loop through the items looking for code and links to new frames
    195                 for(Item i : overlapping_y_ordered_items) {
    196                         if(followLinks && i.hasLink()) {
    197                                 Frame child = i.getChild();
    198                                 if(child != null && !seen.contains(child)) {
    199                                         this.parseFrame(child, true);
    200                                 }
    201                         }
    202                         if(i instanceof Text && !i.isAnnotation()) {
    203                                 String text = ((Text)i).getText();
    204                                 if (i == org.expeditee.io.flowlayout.XGroupItem.GROUPSEP_START) {
    205                                         text = "{";
    206                                 }
    207                                 else if (i == org.expeditee.io.flowlayout.XGroupItem.GROUPSEP_END) {
    208                                                 text = "}";
    209                                 }
    210                                
    211                                 int lineNumber = 0;
    212                                 for(String line : text.trim().split("[\\n\\r]+")) {
    213                                         sb.append(line).append("\n");
    214                                         lines.add(new CodeLine((Text)i, lineNumber++, line));
    215                                 }
    216                         }
    217                 }
    218         }
    219        
    220         private void handleError(String message, int lineNumber) throws Exception {
    221                 // negative line number bad
    222                 if(lineNumber < 0) {
    223                         MessageBay.errorMessage("Failed to determine the line on which the error occurred");
    224                         return;
    225                 }
    226                 // if for some reason the error is after the end of the code, assume it should be the last line
    227                 if(lineNumber > this.lines.size()) {
    228                         lineNumber = this.lines.size();
    229                 }
    230                 CodeLine cl = this.lines.get(lineNumber - 1);
    231                 Frame errorSourceFrame = cl.item.getParent();
    232                 if(errorSourceFrame == null) {
    233                         MessageBay.errorMessage("Failed to find frame on which the error occurred");
    234                         return;
    235                 }
    236                 Frame errorFrame;
    237                 String title = "Error parsing \"" + errorSourceFrame.getTitle() + "\" (" + errorSourceFrame.getName() + ")";
    238                 if(FrameIO.canAccessFrameset(ERROR_FRAMESET)) {
    239                         errorFrame = FrameIO.CreateFrame(ERROR_FRAMESET, title, null);
    240                 } else {
    241                         errorFrame = FrameIO.CreateFrameset(ERROR_FRAMESET, FrameIO.FRAME_PATH);
    242                         errorFrame.setTitle(title);
    243                 }
    244                 Collection<Item> toAdd = errorSourceFrame.getAllItems();
    245                 toAdd.remove(errorSourceFrame.getTitleItem());
    246                 toAdd.remove(cl.item);
    247                 errorFrame.addAllItems(ItemUtils.CopyItems(toAdd));
    248                 String errorItemText = cl.item.getText().trim();
    249                 String[] errorItemLines = errorItemText.split("[\\n\\r]+");
    250                 int errorLinePos = 0;
    251                 int x = cl.item.getX();
    252                 int y = cl.item.getY();
    253                 if(cl.line != 0) {
    254                 for(int i = 0; i < cl.line; i++) {
    255                         errorLinePos += errorItemLines[i].length();
    256                 }
    257                 Text beforeErrorItem = errorFrame.addText(x, y,
    258                                 errorItemText.substring(0, errorLinePos), null);
    259                 y = beforeErrorItem.getY() + beforeErrorItem.getBoundsHeight();
    260                 }
    261                 Text errorItem;
    262                 errorItem = errorFrame.addText(x, y, errorItemLines[cl.line], null);
    263                 errorItem.setBackgroundColor(Color.RED);
    264                 for(String line : message.split("[\\n\\r]+")) {
    265                         errorItem.setTooltip("text: " + line);
    266                 }
    267                 errorItem.setTooltip("font: " + Text.MONOSPACED_FONT);
    268                 errorItem.setTooltip("width: " + 80 * 12);
    269                 errorLinePos += errorItemLines[cl.line].length();
    270                 if(++errorLinePos < errorItemText.length()) {
    271                         errorFrame.addText(cl.item.getX(), errorItem.getY() + errorItem.getBoundsHeight(),
    272                                         errorItemText.substring(errorLinePos + 1), null);
    273                 }
    274                 errorFrame.change();
    275                 FrameIO.SaveFrame(errorFrame);
    276                 MessageBay.displayMessage("Script failed at line " + lineNumber +  " - `" + cl.source + "`",
    277                                 errorFrame.getName(), MessageBay.ERROR_COLOR, true, null);
    278                 FrameUtils.DisplayFrame(errorFrame, true, true);
    279         }
    280        
    281         public String toString() {
    282                 return this.sb.toString();
    283         }
    284109
     110    private Javascript2(Frame frame, boolean followLinks) {
     111        super(frame,followLinks);
     112    }
     113   
    285114}
  • trunk/src/org/expeditee/items/widgets/JSWidget.java

    r919 r1078  
    4343public class JSWidget extends DataFrameWidget implements JSThreadable {
    4444       
    45         private static final Object global = Javascript2.eval("new Object()");
     45        private static Object global = null;
    4646       
    4747        // a method to run that will set up and return the root JComponent for this Widget
     
    6868        private JSWidget(Text source, int width, int height, String init, String save, String load) throws Exception {
    6969                super(source, new JPanel(new BorderLayout()), -1, width, -1, -1, height, -1);
     70                if (global == null) {
     71                    global = Javascript2.eval("new Object()");
     72                }
    7073                this.init = init;
    7174                this.save = save;
Note: See TracChangeset for help on using the changeset viewer.