mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-01 12:24:14 +01:00
Removing some Processing stuff that we don't need.
Moving the Arduino Fio up in the boards menu.
This commit is contained in:
parent
e5d56a1e59
commit
5d54fbf70b
@ -1334,7 +1334,7 @@ public class Sketch {
|
||||
|
||||
if (libFolder != null && !importedLibraries.contains(libFolder)) {
|
||||
importedLibraries.add(libFolder);
|
||||
classPath += Compiler.contentsToClassPath(libFolder);
|
||||
//classPath += Compiler.contentsToClassPath(libFolder);
|
||||
libraryPath += File.pathSeparator + libFolder.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
@ -1565,7 +1565,6 @@ public class Sketch {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
size(appletFolder.getPath(), foundName);
|
||||
upload(appletFolder.getPath(), foundName, verbose);
|
||||
|
||||
return true;
|
||||
@ -1680,124 +1679,6 @@ public class Sketch {
|
||||
}
|
||||
|
||||
|
||||
protected void addManifest(ZipOutputStream zos) throws IOException {
|
||||
ZipEntry entry = new ZipEntry("META-INF/MANIFEST.MF");
|
||||
zos.putNextEntry(entry);
|
||||
|
||||
String contents =
|
||||
"Manifest-Version: 1.0\n" +
|
||||
"Created-By: Processing " + Base.VERSION_NAME + "\n" +
|
||||
"Main-Class: " + name + "\n"; // TODO not package friendly
|
||||
zos.write(contents.getBytes());
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Slurps up .class files from a colon (or semicolon on windows)
|
||||
* separated list of paths and adds them to a ZipOutputStream.
|
||||
*/
|
||||
protected void packClassPathIntoZipFile(String path,
|
||||
ZipOutputStream zos,
|
||||
HashMap<String,Object> zipFileContents)
|
||||
throws IOException {
|
||||
String[] pieces = PApplet.split(path, File.pathSeparatorChar);
|
||||
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
if (pieces[i].length() == 0) continue;
|
||||
|
||||
// is it a jar file or directory?
|
||||
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
||||
pieces[i].toLowerCase().endsWith(".zip")) {
|
||||
try {
|
||||
ZipFile file = new ZipFile(pieces[i]);
|
||||
Enumeration<?> entries = file.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
if (entry.isDirectory()) {
|
||||
// actually 'continue's for all dir entries
|
||||
|
||||
} else {
|
||||
String entryName = entry.getName();
|
||||
// ignore contents of the META-INF folders
|
||||
if (entryName.indexOf("META-INF") == 0) continue;
|
||||
|
||||
// don't allow duplicate entries
|
||||
if (zipFileContents.get(entryName) != null) continue;
|
||||
zipFileContents.put(entryName, new Object());
|
||||
|
||||
ZipEntry entree = new ZipEntry(entryName);
|
||||
|
||||
zos.putNextEntry(entree);
|
||||
byte buffer[] = new byte[(int) entry.getSize()];
|
||||
InputStream is = file.getInputStream(entry);
|
||||
|
||||
int offset = 0;
|
||||
int remaining = buffer.length;
|
||||
while (remaining > 0) {
|
||||
int count = is.read(buffer, offset, remaining);
|
||||
offset += count;
|
||||
remaining -= count;
|
||||
}
|
||||
|
||||
zos.write(buffer);
|
||||
zos.flush();
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error in file " + pieces[i]);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else { // not a .jar or .zip, prolly a directory
|
||||
File dir = new File(pieces[i]);
|
||||
// but must be a dir, since it's one of several paths
|
||||
// just need to check if it exists
|
||||
if (dir.exists()) {
|
||||
packClassPathIntoZipFileRecursive(dir, null, zos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Continue the process of magical exporting. This function
|
||||
* can be called recursively to walk through folders looking
|
||||
* for more goodies that will be added to the ZipOutputStream.
|
||||
*/
|
||||
static protected void packClassPathIntoZipFileRecursive(File dir,
|
||||
String sofar,
|
||||
ZipOutputStream zos)
|
||||
throws IOException {
|
||||
String files[] = dir.list();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
// ignore . .. and .DS_Store
|
||||
if (files[i].charAt(0) == '.') continue;
|
||||
|
||||
File sub = new File(dir, files[i]);
|
||||
String nowfar = (sofar == null) ?
|
||||
files[i] : (sofar + "/" + files[i]);
|
||||
|
||||
if (sub.isDirectory()) {
|
||||
packClassPathIntoZipFileRecursive(sub, nowfar, zos);
|
||||
|
||||
} else {
|
||||
// don't add .jar and .zip files, since they only work
|
||||
// inside the root, and they're unpacked
|
||||
if (!files[i].toLowerCase().endsWith(".jar") &&
|
||||
!files[i].toLowerCase().endsWith(".zip") &&
|
||||
files[i].charAt(0) != '.') {
|
||||
ZipEntry entry = new ZipEntry(nowfar);
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(Base.loadBytesRaw(sub));
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make sure the sketch hasn't been moved or deleted by some
|
||||
* nefarious user. If they did, try to re-create it and save.
|
||||
|
@ -493,167 +493,4 @@ public class Compiler implements MessageConsumer {
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a folder, return a list of absolute paths to all jar or zip files
|
||||
* inside that folder, separated by pathSeparatorChar.
|
||||
*
|
||||
* This will prepend a colon (or whatever the path separator is)
|
||||
* so that it can be directly appended to another path string.
|
||||
*
|
||||
* As of 0136, this will no longer add the root folder as well.
|
||||
*
|
||||
* This function doesn't bother checking to see if there are any .class
|
||||
* files in the folder or within a subfolder.
|
||||
*/
|
||||
static public String contentsToClassPath(File folder) {
|
||||
if (folder == null) return "";
|
||||
|
||||
StringBuffer abuffer = new StringBuffer();
|
||||
String sep = System.getProperty("path.separator");
|
||||
|
||||
try {
|
||||
String path = folder.getCanonicalPath();
|
||||
|
||||
// disabled as of 0136
|
||||
// add the folder itself in case any unzipped files
|
||||
// abuffer.append(sep);
|
||||
// abuffer.append(path);
|
||||
//
|
||||
// When getting the name of this folder, make sure it has a slash
|
||||
// after it, so that the names of sub-items can be added.
|
||||
if (!path.endsWith(File.separator)) {
|
||||
path += File.separator;
|
||||
}
|
||||
|
||||
String list[] = folder.list();
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
// Skip . and ._ files. Prior to 0125p3, .jar files that had
|
||||
// OS X AppleDouble files associated would cause trouble.
|
||||
if (list[i].startsWith(".")) continue;
|
||||
|
||||
if (list[i].toLowerCase().endsWith(".jar") ||
|
||||
list[i].toLowerCase().endsWith(".zip")) {
|
||||
abuffer.append(sep);
|
||||
abuffer.append(path);
|
||||
abuffer.append(list[i]);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(); // this would be odd
|
||||
}
|
||||
//System.out.println("included path is " + abuffer.toString());
|
||||
//packageListFromClassPath(abuffer.toString()); // WHY?
|
||||
return abuffer.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A classpath, separated by the path separator, will contain
|
||||
* a series of .jar/.zip files or directories containing .class
|
||||
* files, or containing subdirectories that have .class files.
|
||||
*
|
||||
* @param path the input classpath
|
||||
* @return array of possible package names
|
||||
*/
|
||||
static public String[] packageListFromClassPath(String path) {
|
||||
Hashtable table = new Hashtable();
|
||||
String pieces[] =
|
||||
PApplet.split(path, File.pathSeparatorChar);
|
||||
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
//System.out.println("checking piece '" + pieces[i] + "'");
|
||||
if (pieces[i].length() == 0) continue;
|
||||
|
||||
if (pieces[i].toLowerCase().endsWith(".jar") ||
|
||||
pieces[i].toLowerCase().endsWith(".zip")) {
|
||||
//System.out.println("checking " + pieces[i]);
|
||||
packageListFromZip(pieces[i], table);
|
||||
|
||||
} else { // it's another type of file or directory
|
||||
File dir = new File(pieces[i]);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
packageListFromFolder(dir, null, table);
|
||||
//importCount = magicImportsRecursive(dir, null,
|
||||
// table);
|
||||
//imports, importCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
int tableCount = table.size();
|
||||
String output[] = new String[tableCount];
|
||||
int index = 0;
|
||||
Enumeration e = table.keys();
|
||||
while (e.hasMoreElements()) {
|
||||
output[index++] = ((String) e.nextElement()).replace('/', '.');
|
||||
}
|
||||
//System.arraycopy(imports, 0, output, 0, importCount);
|
||||
//PApplet.printarr(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
static private void packageListFromZip(String filename, Hashtable table) {
|
||||
try {
|
||||
ZipFile file = new ZipFile(filename);
|
||||
Enumeration entries = file.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
|
||||
if (!entry.isDirectory()) {
|
||||
String name = entry.getName();
|
||||
|
||||
if (name.endsWith(".class")) {
|
||||
int slash = name.lastIndexOf('/');
|
||||
if (slash == -1) continue;
|
||||
|
||||
String pname = name.substring(0, slash);
|
||||
if (table.get(pname) == null) {
|
||||
table.put(pname, new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Ignoring " + filename + " (" + e.getMessage() + ")");
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make list of package names by traversing a directory hierarchy.
|
||||
* Each time a class is found in a folder, add its containing set
|
||||
* of folders to the package list. If another folder is found,
|
||||
* walk down into that folder and continue.
|
||||
*/
|
||||
static private void packageListFromFolder(File dir, String sofar,
|
||||
Hashtable table) {
|
||||
//String imports[],
|
||||
//int importCount) {
|
||||
//System.err.println("checking dir '" + dir + "'");
|
||||
boolean foundClass = false;
|
||||
String files[] = dir.list();
|
||||
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].equals(".") || files[i].equals("..")) continue;
|
||||
|
||||
File sub = new File(dir, files[i]);
|
||||
if (sub.isDirectory()) {
|
||||
String nowfar =
|
||||
(sofar == null) ? files[i] : (sofar + "." + files[i]);
|
||||
packageListFromFolder(sub, nowfar, table);
|
||||
//System.out.println(nowfar);
|
||||
//imports[importCount++] = nowfar;
|
||||
//importCount = magicImportsRecursive(sub, nowfar,
|
||||
// imports, importCount);
|
||||
} else if (!foundClass) { // if no classes found in this folder yet
|
||||
if (files[i].endsWith(".class")) {
|
||||
//System.out.println("unique class: " + files[i] + " for " + sofar);
|
||||
table.put(sofar, new Object());
|
||||
foundClass = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,404 +0,0 @@
|
||||
/*
|
||||
* @(#)EventThread.java 1.4 03/01/23
|
||||
*
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||
* modify and redistribute this software in source and binary code form,
|
||||
* provided that i) this copyright notice and license appear on all copies of
|
||||
* the software; and ii) Licensee does not utilize the software in a manner
|
||||
* which is disparaging to Sun.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
|
||||
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
|
||||
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
|
||||
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
|
||||
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* This software is not designed or intended for use in on-line control of
|
||||
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||
* the design, construction, operation or maintenance of any nuclear
|
||||
* facility. Licensee represents and warrants that it will not use or
|
||||
* redistribute the Software for such purposes.
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.jdi.*;
|
||||
import com.sun.jdi.event.*;
|
||||
import com.sun.jdi.request.*;
|
||||
|
||||
/**
|
||||
* This class processes incoming JDI events and displays them
|
||||
*
|
||||
* @version @(#) EventThread.java 1.4 03/01/23 23:33:38
|
||||
* @author Robert Field
|
||||
*/
|
||||
public class EventThread extends Thread {
|
||||
|
||||
private final Runner parent;
|
||||
private final VirtualMachine vm; // Running VM
|
||||
private final String[] excludes; // Packages to exclude
|
||||
private final PrintWriter writer; // Where output goes
|
||||
|
||||
static String nextBaseIndent = ""; // Starting indent for next thread
|
||||
|
||||
private boolean connected = true; // Connected to VM
|
||||
private boolean vmDied = true; // VMDeath occurred
|
||||
|
||||
// Maps ThreadReference to ThreadTrace instances
|
||||
private Map traceMap = new HashMap();
|
||||
|
||||
|
||||
public EventThread(Runner parent, VirtualMachine vm, String[] excludes, PrintWriter writer) {
|
||||
super("event-handler");
|
||||
this.parent = parent;
|
||||
this.vm = vm;
|
||||
this.excludes = excludes;
|
||||
this.writer = writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the event handling thread.
|
||||
* As long as we are connected, get event sets off
|
||||
* the queue and dispatch the events within them.
|
||||
*/
|
||||
public void run() {
|
||||
EventQueue queue = vm.eventQueue();
|
||||
while (connected) {
|
||||
try {
|
||||
EventSet eventSet = queue.remove();
|
||||
EventIterator it = eventSet.eventIterator();
|
||||
while (it.hasNext()) {
|
||||
handleEvent(it.nextEvent());
|
||||
}
|
||||
eventSet.resume();
|
||||
} catch (InterruptedException exc) {
|
||||
// Ignore
|
||||
} catch (VMDisconnectedException discExc) {
|
||||
handleDisconnectedException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the desired event requests, and enable
|
||||
* them so that we will get events.
|
||||
* @param excludes Class patterns for which we don't want events
|
||||
* @param watchFields Do we want to watch assignments to fields
|
||||
*/
|
||||
public void setEventRequests(boolean watchFields) {
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
|
||||
// VMDeathRequest deathReq = mgr.createVMDeathRequest();
|
||||
// deathReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
// deathReq.enable();
|
||||
|
||||
// get only the uncaught exceptions
|
||||
ExceptionRequest excReq = mgr.createExceptionRequest(null, false, true);
|
||||
// this version reports all exceptions, caught or uncaught
|
||||
//ExceptionRequest excReq = mgr.createExceptionRequest(null, true, true);
|
||||
// suspend so we can step
|
||||
excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
excReq.enable();
|
||||
|
||||
/*
|
||||
MethodEntryRequest menr = mgr.createMethodEntryRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
menr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
menr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
menr.enable();
|
||||
|
||||
MethodExitRequest mexr = mgr.createMethodExitRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
mexr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
mexr.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
mexr.enable();
|
||||
|
||||
ThreadDeathRequest tdr = mgr.createThreadDeathRequest();
|
||||
// Make sure we sync on thread death
|
||||
tdr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
tdr.enable();
|
||||
*/
|
||||
|
||||
// turn on field watching (waaay slow)
|
||||
/*
|
||||
// if (watchFields) {
|
||||
ClassPrepareRequest cpr = mgr.createClassPrepareRequest();
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
cpr.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
cpr.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
cpr.enable();
|
||||
// }
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* This class keeps context on events in one thread.
|
||||
* In this implementation, context is the indentation prefix.
|
||||
*/
|
||||
class ThreadTrace {
|
||||
final ThreadReference thread;
|
||||
final String baseIndent;
|
||||
static final String threadDelta = " ";
|
||||
StringBuffer indent;
|
||||
|
||||
ThreadTrace(ThreadReference thread) {
|
||||
this.thread = thread;
|
||||
this.baseIndent = nextBaseIndent;
|
||||
indent = new StringBuffer(baseIndent);
|
||||
nextBaseIndent += threadDelta;
|
||||
println("====== " + thread.name() + " ======");
|
||||
}
|
||||
|
||||
private void println(String str) {
|
||||
if (writer != null) {
|
||||
writer.print(indent);
|
||||
writer.println(str);
|
||||
writer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void methodEntryEvent(MethodEntryEvent event) {
|
||||
println(event.method().name() + " -- "
|
||||
+ event.method().declaringType().name());
|
||||
indent.append("| ");
|
||||
}
|
||||
|
||||
void methodExitEvent(MethodExitEvent event) {
|
||||
indent.setLength(indent.length()-2);
|
||||
}
|
||||
|
||||
void fieldWatchEvent(ModificationWatchpointEvent event) {
|
||||
Field field = event.field();
|
||||
Value value = event.valueToBe();
|
||||
println(" " + field.name() + " = " + value);
|
||||
}
|
||||
|
||||
void exceptionEvent(ExceptionEvent event) {
|
||||
println("Exception: " + event.exception() +
|
||||
" catch: " + event.catchLocation());
|
||||
// System.out.println("Exception: " + event.exception() +
|
||||
// " catch: " + event.catchLocation());
|
||||
|
||||
// Step to the catch
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
StepRequest req = mgr.createStepRequest(thread,
|
||||
StepRequest.STEP_MIN,
|
||||
StepRequest.STEP_INTO);
|
||||
req.addCountFilter(1); // next step only
|
||||
req.setSuspendPolicy(EventRequest.SUSPEND_ALL);
|
||||
req.enable();
|
||||
}
|
||||
|
||||
// Step to exception catch
|
||||
void stepEvent(StepEvent event) {
|
||||
// Adjust call depth
|
||||
int cnt = 0;
|
||||
indent = new StringBuffer(baseIndent);
|
||||
try {
|
||||
cnt = thread.frameCount();
|
||||
} catch (IncompatibleThreadStateException exc) {
|
||||
}
|
||||
while (cnt-- > 0) {
|
||||
indent.append("| ");
|
||||
}
|
||||
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
mgr.deleteEventRequest(event.request());
|
||||
}
|
||||
|
||||
void threadDeathEvent(ThreadDeathEvent event) {
|
||||
indent = new StringBuffer(baseIndent);
|
||||
println("====== " + thread.name() + " end ======");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ThreadTrace instance for the specified thread,
|
||||
* creating one if needed.
|
||||
*/
|
||||
ThreadTrace threadTrace(ThreadReference thread) {
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(thread);
|
||||
if (trace == null) {
|
||||
trace = new ThreadTrace(thread);
|
||||
traceMap.put(thread, trace);
|
||||
}
|
||||
return trace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch incoming events
|
||||
*/
|
||||
private void handleEvent(Event event) {
|
||||
if (event instanceof ExceptionEvent) {
|
||||
exceptionEvent((ExceptionEvent)event);
|
||||
} else if (event instanceof ModificationWatchpointEvent) {
|
||||
fieldWatchEvent((ModificationWatchpointEvent)event);
|
||||
} else if (event instanceof MethodEntryEvent) {
|
||||
methodEntryEvent((MethodEntryEvent)event);
|
||||
} else if (event instanceof MethodExitEvent) {
|
||||
methodExitEvent((MethodExitEvent)event);
|
||||
} else if (event instanceof StepEvent) {
|
||||
stepEvent((StepEvent)event);
|
||||
} else if (event instanceof ThreadDeathEvent) {
|
||||
threadDeathEvent((ThreadDeathEvent)event);
|
||||
} else if (event instanceof ClassPrepareEvent) {
|
||||
classPrepareEvent((ClassPrepareEvent)event);
|
||||
} else if (event instanceof VMStartEvent) {
|
||||
vmStartEvent((VMStartEvent)event);
|
||||
} else if (event instanceof VMDeathEvent) {
|
||||
vmDeathEvent((VMDeathEvent)event);
|
||||
} else if (event instanceof VMDisconnectEvent) {
|
||||
vmDisconnectEvent((VMDisconnectEvent)event);
|
||||
} else {
|
||||
throw new Error("Unexpected event type");
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* A VMDisconnectedException has happened while dealing with
|
||||
* another event. We need to flush the event queue, dealing only
|
||||
* with exit events (VMDeath, VMDisconnect) so that we terminate
|
||||
* correctly.
|
||||
*/
|
||||
synchronized void handleDisconnectedException() {
|
||||
EventQueue queue = vm.eventQueue();
|
||||
while (connected) {
|
||||
try {
|
||||
EventSet eventSet = queue.remove();
|
||||
EventIterator iter = eventSet.eventIterator();
|
||||
while (iter.hasNext()) {
|
||||
Event event = iter.nextEvent();
|
||||
if (event instanceof VMDeathEvent) {
|
||||
vmDeathEvent((VMDeathEvent)event);
|
||||
} else if (event instanceof VMDisconnectEvent) {
|
||||
vmDisconnectEvent((VMDisconnectEvent)event);
|
||||
}
|
||||
}
|
||||
eventSet.resume(); // Resume the VM
|
||||
} catch (InterruptedException exc) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void vmStartEvent(VMStartEvent event) {
|
||||
if (writer != null) writer.println("-- VM Started --");
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void methodEntryEvent(MethodEntryEvent event) {
|
||||
threadTrace(event.thread()).methodEntryEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void methodExitEvent(MethodExitEvent event) {
|
||||
threadTrace(event.thread()).methodExitEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void stepEvent(StepEvent event) {
|
||||
threadTrace(event.thread()).stepEvent(event);
|
||||
}
|
||||
|
||||
// Forward event for thread specific processing
|
||||
private void fieldWatchEvent(ModificationWatchpointEvent event) {
|
||||
threadTrace(event.thread()).fieldWatchEvent(event);
|
||||
}
|
||||
|
||||
void threadDeathEvent(ThreadDeathEvent event) {
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(event.thread());
|
||||
if (trace != null) { // only want threads we care about
|
||||
trace.threadDeathEvent(event); // Forward event
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A new class has been loaded.
|
||||
* Set watchpoints on each of its fields
|
||||
*/
|
||||
private void classPrepareEvent(ClassPrepareEvent event) {
|
||||
// System.out.println(event);
|
||||
// List list = event.referenceType().methodsByName("stop");
|
||||
// Object o = list.get(0);
|
||||
// System.out.println("stop methods = " + list);
|
||||
// System.out.println(o.getClass());
|
||||
|
||||
EventRequestManager mgr = vm.eventRequestManager();
|
||||
List fields = event.referenceType().visibleFields();
|
||||
for (Iterator it = fields.iterator(); it.hasNext(); ) {
|
||||
Field field = (Field)it.next();
|
||||
ModificationWatchpointRequest req =
|
||||
mgr.createModificationWatchpointRequest(field);
|
||||
for (int i=0; i<excludes.length; ++i) {
|
||||
req.addClassExclusionFilter(excludes[i]);
|
||||
}
|
||||
req.setSuspendPolicy(EventRequest.SUSPEND_NONE);
|
||||
req.enable();
|
||||
}
|
||||
}
|
||||
|
||||
private void exceptionEvent(ExceptionEvent event) {
|
||||
// com.sun.jdi.ObjectReference or = event.exception();
|
||||
// System.out.println("exceptionEvent() fired " + or);
|
||||
// System.out.println("catch location " + event.catchLocation());
|
||||
|
||||
parent.exception(event);
|
||||
|
||||
/*
|
||||
ObjectReference or = event.exception();
|
||||
ThreadReference thread = event.thread();
|
||||
ThreadTrace trace = (ThreadTrace)traceMap.get(thread);
|
||||
if (trace != null) { // only want threads we care about
|
||||
trace.exceptionEvent(event); // Forward event
|
||||
}
|
||||
try {
|
||||
List frames = thread.frames();
|
||||
for (Object item : frames) {
|
||||
System.out.println("got " + item);
|
||||
}
|
||||
//System.out.println(frames);
|
||||
} catch (IncompatibleThreadStateException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void vmDeathEvent(VMDeathEvent event) {
|
||||
//System.err.println("vm is dead! dead!");
|
||||
vmDied = true;
|
||||
if (writer != null) {
|
||||
writer.println("-- The application exited --");
|
||||
}
|
||||
}
|
||||
|
||||
public void vmDisconnectEvent(VMDisconnectEvent event) {
|
||||
connected = false;
|
||||
if (!vmDied) {
|
||||
if (writer != null) {
|
||||
writer.println("-- The application has been disconnected --");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,659 +0,0 @@
|
||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-09 Ben Fry and Casey Reas
|
||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import processing.app.*;
|
||||
import processing.app.preproc.PdePreprocessor;
|
||||
import processing.core.*;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import com.sun.jdi.*;
|
||||
import com.sun.jdi.connect.*;
|
||||
import com.sun.jdi.event.ExceptionEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Runs a compiled sketch. As of release 0136, all sketches are run externally
|
||||
* to the environment so that a debugging interface can be used. This opens up
|
||||
* future options for a decent debugger, but in the meantime fixes several
|
||||
* problems with output and error streams, messages getting lost on Mac OS X,
|
||||
* the run/stop buttons not working, libraries not shutting down, exceptions
|
||||
* not coming through, exceptions being printed twice, having to force quit
|
||||
* if you make a bad while() loop, and so on.
|
||||
*/
|
||||
public class Runner implements MessageConsumer {
|
||||
|
||||
private boolean presenting;
|
||||
|
||||
// Object that listens for error messages or exceptions.
|
||||
protected RunnerListener listener;
|
||||
|
||||
// Running remote VM
|
||||
protected VirtualMachine vm;
|
||||
|
||||
// Thread transferring remote error stream to our error stream
|
||||
protected Thread errThread = null;
|
||||
|
||||
// Thread transferring remote output stream to our output stream
|
||||
protected Thread outThread = null;
|
||||
|
||||
// Mode for tracing the Trace program (default= 0 off)
|
||||
protected int debugTraceMode = 0;
|
||||
|
||||
// Do we want to watch assignments to fields
|
||||
protected boolean watchFields = false;
|
||||
|
||||
// Class patterns for which we don't want events
|
||||
protected String[] excludes = {
|
||||
"java.*", "javax.*", "sun.*", "com.sun.*",
|
||||
"apple.*",
|
||||
"processing.*"
|
||||
};
|
||||
|
||||
protected RunnerException exception;
|
||||
//private PrintStream leechErr;
|
||||
|
||||
protected Editor editor;
|
||||
protected Sketch sketch;
|
||||
private String appletClassName;
|
||||
|
||||
|
||||
public Runner(RunnerListener listener, Sketch sketch) {
|
||||
this.listener = listener;
|
||||
this.sketch = sketch;
|
||||
|
||||
if (listener instanceof Editor) {
|
||||
this.editor = (Editor) listener;
|
||||
// } else {
|
||||
// System.out.println("actually it's a " + listener.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void launch(String appletClassName, boolean presenting) {
|
||||
this.appletClassName = appletClassName;
|
||||
this.presenting = presenting;
|
||||
|
||||
// TODO entire class is a total mess as of release 0136.
|
||||
// This will be cleaned up significantly over the next couple months.
|
||||
|
||||
// all params have to be stored as separate items,
|
||||
// so a growable array needs to be used. i.e. -Xms128m -Xmx1024m
|
||||
// will throw an error if it's shoved into a single array element
|
||||
//Vector params = new Vector();
|
||||
|
||||
// get around Apple's Java 1.5 bugs
|
||||
//params.add("/System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Commands/java");
|
||||
//params.add("java");
|
||||
//System.out.println("0");
|
||||
|
||||
String[] machineParamList = getMachineParams();
|
||||
String[] sketchParamList = getSketchParams();
|
||||
|
||||
vm = launchVirtualMachine(machineParamList, sketchParamList);
|
||||
if (vm != null) {
|
||||
generateTrace(null);
|
||||
// try {
|
||||
// generateTrace(new PrintWriter("/Users/fry/Desktop/output.txt"));
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected String[] getMachineParams() {
|
||||
ArrayList<String> params = new ArrayList<String>();
|
||||
|
||||
//params.add("-Xint"); // interpreted mode
|
||||
//params.add("-Xprof"); // profiler
|
||||
//params.add("-Xaprof"); // allocation profiler
|
||||
//params.add("-Xrunhprof:cpu=samples"); // old-style profiler
|
||||
|
||||
// TODO change this to use run.args = true, run.args.0, run.args.1, etc.
|
||||
// so that spaces can be included in the arg names
|
||||
String options = Preferences.get("run.options");
|
||||
if (options.length() > 0) {
|
||||
String pieces[] = PApplet.split(options, ' ');
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
String p = pieces[i].trim();
|
||||
if (p.length() > 0) {
|
||||
params.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// params.add("-Djava.ext.dirs=nuffing");
|
||||
|
||||
if (Preferences.getBoolean("run.options.memory")) {
|
||||
params.add("-Xms" + Preferences.get("run.options.memory.initial") + "m");
|
||||
params.add("-Xmx" + Preferences.get("run.options.memory.maximum") + "m");
|
||||
}
|
||||
|
||||
if (Base.isMacOS()) {
|
||||
params.add("-Xdock:name=" + appletClassName);
|
||||
// params.add("-Dcom.apple.mrj.application.apple.menu.about.name=" +
|
||||
// sketch.getMainClassName());
|
||||
}
|
||||
// sketch.libraryPath might be ""
|
||||
// librariesClassPath will always have sep char prepended
|
||||
params.add("-Djava.library.path=" +
|
||||
sketch.getLibraryPath() +
|
||||
File.pathSeparator +
|
||||
System.getProperty("java.library.path"));
|
||||
|
||||
params.add("-cp");
|
||||
params.add(sketch.getClassPath());
|
||||
// params.add(sketch.getClassPath() +
|
||||
// File.pathSeparator +
|
||||
// Base.librariesClassPath);
|
||||
|
||||
//PApplet.println(PApplet.split(sketch.classPath, ':'));
|
||||
|
||||
String outgoing[] = new String[params.size()];
|
||||
params.toArray(outgoing);
|
||||
|
||||
//PApplet.println(outgoing);
|
||||
// PApplet.println(PApplet.split(outgoing[0], ":"));
|
||||
// PApplet.println();
|
||||
// PApplet.println("class path");
|
||||
// PApplet.println(PApplet.split(outgoing[2], ":"));
|
||||
|
||||
return outgoing;
|
||||
//return (String[]) params.toArray();
|
||||
|
||||
// System.out.println("sketch class path");
|
||||
// PApplet.println(PApplet.split(sketch.classPath, ';'));
|
||||
// System.out.println();
|
||||
// System.out.println("libraries class path");
|
||||
// PApplet.println(PApplet.split(Base.librariesClassPath, ';'));
|
||||
// System.out.println();
|
||||
}
|
||||
|
||||
|
||||
protected String[] getSketchParams() {
|
||||
ArrayList<String> params = new ArrayList<String>();
|
||||
|
||||
// It's dangerous to add your own main() to your code,
|
||||
// but if you've done it, we'll respect your right to hang yourself.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=1446
|
||||
if (PdePreprocessor.foundMain) {
|
||||
params.add(appletClassName);
|
||||
|
||||
} else {
|
||||
params.add("processing.core.PApplet");
|
||||
|
||||
// If there was a saved location (this guy has been run more than once)
|
||||
// then the location will be set to the last position of the sketch window.
|
||||
// This will be passed to the PApplet runner using something like
|
||||
// --location=30,20
|
||||
// Otherwise, the editor location will be passed, and the applet will
|
||||
// figure out where to place itself based on the editor location.
|
||||
// --editor-location=150,20
|
||||
if (editor != null) { // if running processing-cmd, don't do placement
|
||||
Point windowLocation = editor.getSketchLocation();
|
||||
if (windowLocation != null) {
|
||||
params.add(PApplet.ARGS_LOCATION + "=" +
|
||||
windowLocation.x + "," + windowLocation.y);
|
||||
} else {
|
||||
Point editorLocation = editor.getLocation();
|
||||
params.add(PApplet.ARGS_EDITOR_LOCATION + "=" +
|
||||
editorLocation.x + "," + editorLocation.y);
|
||||
}
|
||||
params.add(PApplet.ARGS_EXTERNAL);
|
||||
}
|
||||
|
||||
params.add(PApplet.ARGS_DISPLAY + "=" +
|
||||
Preferences.get("run.display"));
|
||||
params.add(PApplet.ARGS_SKETCH_FOLDER + "=" +
|
||||
sketch.getFolder().getAbsolutePath());
|
||||
|
||||
if (presenting) {
|
||||
params.add(PApplet.ARGS_PRESENT);
|
||||
if (Preferences.getBoolean("run.present.exclusive")) {
|
||||
params.add(PApplet.ARGS_EXCLUSIVE);
|
||||
}
|
||||
params.add(PApplet.ARGS_STOP_COLOR + "=" +
|
||||
Preferences.get("run.present.stop.color"));
|
||||
params.add(PApplet.ARGS_BGCOLOR + "=" +
|
||||
Preferences.get("run.present.bgcolor"));
|
||||
}
|
||||
|
||||
params.add(appletClassName);
|
||||
}
|
||||
|
||||
// String outgoing[] = new String[params.size()];
|
||||
// params.toArray(outgoing);
|
||||
// return outgoing;
|
||||
return (String[]) params.toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
protected VirtualMachine launchVirtualMachine(String[] vmParams,
|
||||
String[] classParams) {
|
||||
//vm = launchTarget(sb.toString());
|
||||
LaunchingConnector connector = (LaunchingConnector)
|
||||
findConnector("com.sun.jdi.RawCommandLineLaunch");
|
||||
//PApplet.println(connector); // gets the defaults
|
||||
|
||||
//Map arguments = connectorArguments(connector, mainArgs);
|
||||
Map arguments = connector.defaultArguments();
|
||||
|
||||
Connector.Argument commandArg =
|
||||
(Connector.Argument)arguments.get("command");
|
||||
// Using localhost instead of 127.0.0.1 sometimes causes a
|
||||
// "Transport Error 202" error message when trying to run.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=895
|
||||
String addr = "127.0.0.1:" + (8000 + (int) (Math.random() * 1000));
|
||||
//String addr = "localhost:" + (8000 + (int) (Math.random() * 1000));
|
||||
//String addr = "" + (8000 + (int) (Math.random() * 1000));
|
||||
|
||||
String commandArgs =
|
||||
"java -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
|
||||
if (Base.isWindows()) {
|
||||
commandArgs =
|
||||
"java -Xrunjdwp:transport=dt_shmem,address=" + addr + ",suspend=y ";
|
||||
} else if (Base.isMacOS()) {
|
||||
if (System.getProperty("os.version").startsWith("10.4")) {
|
||||
// -d32 not understood by 10.4 (and not needed)
|
||||
commandArgs =
|
||||
"java -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
|
||||
} else {
|
||||
commandArgs =
|
||||
"java -d32 -Xrunjdwp:transport=dt_socket,address=" + addr + ",suspend=y ";
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < vmParams.length; i++) {
|
||||
commandArgs = addArgument(commandArgs, vmParams[i], ' ');
|
||||
}
|
||||
if (classParams != null) {
|
||||
for (int i = 0; i < classParams.length; i++) {
|
||||
commandArgs = addArgument(commandArgs, classParams[i], ' ');
|
||||
}
|
||||
}
|
||||
commandArg.setValue(commandArgs);
|
||||
|
||||
Connector.Argument addressArg =
|
||||
(Connector.Argument)arguments.get("address");
|
||||
addressArg.setValue(addr);
|
||||
|
||||
//PApplet.println(connector); // prints the current
|
||||
//com.sun.tools.jdi.AbstractLauncher al;
|
||||
//com.sun.tools.jdi.RawCommandLineLauncher rcll;
|
||||
|
||||
//System.out.println(PApplet.javaVersion);
|
||||
// http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#sunlaunch
|
||||
try {
|
||||
return connector.launch(arguments);
|
||||
} catch (IOException exc) {
|
||||
throw new Error("Unable to launch target VM: " + exc);
|
||||
} catch (IllegalConnectorArgumentsException exc) {
|
||||
throw new Error("Internal error: " + exc);
|
||||
} catch (VMStartException exc) {
|
||||
Process p = exc.process();
|
||||
//System.out.println(p);
|
||||
String[] errorStrings = PApplet.loadStrings(p.getErrorStream());
|
||||
/*String[] inputStrings =*/ PApplet.loadStrings(p.getInputStream());
|
||||
|
||||
if (errorStrings != null && errorStrings.length > 1) {
|
||||
if (errorStrings[0].indexOf("Invalid maximum heap size") != -1) {
|
||||
Base.showWarning("Way Too High",
|
||||
"Please lower the value for \u201Cmaximum available memory\u201D in the\n" +
|
||||
"Preferences window. For more information, read Help \u2192 Troubleshooting.",
|
||||
exc);
|
||||
} else {
|
||||
PApplet.println(errorStrings);
|
||||
System.err.println("Using startup command:");
|
||||
PApplet.println(arguments);
|
||||
}
|
||||
} else {
|
||||
exc.printStackTrace();
|
||||
System.err.println("Could not run the sketch (Target VM failed to initialize).");
|
||||
if (Preferences.getBoolean("run.options.memory")) {
|
||||
// Only mention this if they've even altered the memory setup
|
||||
System.err.println("Make sure that you haven't set the maximum available memory too high.");
|
||||
}
|
||||
System.err.println("For more information, read revisions.txt and Help \u2192 Troubleshooting.");
|
||||
}
|
||||
// changing this to separate editor and listener [091124]
|
||||
//if (editor != null) {
|
||||
listener.statusError("Could not run the sketch.");
|
||||
//}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean hasWhitespace(String string) {
|
||||
int length = string.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (Character.isWhitespace(string.charAt(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static String addArgument(String string, String argument, char sep) {
|
||||
if (hasWhitespace(argument) || argument.indexOf(',') != -1) {
|
||||
// Quotes were stripped out for this argument, add 'em back.
|
||||
StringBuffer buffer = new StringBuffer(string);
|
||||
buffer.append('"');
|
||||
for (int i = 0; i < argument.length(); i++) {
|
||||
char c = argument.charAt(i);
|
||||
if (c == '"') {
|
||||
buffer.append('\\');
|
||||
}
|
||||
buffer.append(c);
|
||||
}
|
||||
buffer.append('\"');
|
||||
buffer.append(sep);
|
||||
return buffer.toString();
|
||||
} else {
|
||||
return string + argument + String.valueOf(sep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the trace.
|
||||
* Enable events, start thread to display events,
|
||||
* start threads to forward remote error and output streams,
|
||||
* resume the remote VM, wait for the final event, and shutdown.
|
||||
*/
|
||||
protected void generateTrace(PrintWriter writer) {
|
||||
vm.setDebugTraceMode(debugTraceMode);
|
||||
|
||||
EventThread eventThread = null;
|
||||
//if (writer != null) {
|
||||
eventThread = new EventThread(this, vm, excludes, writer);
|
||||
eventThread.setEventRequests(watchFields);
|
||||
eventThread.start();
|
||||
//}
|
||||
|
||||
//redirectOutput();
|
||||
|
||||
Process process = vm.process();
|
||||
|
||||
// processInput = new SystemOutSiphon(process.getInputStream());
|
||||
// processError = new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// Copy target's output and error to our output and error.
|
||||
// errThread = new StreamRedirectThread("error reader",
|
||||
// process.getErrorStream(),
|
||||
// System.err);
|
||||
MessageSiphon ms = new MessageSiphon(process.getErrorStream(), this);
|
||||
errThread = ms.getThread();
|
||||
|
||||
outThread = new StreamRedirectThread("output reader",
|
||||
process.getInputStream(),
|
||||
System.out);
|
||||
|
||||
errThread.start();
|
||||
outThread.start();
|
||||
|
||||
vm.resume();
|
||||
//System.out.println("done with resume");
|
||||
|
||||
// Shutdown begins when event thread terminates
|
||||
try {
|
||||
if (eventThread != null) eventThread.join();
|
||||
// System.out.println("in here");
|
||||
// Bug #852 tracked to this next line in the code.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=852
|
||||
errThread.join(); // Make sure output is forwarded
|
||||
// System.out.println("and then");
|
||||
outThread.join(); // before we exit
|
||||
// System.out.println("out of it");
|
||||
|
||||
// At this point, disable the run button.
|
||||
// This happens when the sketch is exited by hitting ESC,
|
||||
// or the user manually closes the sketch window.
|
||||
// TODO this should be handled better, should it not?
|
||||
if (editor != null) {
|
||||
editor.internalRunnerClosed();
|
||||
}
|
||||
} catch (InterruptedException exc) {
|
||||
// we don't interrupt
|
||||
}
|
||||
//System.out.println("and leaving");
|
||||
if (writer != null) writer.close();
|
||||
}
|
||||
|
||||
|
||||
protected Connector findConnector(String connectorName) {
|
||||
List connectors = Bootstrap.virtualMachineManager().allConnectors();
|
||||
|
||||
// debug: code to list available connectors
|
||||
// Iterator iter2 = connectors.iterator();
|
||||
// while (iter2.hasNext()) {
|
||||
// Connector connector = (Connector)iter2.next();
|
||||
// System.out.println("connector name is " + connector.name());
|
||||
// }
|
||||
|
||||
Iterator iter = connectors.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Connector connector = (Connector)iter.next();
|
||||
if (connector.name().equals(connectorName)) {
|
||||
return connector;
|
||||
}
|
||||
}
|
||||
throw new Error("No connector");
|
||||
}
|
||||
|
||||
|
||||
public void exception(ExceptionEvent event) {
|
||||
// System.out.println(event);
|
||||
ObjectReference or = event.exception();
|
||||
ReferenceType rt = or.referenceType();
|
||||
String exceptionName = rt.name();
|
||||
//Field messageField = Throwable.class.getField("detailMessage");
|
||||
Field messageField = rt.fieldByName("detailMessage");
|
||||
// System.out.println("field " + messageField);
|
||||
Value messageValue = or.getValue(messageField);
|
||||
// System.out.println("mess val " + messageValue);
|
||||
|
||||
int last = exceptionName.lastIndexOf('.');
|
||||
String message = exceptionName.substring(last + 1);
|
||||
if (messageValue != null) {
|
||||
String messageStr = messageValue.toString();
|
||||
if (messageStr.startsWith("\"")) {
|
||||
messageStr = messageStr.substring(1, messageStr.length() - 1);
|
||||
}
|
||||
message += ": " + messageStr;
|
||||
}
|
||||
// System.out.println("mess type " + messageValue.type());
|
||||
//StringReference messageReference = (StringReference) messageValue.type();
|
||||
|
||||
// System.out.println(or.referenceType().fields());
|
||||
// if (name.startsWith("java.lang.")) {
|
||||
// name = name.substring(10);
|
||||
if (!handleCommonErrors(exceptionName, message, listener)) {
|
||||
reportException(message, event.thread());
|
||||
}
|
||||
if (editor != null) {
|
||||
editor.internalRunnerClosed();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean handleCommonErrors(final String exceptionClass, final String message, final RunnerListener listener)
|
||||
{
|
||||
if (exceptionClass.equals("java.lang.OutOfMemoryError")) {
|
||||
listener.statusError("OutOfMemoryError: You may need to increase the memory setting in Preferences.");
|
||||
System.err.println("An OutOfMemoryError means that your code is either using up too much memory");
|
||||
System.err.println("because of a bug (e.g. creating an array that's too large, or unintentionally");
|
||||
System.err.println("loading thousands of images), or that your sketch may need more memory to run.");
|
||||
System.err.println("If your sketch uses a lot of memory (for instance if it loads a lot of data files)");
|
||||
System.err.println("you can increase the memory available to your sketch using the Preferences window.");
|
||||
|
||||
} else if (exceptionClass.equals("java.lang.StackOverflowError")) {
|
||||
listener.statusError("StackOverflowError: This sketch is attempting too much recursion.");
|
||||
System.err.println("A StackOverflowError means that you have a bug that's causing a function");
|
||||
System.err.println("to be called recursively (it's calling itself and going in circles),");
|
||||
System.err.println("or you're intentionally calling a recursive function too much,");
|
||||
System.err.println("and your code should be rewritten in a more efficient manner.");
|
||||
|
||||
} else if (exceptionClass.equals("java.lang.UnsupportedClassVersionError")) {
|
||||
listener.statusError("UnsupportedClassVersionError: A library is using code compiled with an unsupported version of Java.");
|
||||
System.err.println("This version of Processing only supports libraries and JAR files compiled for Java 1.5.");
|
||||
System.err.println("A library used by this sketch was compiled for Java 1.6 or later, ");
|
||||
System.err.println("and needs to be recompiled to be compatible with Java 1.5.");
|
||||
} else if (exceptionClass.equals("java.lang.NoSuchMethodError") || exceptionClass.equals("java.lang.NoSuchFieldError")) {
|
||||
listener.statusError(exceptionClass.substring(10) + ": You're probably using a library that's incompatible with this version of Processing.");
|
||||
} else if (message!=null &&
|
||||
message.equals("ClassNotFoundException: quicktime.std.StdQTException")) {
|
||||
listener
|
||||
.statusError("Could not find QuickTime, please reinstall QuickTime 7 or later.");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: This may be called more than one time per error in the VM,
|
||||
// presumably because exceptions might be wrapped inside others,
|
||||
// and this will fire for both.
|
||||
protected void reportException(String message, ThreadReference thread) {
|
||||
listener.statusError(findException(message, thread));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move through a list of stack frames, searching for references to code
|
||||
* found in the current sketch. Return with a RunnerException that contains
|
||||
* the location of the error, or if nothing is found, just return with a
|
||||
* RunnerException that wraps the error message itself.
|
||||
*/
|
||||
RunnerException findException(String message, ThreadReference thread) {
|
||||
try {
|
||||
// use to dump the stack for debugging
|
||||
// for (StackFrame frame : thread.frames()) {
|
||||
// System.out.println("frame: " + frame);
|
||||
// }
|
||||
|
||||
List<StackFrame> frames = thread.frames();
|
||||
for (StackFrame frame : frames) {
|
||||
try {
|
||||
Location location = frame.location();
|
||||
String filename = null;
|
||||
filename = location.sourceName();
|
||||
int lineNumber = location.lineNumber() - 1;
|
||||
RunnerException rex =
|
||||
sketch.placeException(message, filename, lineNumber);
|
||||
if (rex != null) {
|
||||
return rex;
|
||||
}
|
||||
} catch (AbsentInformationException e) {
|
||||
// Any of the thread.blah() methods can throw an AbsentInformationEx
|
||||
// if that bit of data is missing. If so, just write out the error
|
||||
// message to the console.
|
||||
//e.printStackTrace(); // not useful
|
||||
exception = new RunnerException(message);
|
||||
exception.hideStackTrace();
|
||||
listener.statusError(exception);
|
||||
}
|
||||
}
|
||||
} catch (IncompatibleThreadStateException e) {
|
||||
// This shouldn't happen, but if it does, print the exception in case
|
||||
// it's something that needs to be debugged separately.
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Give up, nothing found inside the pile of stack frames
|
||||
RunnerException rex = new RunnerException(message);
|
||||
// exception is being created /here/, so stack trace is not useful
|
||||
rex.hideStackTrace();
|
||||
return rex;
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
// TODO make sure stop() has already been called to exit the sketch
|
||||
|
||||
// TODO actually kill off the vm here
|
||||
if (vm != null) {
|
||||
try {
|
||||
vm.exit(0);
|
||||
|
||||
} catch (com.sun.jdi.VMDisconnectedException vmde) {
|
||||
// if the vm has disconnected on its own, ignore message
|
||||
//System.out.println("harmless disconnect " + vmde.getMessage());
|
||||
// TODO shouldn't need to do this, need to do more cleanup
|
||||
}
|
||||
vm = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// made synchronized for rev 87
|
||||
// attempted to remove synchronized for 0136 to fix bug #775 (no luck tho)
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=775
|
||||
synchronized public void message(String s) {
|
||||
//System.out.println("M" + s.length() + ":" + s.trim()); // + "MMM" + s.length());
|
||||
|
||||
// this eats the CRLFs on the lines.. oops.. do it later
|
||||
//if (s.trim().length() == 0) return;
|
||||
|
||||
// this is PApplet sending a message (via System.out.println)
|
||||
// that signals that the applet has been quit.
|
||||
if (s.indexOf(PApplet.EXTERNAL_STOP) == 0) {
|
||||
//System.out.println("external: quit");
|
||||
if (editor != null) {
|
||||
//editor.internalCloseRunner(); // [091124]
|
||||
editor.handleStop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// this is the PApplet sending us a message that the applet
|
||||
// is being moved to a new window location
|
||||
if (s.indexOf(PApplet.EXTERNAL_MOVE) == 0) {
|
||||
String nums = s.substring(s.indexOf(' ') + 1).trim();
|
||||
int space = nums.indexOf(' ');
|
||||
int left = Integer.parseInt(nums.substring(0, space));
|
||||
int top = Integer.parseInt(nums.substring(space + 1));
|
||||
// this is only fired when connected to an editor
|
||||
editor.setSketchLocation(new Point(left, top));
|
||||
//System.out.println("external: move to " + left + " " + top);
|
||||
return;
|
||||
}
|
||||
|
||||
// these are used for debugging, in case there are concerns
|
||||
// that some errors aren't coming through properly
|
||||
// if (s.length() > 2) {
|
||||
// System.err.println(newMessage);
|
||||
// System.err.println("message " + s.length() + ":" + s);
|
||||
// }
|
||||
|
||||
// always shove out the mesage, since it might not fall under
|
||||
// the same setup as we're expecting
|
||||
System.err.print(s);
|
||||
//System.err.println("[" + s.length() + "] " + s);
|
||||
System.err.flush();
|
||||
}
|
||||
}
|
@ -101,6 +101,26 @@ bt.build.core=arduino
|
||||
|
||||
##############################################################
|
||||
|
||||
fio.name=Arduino Fio
|
||||
|
||||
fio.upload.protocol=stk500
|
||||
fio.upload.maximum_size=30720
|
||||
fio.upload.speed=57600
|
||||
|
||||
fio.bootloader.low_fuses=0xFF
|
||||
fio.bootloader.high_fuses=0xDA
|
||||
fio.bootloader.extended_fuses=0x05
|
||||
fio.bootloader.path=arduino:atmega
|
||||
fio.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
|
||||
fio.bootloader.unlock_bits=0x3F
|
||||
fio.bootloader.lock_bits=0x0F
|
||||
|
||||
fio.build.mcu=atmega328p
|
||||
fio.build.f_cpu=8000000L
|
||||
fio.build.core=arduino:arduino
|
||||
|
||||
##############################################################
|
||||
|
||||
lilypad328.name=LilyPad Arduino w/ ATmega328
|
||||
|
||||
lilypad328.upload.protocol=stk500
|
||||
@ -179,27 +199,6 @@ pro.build.mcu=atmega168
|
||||
pro.build.f_cpu=8000000L
|
||||
pro.build.core=arduino
|
||||
|
||||
##############################################################
|
||||
|
||||
fio.name=Arduino Fio
|
||||
|
||||
fio.upload.protocol=stk500
|
||||
fio.upload.maximum_size=30720
|
||||
fio.upload.speed=57600
|
||||
|
||||
fio.bootloader.low_fuses=0xFF
|
||||
fio.bootloader.high_fuses=0xDA
|
||||
fio.bootloader.extended_fuses=0x05
|
||||
fio.bootloader.path=arduino:atmega
|
||||
fio.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
|
||||
fio.bootloader.unlock_bits=0x3F
|
||||
fio.bootloader.lock_bits=0x0F
|
||||
|
||||
fio.build.mcu=atmega328p
|
||||
fio.build.f_cpu=8000000L
|
||||
fio.build.core=arduino:arduino
|
||||
|
||||
|
||||
##############################################################
|
||||
|
||||
atmega168.name=Arduino NG or older w/ ATmega168
|
||||
|
Loading…
Reference in New Issue
Block a user