Added source to maple_loader.jar
This commit is contained in:
parent
9c951d40d6
commit
ce70ae4fce
|
@ -0,0 +1,5 @@
|
|||
These files build the maple_loader.jar file used on Windows to reset the Sketch via USB Serial, so that the bootloader will run in dfu upload mode, ready for a new sketch to be uploaded
|
||||
|
||||
The files were written by @bobC (github) and have been slightly modified by me (Roger Clark), so that dfu-util no longer attempts to reset the board after upload.
|
||||
This change to dfu-util's reset command line argument, was required because dfu-util was showing errors on some Windows systems, because the bootloader had reset its self after upload,
|
||||
before dfu-util had chance to tell it to reset.
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="maple_loader" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project maple_loader.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar: JAR building
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="maple_loader-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
|
@ -0,0 +1,4 @@
|
|||
#Mon, 20 Jul 2015 11:21:26 +1000
|
||||
|
||||
|
||||
C\:\\Users\\rclark\\Desktop\\maple-asp-master\\installer\\maple_loader=
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,32 @@
|
|||
========================
|
||||
BUILD OUTPUT DESCRIPTION
|
||||
========================
|
||||
|
||||
When you build an Java application project that has a main class, the IDE
|
||||
automatically copies all of the JAR
|
||||
files on the projects classpath to your projects dist/lib folder. The IDE
|
||||
also adds each of the JAR files to the Class-Path element in the application
|
||||
JAR files manifest file (MANIFEST.MF).
|
||||
|
||||
To run the project from the command line, go to the dist folder and
|
||||
type the following:
|
||||
|
||||
java -jar "maple_loader.jar"
|
||||
|
||||
To distribute this project, zip up the dist folder (including the lib folder)
|
||||
and distribute the ZIP file.
|
||||
|
||||
Notes:
|
||||
|
||||
* If two JAR files on the project classpath have the same name, only the first
|
||||
JAR file is copied to the lib folder.
|
||||
* Only JAR files are copied to the lib folder.
|
||||
If the classpath contains other types of files or folders, these files (folders)
|
||||
are not copied.
|
||||
* If a library on the projects classpath also has a Class-Path element
|
||||
specified in the manifest,the content of the Class-Path element has to be on
|
||||
the projects runtime path.
|
||||
* To set a main class in a standard Java project, right-click the project node
|
||||
in the Projects window and choose Properties. Then click Run and enter the
|
||||
class name in the Main Class field. Alternatively, you can manually type the
|
||||
class name in the manifest Main-Class element.
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,8 @@
|
|||
build.xml.data.CRC32=2e6a03ba
|
||||
build.xml.script.CRC32=4676ee6b
|
||||
build.xml.stylesheet.CRC32=8064a381@1.75.2.48
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=2e6a03ba
|
||||
nbproject/build-impl.xml.script.CRC32=392b3f79
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
|
|
@ -0,0 +1,6 @@
|
|||
compile.on.save=true
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
user.properties.file=C:\\Users\\rclark\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group>
|
||||
<file>file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/CliMain.java</file>
|
||||
<file>file:/C:/Users/rclark/Desktop/maple-asp-master/installer/maple_loader/src/CliTemplate/DFUUploader.java</file>
|
||||
</group>
|
||||
</open-files>
|
||||
</project-private>
|
|
@ -0,0 +1,79 @@
|
|||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=
|
||||
annotation.processing.run.all.processors=true
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=maple_loader
|
||||
application.vendor=bob
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# Files in build.classes.dir which should be excluded from distribution jar
|
||||
dist.archive.excludes=
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/maple_loader.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.jssc.jar=dist/lib/jssc.jar
|
||||
file.reference.jssc.jar-1=jars/jssc.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${file.reference.jssc.jar}:\
|
||||
${file.reference.jssc.jar-1}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.7
|
||||
javac.target=1.7
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
main.class=CliTemplate.CliMain
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project.
|
||||
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
|
||||
# To set system properties for unit tests define test-sys-prop.name=value:
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>maple_loader</name>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package CliTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import processing.app.Preferences;
|
||||
|
||||
//import processing.app.I18n;
|
||||
import processing.app.helpers.ProcessUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author cousinr
|
||||
*/
|
||||
public class CliMain {
|
||||
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
String comPort = args[0]; //
|
||||
String altIf = args[1]; //
|
||||
String usbID = args[2]; // "1EAF:0003";
|
||||
String binFile = args[3]; // bin file
|
||||
|
||||
System.out.println("maple_loader v0.1");
|
||||
|
||||
Preferences.set ("serial.port",comPort);
|
||||
Preferences.set ("serial.parity","N");
|
||||
Preferences.setInteger ("serial.databits", 8);
|
||||
Preferences.setInteger ("serial.debug_rate",9600);
|
||||
Preferences.setInteger ("serial.stopbits",1);
|
||||
|
||||
Preferences.setInteger ("programDelay",1200);
|
||||
|
||||
Preferences.set ("upload.usbID", usbID);
|
||||
Preferences.set ("upload.altID", altIf);
|
||||
Preferences.setBoolean ("upload.auto_reset", true);
|
||||
Preferences.setBoolean ("upload.verbose", false);
|
||||
|
||||
//
|
||||
DFUUploader dfuUploader = new DFUUploader();
|
||||
try {
|
||||
//dfuUploader.uploadViaDFU(binFile);
|
||||
dfuUploader.uploadViaDFU(binFile);
|
||||
} catch (Exception e)
|
||||
{
|
||||
System.err.print (MessageFormat.format("an error occurred! {0}\n", e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
DFUUploader - uploader implementation using DFU
|
||||
|
||||
Copyright (c) 2010
|
||||
Andrew Meyer
|
||||
|
||||
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 CliTemplate;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import processing.app.Preferences;
|
||||
import processing.app.Serial;
|
||||
import processing.app.debug.MessageConsumer;
|
||||
import processing.app.debug.MessageSiphon;
|
||||
import processing.app.debug.RunnerException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bob
|
||||
*/
|
||||
public class DFUUploader implements MessageConsumer {
|
||||
|
||||
boolean firstErrorFound;
|
||||
boolean secondErrorFound;
|
||||
// part of the PdeMessageConsumer interface
|
||||
boolean notFoundError;
|
||||
boolean verbose;
|
||||
RunnerException exception;
|
||||
|
||||
static final String SUPER_BADNESS =
|
||||
"Compiler error!";
|
||||
|
||||
public boolean uploadUsingPreferences(String binPath, boolean verbose)
|
||||
throws RunnerException {
|
||||
|
||||
this.verbose = verbose;
|
||||
|
||||
return uploadViaDFU(binPath);
|
||||
}
|
||||
|
||||
// works with old and new versions of dfu-util
|
||||
private boolean found_device (String dfuData, String usbID)
|
||||
{
|
||||
return dfuData.contains(("Found DFU: [0x"+usbID.substring(0,4)).toUpperCase()) ||
|
||||
dfuData.contains(("Found DFU: ["+usbID.substring(0,4)).toUpperCase());
|
||||
}
|
||||
|
||||
public boolean uploadViaDFU (String binPath)
|
||||
throws RunnerException {
|
||||
|
||||
this.verbose = Preferences.getBoolean ("upload.verbose");
|
||||
|
||||
/* todo, check for size overruns! */
|
||||
String fileType="bin";
|
||||
|
||||
if (fileType.equals("bin")) {
|
||||
String usbID = Preferences.get("upload.usbID");
|
||||
if (usbID == null) {
|
||||
/* fall back on default */
|
||||
/* this isnt great because is default Avrdude or dfu-util? */
|
||||
usbID = Preferences.get("upload.usbID");
|
||||
}
|
||||
|
||||
/* if auto-reset, then emit the reset pulse on dtr/rts */
|
||||
if (Preferences.get("upload.auto_reset") != null) {
|
||||
if (Preferences.get("upload.auto_reset").toLowerCase().equals("true")) {
|
||||
System.out.println("Resetting to bootloader via DTR pulse");
|
||||
emitResetPulse();
|
||||
}
|
||||
} else {
|
||||
System.out.println("Resetting to bootloader via DTR pulse");
|
||||
emitResetPulse();
|
||||
}
|
||||
|
||||
String dfuList = new String();
|
||||
List commandCheck = new ArrayList();
|
||||
commandCheck.add("dfu-util");
|
||||
commandCheck.add("-l");
|
||||
long startChecking = System.currentTimeMillis();
|
||||
System.out.println("Searching for DFU device [" + usbID + "]...");
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {}
|
||||
dfuList = executeCheckCommand(commandCheck);
|
||||
//System.out.println(dfuList);
|
||||
}
|
||||
while ( !found_device (dfuList.toUpperCase(), usbID) && (System.currentTimeMillis() - startChecking < 7000));
|
||||
|
||||
if ( !found_device (dfuList.toUpperCase(), usbID) )
|
||||
{
|
||||
System.out.println(dfuList);
|
||||
System.err.println("Couldn't find the DFU device: [" + usbID + "]");
|
||||
return false;
|
||||
}
|
||||
System.out.println("Found it!");
|
||||
|
||||
/* todo, add handle to let user choose altIf at upload time! */
|
||||
String altIf = Preferences.get("upload.altID");
|
||||
|
||||
List commandDownloader = new ArrayList();
|
||||
commandDownloader.add("dfu-util");
|
||||
commandDownloader.add("-a "+altIf);
|
||||
commandDownloader.add("-R");
|
||||
commandDownloader.add("-d "+usbID);
|
||||
commandDownloader.add("-D"+ binPath); //"./thisbin.bin");
|
||||
|
||||
return executeUploadCommand(commandDownloader);
|
||||
}
|
||||
|
||||
System.err.println("Only .bin files are supported at this time");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* we need to ensure both RTS and DTR are low to start,
|
||||
then pulse DTR on its own. This is the reset signal
|
||||
maple responds to
|
||||
*/
|
||||
private void emitResetPulse() throws RunnerException {
|
||||
|
||||
/* wait a while for the device to reboot */
|
||||
int programDelay = Preferences.getInteger("programDelay");
|
||||
|
||||
try {
|
||||
Serial serialPort = new Serial();
|
||||
|
||||
// try to toggle DTR/RTS (old scheme)
|
||||
serialPort.setRTS(false);
|
||||
serialPort.setDTR(false);
|
||||
serialPort.setDTR(true);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {}
|
||||
serialPort.setDTR(false);
|
||||
|
||||
// try magic number
|
||||
serialPort.setRTS(true);
|
||||
serialPort.setDTR(true);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {}
|
||||
serialPort.setDTR(false);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {}
|
||||
serialPort.write("1EAF");
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {}
|
||||
serialPort.dispose();
|
||||
|
||||
} catch(Exception e) {
|
||||
System.err.println("Reset via USB Serial Failed! Did you select the right serial port?\nAssuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected String executeCheckCommand(Collection commandDownloader)
|
||||
throws RunnerException
|
||||
{
|
||||
firstErrorFound = false; // haven't found any errors yet
|
||||
secondErrorFound = false;
|
||||
notFoundError = false;
|
||||
int result=0; // pre-initialized to quiet a bogus warning from jikes
|
||||
|
||||
String userdir = System.getProperty("user.dir") + File.separator;
|
||||
String returnStr = new String();
|
||||
|
||||
try {
|
||||
String[] commandArray = new String[commandDownloader.size()];
|
||||
commandDownloader.toArray(commandArray);
|
||||
|
||||
String armBasePath;
|
||||
|
||||
//armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/");
|
||||
armBasePath = "";
|
||||
|
||||
commandArray[0] = armBasePath + commandArray[0];
|
||||
|
||||
if (verbose || Preferences.getBoolean("upload.verbose")) {
|
||||
for(int i = 0; i < commandArray.length; i++) {
|
||||
System.out.print(commandArray[i] + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
Process process = Runtime.getRuntime().exec(commandArray);
|
||||
BufferedReader stdInput = new BufferedReader(new
|
||||
InputStreamReader(process.getInputStream()));
|
||||
BufferedReader stdError = new BufferedReader(new
|
||||
InputStreamReader(process.getErrorStream()));
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
boolean busy = true;
|
||||
while (busy) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
busy = false;
|
||||
} catch (InterruptedException intExc) {
|
||||
}
|
||||
}
|
||||
|
||||
String s;
|
||||
while ((s = stdInput.readLine()) != null) {
|
||||
returnStr += s + "\n";
|
||||
}
|
||||
|
||||
process.destroy();
|
||||
|
||||
if(exception!=null) {
|
||||
exception.hideStackTrace();
|
||||
throw exception;
|
||||
}
|
||||
if(result!=0) return "Error!";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println("result2 is "+result);
|
||||
// if the result isn't a known, expected value it means that something
|
||||
// is fairly wrong, one possibility is that jikes has crashed.
|
||||
//
|
||||
if (exception != null) throw exception;
|
||||
|
||||
if ((result != 0) && (result != 1 )) {
|
||||
exception = new RunnerException(SUPER_BADNESS);
|
||||
}
|
||||
|
||||
return returnStr; // ? true : false;
|
||||
|
||||
}
|
||||
|
||||
// Need to overload this from Uploader to use the system-wide dfu-util
|
||||
protected boolean executeUploadCommand(Collection commandDownloader)
|
||||
throws RunnerException
|
||||
{
|
||||
firstErrorFound = false; // haven't found any errors yet
|
||||
secondErrorFound = false;
|
||||
notFoundError = false;
|
||||
int result=0; // pre-initialized to quiet a bogus warning from jikes
|
||||
|
||||
String userdir = System.getProperty("user.dir") + File.separator;
|
||||
|
||||
try {
|
||||
String[] commandArray = new String[commandDownloader.size()];
|
||||
commandDownloader.toArray(commandArray);
|
||||
|
||||
String armBasePath;
|
||||
|
||||
//armBasePath = new String(Base.getHardwarePath() + "/tools/arm/bin/");
|
||||
armBasePath = "";
|
||||
|
||||
commandArray[0] = armBasePath + commandArray[0];
|
||||
|
||||
if (verbose || Preferences.getBoolean("upload.verbose")) {
|
||||
for(int i = 0; i < commandArray.length; i++) {
|
||||
System.out.print(commandArray[i] + " ");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
Process process = Runtime.getRuntime().exec(commandArray);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
//
|
||||
boolean compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
result = process.waitFor();
|
||||
compiling = false;
|
||||
} catch (InterruptedException intExc) {
|
||||
}
|
||||
}
|
||||
if(exception!=null) {
|
||||
exception.hideStackTrace();
|
||||
throw exception;
|
||||
}
|
||||
if(result!=0)
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println("result2 is "+result);
|
||||
// if the result isn't a known, expected value it means that something
|
||||
// is fairly wrong, one possibility is that jikes has crashed.
|
||||
//
|
||||
if (exception != null) throw exception;
|
||||
|
||||
if ((result != 0) && (result != 1 )) {
|
||||
exception = new RunnerException(SUPER_BADNESS);
|
||||
//editor.error(exception);
|
||||
//PdeBase.openURL(BUGS_URL);
|
||||
//throw new PdeException(SUPER_BADNESS);
|
||||
}
|
||||
|
||||
return (result == 0); // ? true : false;
|
||||
|
||||
}
|
||||
|
||||
// deal with messages from dfu-util...
|
||||
public void message(String s) {
|
||||
|
||||
if(s.indexOf("dfu-util - (C) ") != -1) { return; }
|
||||
if(s.indexOf("This program is Free Software and has ABSOLUTELY NO WARRANTY") != -1) { return; }
|
||||
|
||||
if(s.indexOf("No DFU capable USB device found") != -1) {
|
||||
System.err.print(s);
|
||||
exception = new RunnerException("Problem uploading via dfu-util: No Maple found");
|
||||
return;
|
||||
}
|
||||
|
||||
if(s.indexOf("Operation not perimitted") != -1) {
|
||||
System.err.print(s);
|
||||
exception = new RunnerException("Problem uploading via dfu-util: Insufficient privilages");
|
||||
return;
|
||||
}
|
||||
|
||||
// else just print everything...
|
||||
System.out.print(s);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package CliTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import processing.app.debug.MessageConsumer;
|
||||
import processing.app.debug.MessageSiphon;
|
||||
import processing.app.debug.RunnerException;
|
||||
import processing.app.helpers.ProcessUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author cousinr
|
||||
*/
|
||||
public class ExecCommand implements MessageConsumer {
|
||||
|
||||
private boolean verbose = true;
|
||||
private boolean firstErrorFound;
|
||||
private boolean secondErrorFound;
|
||||
private RunnerException exception;
|
||||
|
||||
/**
|
||||
* Either succeeds or throws a RunnerException fit for public consumption.
|
||||
*
|
||||
* @param command
|
||||
* @throws RunnerException
|
||||
*/
|
||||
public void execAsynchronously(String[] command) throws RunnerException {
|
||||
|
||||
// eliminate any empty array entries
|
||||
List<String> stringList = new ArrayList<>();
|
||||
for (String string : command) {
|
||||
string = string.trim();
|
||||
if (string.length() != 0)
|
||||
stringList.add(string);
|
||||
}
|
||||
command = stringList.toArray(new String[stringList.size()]);
|
||||
if (command.length == 0)
|
||||
return;
|
||||
int result = 0;
|
||||
|
||||
if (verbose) {
|
||||
for (String c : command)
|
||||
System.out.print(c + " ");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
firstErrorFound = false; // haven't found any errors yet
|
||||
secondErrorFound = false;
|
||||
|
||||
Process process;
|
||||
try {
|
||||
process = ProcessUtils.exec(command);
|
||||
} catch (IOException e) {
|
||||
RunnerException re = new RunnerException(e.getMessage());
|
||||
re.hideStackTrace();
|
||||
throw re;
|
||||
}
|
||||
|
||||
MessageSiphon in = new MessageSiphon(process.getInputStream(), this);
|
||||
MessageSiphon err = new MessageSiphon(process.getErrorStream(), this);
|
||||
|
||||
// wait for the process to finish. if interrupted
|
||||
// before waitFor returns, continue waiting
|
||||
boolean compiling = true;
|
||||
while (compiling) {
|
||||
try {
|
||||
in.join();
|
||||
err.join();
|
||||
result = process.waitFor();
|
||||
//System.out.println("result is " + result);
|
||||
compiling = false;
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
|
||||
// an error was queued up by message(), barf this back to compile(),
|
||||
// which will barf it back to Editor. if you're having trouble
|
||||
// discerning the imagery, consider how cows regurgitate their food
|
||||
// to digest it, and the fact that they have five stomaches.
|
||||
//
|
||||
//System.out.println("throwing up " + exception);
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
|
||||
if (result > 1) {
|
||||
// a failure in the tool (e.g. unable to locate a sub-executable)
|
||||
System.err.println(MessageFormat.format("{0} returned {1}", command[0], result));
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
RunnerException re = new RunnerException(MessageFormat.format("exit code: {0}", result));
|
||||
re.hideStackTrace();
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of the MessageConsumer interface, this is called
|
||||
* whenever a piece (usually a line) of error message is spewed
|
||||
* out from the compiler. The errors are parsed for their contents
|
||||
* and line number, which is then reported back to Editor.
|
||||
* @param s
|
||||
*/
|
||||
@Override
|
||||
public void message(String s) {
|
||||
int i;
|
||||
|
||||
|
||||
System.err.print(s);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-10 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 version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* The base class for the main processing application.
|
||||
* Primary role of this class is for platform identification and
|
||||
* general interaction with the system (launching URLs, loading
|
||||
* files and images, etc) that comes from that.
|
||||
*/
|
||||
public class Base {
|
||||
|
||||
/**
|
||||
* returns true if running on windows.
|
||||
*/
|
||||
static public boolean isWindows() {
|
||||
//return PApplet.platform == PConstants.WINDOWS;
|
||||
return System.getProperty("os.name").indexOf("Windows") != -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* true if running on linux.
|
||||
*/
|
||||
static public boolean isLinux() {
|
||||
//return PApplet.platform == PConstants.LINUX;
|
||||
return System.getProperty("os.name").indexOf("Linux") != -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/* -*- 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;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Storage class for user preferences and environment settings.
|
||||
* <P>
|
||||
* This class no longer uses the Properties class, since
|
||||
* properties files are iso8859-1, which is highly likely to
|
||||
* be a problem when trying to save sketch folders and locations.
|
||||
* <p>
|
||||
* The GUI portion in here is really ugly, as it uses exact layout. This was
|
||||
* done in frustration one evening (and pre-Swing), but that's long since past,
|
||||
* and it should all be moved to a proper swing layout like BoxLayout.
|
||||
* <p>
|
||||
* This is very poorly put together, that the preferences panel and the actual
|
||||
* preferences i/o is part of the same code. But there hasn't yet been a
|
||||
* compelling reason to bother with the separation aside from concern about
|
||||
* being lectured by strangers who feel that it doesn't look like what they
|
||||
* learned in CS class.
|
||||
* <p>
|
||||
* Would also be possible to change this to use the Java Preferences API.
|
||||
* Some useful articles
|
||||
* <a href="http://www.onjava.com/pub/a/onjava/synd/2001/10/17/j2se.html">here</a> and
|
||||
* <a href="http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter10/Preferences.html">here</a>.
|
||||
* However, haven't implemented this yet for lack of time, but more
|
||||
* importantly, because it would entail writing to the registry (on Windows),
|
||||
* or an obscure file location (on Mac OS X) and make it far more difficult to
|
||||
* find the preferences to tweak them by hand (no! stay out of regedit!)
|
||||
* or to reset the preferences by simply deleting the preferences.txt file.
|
||||
*/
|
||||
public class Preferences {
|
||||
|
||||
// what to call the feller
|
||||
|
||||
static final String PREFS_FILE = "preferences.txt";
|
||||
|
||||
|
||||
// prompt text stuff
|
||||
|
||||
static final String PROMPT_YES = "Yes";
|
||||
static final String PROMPT_NO = "No";
|
||||
static final String PROMPT_CANCEL = "Cancel";
|
||||
static final String PROMPT_OK = "OK";
|
||||
static final String PROMPT_BROWSE = "Browse";
|
||||
|
||||
/**
|
||||
* Standardized width for buttons. Mac OS X 10.3 wants 70 as its default,
|
||||
* Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper.
|
||||
*/
|
||||
static public int BUTTON_WIDTH = 80;
|
||||
|
||||
/**
|
||||
* Standardized button height. Mac OS X 10.3 (Java 1.4) wants 29,
|
||||
* presumably because it now includes the blue border, where it didn't
|
||||
* in Java 1.3. Windows XP only wants 23 (not sure what default Linux
|
||||
* would be). Because of the disparity, on Mac OS X, it will be set
|
||||
* inside a static block.
|
||||
*/
|
||||
static public int BUTTON_HEIGHT = 24;
|
||||
|
||||
// value for the size bars, buttons, etc
|
||||
|
||||
static final int GRID_SIZE = 33;
|
||||
|
||||
|
||||
// indents and spacing standards. these probably need to be modified
|
||||
// per platform as well, since macosx is so huge, windows is smaller,
|
||||
// and linux is all over the map
|
||||
|
||||
static final int GUI_BIG = 13;
|
||||
static final int GUI_BETWEEN = 10;
|
||||
static final int GUI_SMALL = 6;
|
||||
|
||||
|
||||
|
||||
// data model
|
||||
|
||||
static Hashtable table = new Hashtable();;
|
||||
static File preferencesFile;
|
||||
|
||||
|
||||
static protected void init(String commandLinePrefs) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Preferences() {
|
||||
|
||||
}
|
||||
|
||||
// .................................................................
|
||||
|
||||
// .................................................................
|
||||
|
||||
// .................................................................
|
||||
|
||||
// .................................................................
|
||||
|
||||
|
||||
|
||||
static public String get(String attribute) {
|
||||
return (String) table.get(attribute);
|
||||
}
|
||||
|
||||
static public void set(String attribute, String value) {
|
||||
table.put(attribute, value);
|
||||
}
|
||||
|
||||
|
||||
static public boolean getBoolean(String attribute) {
|
||||
String value = get(attribute);
|
||||
return (new Boolean(value)).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
static public void setBoolean(String attribute, boolean value) {
|
||||
set(attribute, value ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
static public int getInteger(String attribute) {
|
||||
return Integer.parseInt(get(attribute));
|
||||
}
|
||||
|
||||
|
||||
static public void setInteger(String key, int value) {
|
||||
set(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,527 @@
|
|||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
PSerial - class for serial port goodness
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004 Ben Fry & Casey Reas
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
package processing.app;
|
||||
//import processing.core.*;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import jssc.SerialPort;
|
||||
import jssc.SerialPortEvent;
|
||||
import jssc.SerialPortEventListener;
|
||||
import jssc.SerialPortException;
|
||||
import jssc.SerialPortList;
|
||||
import processing.app.debug.MessageConsumer;
|
||||
|
||||
|
||||
public class Serial implements SerialPortEventListener {
|
||||
|
||||
//PApplet parent;
|
||||
|
||||
// properties can be passed in for default values
|
||||
// otherwise defaults to 9600 N81
|
||||
|
||||
// these could be made static, which might be a solution
|
||||
// for the classloading problem.. because if code ran again,
|
||||
// the static class would have an object that could be closed
|
||||
|
||||
SerialPort port;
|
||||
|
||||
int rate;
|
||||
int parity;
|
||||
int databits;
|
||||
int stopbits;
|
||||
boolean monitor = false;
|
||||
|
||||
// read buffer and streams
|
||||
|
||||
InputStream input;
|
||||
OutputStream output;
|
||||
|
||||
byte buffer[] = new byte[32768];
|
||||
int bufferIndex;
|
||||
int bufferLast;
|
||||
|
||||
MessageConsumer consumer;
|
||||
|
||||
public Serial(boolean monitor) throws SerialException {
|
||||
this(Preferences.get("serial.port"),
|
||||
Preferences.getInteger("serial.debug_rate"),
|
||||
Preferences.get("serial.parity").charAt(0),
|
||||
Preferences.getInteger("serial.databits"),
|
||||
new Float(Preferences.get("serial.stopbits")).floatValue());
|
||||
this.monitor = monitor;
|
||||
}
|
||||
|
||||
public Serial() throws SerialException {
|
||||
this(Preferences.get("serial.port"),
|
||||
Preferences.getInteger("serial.debug_rate"),
|
||||
Preferences.get("serial.parity").charAt(0),
|
||||
Preferences.getInteger("serial.databits"),
|
||||
new Float(Preferences.get("serial.stopbits")).floatValue());
|
||||
}
|
||||
|
||||
public Serial(int irate) throws SerialException {
|
||||
this(Preferences.get("serial.port"), irate,
|
||||
Preferences.get("serial.parity").charAt(0),
|
||||
Preferences.getInteger("serial.databits"),
|
||||
new Float(Preferences.get("serial.stopbits")).floatValue());
|
||||
}
|
||||
|
||||
public Serial(String iname, int irate) throws SerialException {
|
||||
this(iname, irate, Preferences.get("serial.parity").charAt(0),
|
||||
Preferences.getInteger("serial.databits"),
|
||||
new Float(Preferences.get("serial.stopbits")).floatValue());
|
||||
}
|
||||
|
||||
public Serial(String iname) throws SerialException {
|
||||
this(iname, Preferences.getInteger("serial.debug_rate"),
|
||||
Preferences.get("serial.parity").charAt(0),
|
||||
Preferences.getInteger("serial.databits"),
|
||||
new Float(Preferences.get("serial.stopbits")).floatValue());
|
||||
}
|
||||
|
||||
public Serial(String iname, int irate,
|
||||
char iparity, int idatabits, float istopbits)
|
||||
throws SerialException {
|
||||
//if (port != null) port.close();
|
||||
//this.parent = parent;
|
||||
//parent.attach(this);
|
||||
|
||||
this.rate = irate;
|
||||
|
||||
parity = SerialPort.PARITY_NONE;
|
||||
if (iparity == 'E') parity = SerialPort.PARITY_EVEN;
|
||||
if (iparity == 'O') parity = SerialPort.PARITY_ODD;
|
||||
|
||||
this.databits = idatabits;
|
||||
|
||||
stopbits = SerialPort.STOPBITS_1;
|
||||
if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5;
|
||||
if (istopbits == 2) stopbits = SerialPort.STOPBITS_2;
|
||||
|
||||
try {
|
||||
port = new SerialPort(iname);
|
||||
port.openPort();
|
||||
port.setParams(rate, databits, stopbits, parity, true, true);
|
||||
port.addEventListener(this);
|
||||
} catch (Exception e) {
|
||||
throw new SerialException(MessageFormat.format("Error opening serial port ''{0}''.", iname), e);
|
||||
}
|
||||
|
||||
if (port == null) {
|
||||
throw new SerialException("Serial port '" + iname + "' not found. Did you select the right one from the Tools > Serial Port menu?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setup() {
|
||||
//parent.registerCall(this, DISPOSE);
|
||||
}
|
||||
|
||||
public void dispose() throws IOException {
|
||||
if (port != null) {
|
||||
try {
|
||||
if (port.isOpened()) {
|
||||
port.closePort(); // close the port
|
||||
}
|
||||
} catch (SerialPortException e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
port = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(MessageConsumer consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
public synchronized void serialEvent(SerialPortEvent serialEvent) {
|
||||
if (serialEvent.isRXCHAR()) {
|
||||
try {
|
||||
byte[] buf = port.readBytes(serialEvent.getEventValue());
|
||||
if (buf.length > 0) {
|
||||
if (bufferLast == buffer.length) {
|
||||
byte temp[] = new byte[bufferLast << 1];
|
||||
System.arraycopy(buffer, 0, temp, 0, bufferLast);
|
||||
buffer = temp;
|
||||
}
|
||||
if (monitor) {
|
||||
System.out.print(new String(buf));
|
||||
}
|
||||
if (this.consumer != null) {
|
||||
this.consumer.message(new String(buf));
|
||||
}
|
||||
}
|
||||
} catch (SerialPortException e) {
|
||||
errorMessage("serialEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that have been read from serial
|
||||
* and are waiting to be dealt with by the user.
|
||||
*/
|
||||
public synchronized int available() {
|
||||
return (bufferLast - bufferIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ignore all the bytes read so far and empty the buffer.
|
||||
*/
|
||||
public synchronized void clear() {
|
||||
bufferLast = 0;
|
||||
bufferIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a number between 0 and 255 for the next byte that's
|
||||
* waiting in the buffer.
|
||||
* Returns -1 if there was no byte (although the user should
|
||||
* first check available() to see if things are ready to avoid this)
|
||||
*/
|
||||
public synchronized int read() {
|
||||
if (bufferIndex == bufferLast) return -1;
|
||||
|
||||
int outgoing = buffer[bufferIndex++] & 0xff;
|
||||
if (bufferIndex == bufferLast) { // rewind
|
||||
bufferIndex = 0;
|
||||
bufferLast = 0;
|
||||
}
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next byte in the buffer as a char.
|
||||
* Returns -1, or 0xffff, if nothing is there.
|
||||
*/
|
||||
public synchronized char readChar() {
|
||||
if (bufferIndex == bufferLast) return (char)(-1);
|
||||
return (char) read();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a byte array of anything that's in the serial buffer.
|
||||
* Not particularly memory/speed efficient, because it creates
|
||||
* a byte array on each read, but it's easier to use than
|
||||
* readBytes(byte b[]) (see below).
|
||||
*/
|
||||
public synchronized byte[] readBytes() {
|
||||
if (bufferIndex == bufferLast) return null;
|
||||
|
||||
int length = bufferLast - bufferIndex;
|
||||
byte outgoing[] = new byte[length];
|
||||
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
|
||||
|
||||
bufferIndex = 0; // rewind
|
||||
bufferLast = 0;
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Grab whatever is in the serial buffer, and stuff it into a
|
||||
* byte buffer passed in by the user. This is more memory/time
|
||||
* efficient than readBytes() returning a byte[] array.
|
||||
* <p/>
|
||||
* Returns an int for how many bytes were read. If more bytes
|
||||
* are available than can fit into the byte array, only those
|
||||
* that will fit are read.
|
||||
*/
|
||||
public synchronized int readBytes(byte outgoing[]) {
|
||||
if (bufferIndex == bufferLast) return 0;
|
||||
|
||||
int length = bufferLast - bufferIndex;
|
||||
if (length > outgoing.length) length = outgoing.length;
|
||||
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
|
||||
|
||||
bufferIndex += length;
|
||||
if (bufferIndex == bufferLast) {
|
||||
bufferIndex = 0; // rewind
|
||||
bufferLast = 0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads from the serial port into a buffer of bytes up to and
|
||||
* including a particular character. If the character isn't in
|
||||
* the serial buffer, then 'null' is returned.
|
||||
*/
|
||||
public synchronized byte[] readBytesUntil(int interesting) {
|
||||
if (bufferIndex == bufferLast) return null;
|
||||
byte what = (byte)interesting;
|
||||
|
||||
int found = -1;
|
||||
for (int k = bufferIndex; k < bufferLast; k++) {
|
||||
if (buffer[k] == what) {
|
||||
found = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == -1) return null;
|
||||
|
||||
int length = found - bufferIndex + 1;
|
||||
byte outgoing[] = new byte[length];
|
||||
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
|
||||
|
||||
bufferIndex = 0; // rewind
|
||||
bufferLast = 0;
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads from the serial port into a buffer of bytes until a
|
||||
* particular character. If the character isn't in the serial
|
||||
* buffer, then 'null' is returned.
|
||||
* <p/>
|
||||
* If outgoing[] is not big enough, then -1 is returned,
|
||||
* and an error message is printed on the console.
|
||||
* If nothing is in the buffer, zero is returned.
|
||||
* If 'interesting' byte is not in the buffer, then 0 is returned.
|
||||
*/
|
||||
public synchronized int readBytesUntil(int interesting, byte outgoing[]) {
|
||||
if (bufferIndex == bufferLast) return 0;
|
||||
byte what = (byte)interesting;
|
||||
|
||||
int found = -1;
|
||||
for (int k = bufferIndex; k < bufferLast; k++) {
|
||||
if (buffer[k] == what) {
|
||||
found = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == -1) return 0;
|
||||
|
||||
int length = found - bufferIndex + 1;
|
||||
if (length > outgoing.length) {
|
||||
System.err.println("readBytesUntil() byte buffer is" +
|
||||
" too small for the " + length +
|
||||
" bytes up to and including char " + interesting);
|
||||
return -1;
|
||||
}
|
||||
//byte outgoing[] = new byte[length];
|
||||
System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
|
||||
|
||||
bufferIndex += length;
|
||||
if (bufferIndex == bufferLast) {
|
||||
bufferIndex = 0; // rewind
|
||||
bufferLast = 0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return whatever has been read from the serial port so far
|
||||
* as a String. It assumes that the incoming characters are ASCII.
|
||||
* <p/>
|
||||
* If you want to move Unicode data, you can first convert the
|
||||
* String to a byte stream in the representation of your choice
|
||||
* (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
|
||||
*/
|
||||
public synchronized String readString() {
|
||||
if (bufferIndex == bufferLast) return null;
|
||||
return new String(readBytes());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Combination of readBytesUntil and readString. See caveats in
|
||||
* each function. Returns null if it still hasn't found what
|
||||
* you're looking for.
|
||||
* <p/>
|
||||
* If you want to move Unicode data, you can first convert the
|
||||
* String to a byte stream in the representation of your choice
|
||||
* (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
|
||||
*/
|
||||
public synchronized String readStringUntil(int interesting) {
|
||||
byte b[] = readBytesUntil(interesting);
|
||||
if (b == null) return null;
|
||||
return new String(b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This will handle both ints, bytes and chars transparently.
|
||||
*/
|
||||
public void write(int what) { // will also cover char
|
||||
try {
|
||||
port.writeInt(what & 0xff);
|
||||
} catch (SerialPortException e) {
|
||||
errorMessage("write", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void write(byte bytes[]) {
|
||||
try {
|
||||
port.writeBytes(bytes);
|
||||
} catch (SerialPortException e) {
|
||||
errorMessage("write", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write a String to the output. Note that this doesn't account
|
||||
* for Unicode (two bytes per char), nor will it send UTF8
|
||||
* characters.. It assumes that you mean to send a byte buffer
|
||||
* (most often the case for networking and serial i/o) and
|
||||
* will only use the bottom 8 bits of each char in the string.
|
||||
* (Meaning that internally it uses String.getBytes)
|
||||
* <p/>
|
||||
* If you want to move Unicode data, you can first convert the
|
||||
* String to a byte stream in the representation of your choice
|
||||
* (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
|
||||
*/
|
||||
public void write(String what) {
|
||||
write(what.getBytes());
|
||||
}
|
||||
|
||||
public void setDTR(boolean state) {
|
||||
try {
|
||||
port.setDTR(state);
|
||||
} catch (SerialPortException e) {
|
||||
errorMessage("setDTR", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRTS(boolean state) {
|
||||
try {
|
||||
port.setRTS(state);
|
||||
} catch (SerialPortException e) {
|
||||
errorMessage("setRTS", e);
|
||||
}
|
||||
}
|
||||
|
||||
static public List<String> list() {
|
||||
return Arrays.asList(SerialPortList.getPortNames());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* General error reporting, all corraled here just in case
|
||||
* I think of something slightly more intelligent to do.
|
||||
*/
|
||||
static public void errorMessage(String where, Throwable e) {
|
||||
System.err.println("Error inside Serial." + where + "()");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class SerialMenuListener implements ItemListener {
|
||||
//public SerialMenuListener() { }
|
||||
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
int count = serialMenu.getItemCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
((CheckboxMenuItem)serialMenu.getItem(i)).setState(false);
|
||||
}
|
||||
CheckboxMenuItem item = (CheckboxMenuItem)e.getSource();
|
||||
item.setState(true);
|
||||
String name = item.getLabel();
|
||||
//System.out.println(item.getLabel());
|
||||
PdeBase.properties.put("serial.port", name);
|
||||
//System.out.println("set to " + get("serial.port"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
protected Vector buildPortList() {
|
||||
// get list of names for serial ports
|
||||
// have the default port checked (if present)
|
||||
Vector list = new Vector();
|
||||
|
||||
//SerialMenuListener listener = new SerialMenuListener();
|
||||
boolean problem = false;
|
||||
|
||||
// if this is failing, it may be because
|
||||
// lib/javax.comm.properties is missing.
|
||||
// java is weird about how it searches for java.comm.properties
|
||||
// so it tends to be very fragile. i.e. quotes in the CLASSPATH
|
||||
// environment variable will hose things.
|
||||
try {
|
||||
//System.out.println("building port list");
|
||||
Enumeration portList = CommPortIdentifier.getPortIdentifiers();
|
||||
while (portList.hasMoreElements()) {
|
||||
CommPortIdentifier portId =
|
||||
(CommPortIdentifier) portList.nextElement();
|
||||
//System.out.println(portId);
|
||||
|
||||
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
|
||||
//if (portId.getName().equals(port)) {
|
||||
String name = portId.getName();
|
||||
//CheckboxMenuItem mi =
|
||||
//new CheckboxMenuItem(name, name.equals(defaultName));
|
||||
|
||||
//mi.addItemListener(listener);
|
||||
//serialMenu.add(mi);
|
||||
list.addElement(name);
|
||||
}
|
||||
}
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
e.printStackTrace();
|
||||
problem = true;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println("exception building serial menu");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//if (serialMenu.getItemCount() == 0) {
|
||||
//System.out.println("dimming serial menu");
|
||||
//serialMenu.setEnabled(false);
|
||||
//}
|
||||
|
||||
// only warn them if this is the first time
|
||||
if (problem && PdeBase.firstTime) {
|
||||
JOptionPane.showMessageDialog(this, //frame,
|
||||
"Serial port support not installed.\n" +
|
||||
"Check the readme for instructions\n" +
|
||||
"if you need to use the serial port. ",
|
||||
"Serial Port Warning",
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Copyright (c) 2007 David A. Mellis
|
||||
|
||||
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;
|
||||
|
||||
public class SerialException extends Exception {
|
||||
public SerialException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SerialException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SerialException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public SerialException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 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;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for dealing with parser/compiler output.
|
||||
* <P>
|
||||
* Different instances of MessageStream need to do different things with
|
||||
* messages. In particular, a stream instance used for parsing output from
|
||||
* the compiler compiler has to interpret its messages differently than one
|
||||
* parsing output from the runtime.
|
||||
* <P>
|
||||
* Classes which consume messages and do something with them
|
||||
* should implement this interface.
|
||||
*/
|
||||
public interface MessageConsumer {
|
||||
|
||||
public void message(String s);
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-06 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 java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
* Slurps up messages from compiler.
|
||||
*/
|
||||
public class MessageSiphon implements Runnable {
|
||||
|
||||
private final BufferedReader streamReader;
|
||||
private final MessageConsumer consumer;
|
||||
|
||||
private Thread thread;
|
||||
private boolean canRun;
|
||||
|
||||
public MessageSiphon(InputStream stream, MessageConsumer consumer) {
|
||||
this.streamReader = new BufferedReader(new InputStreamReader(stream));
|
||||
this.consumer = consumer;
|
||||
this.canRun = true;
|
||||
|
||||
thread = new Thread(this);
|
||||
// don't set priority too low, otherwise exceptions won't
|
||||
// bubble up in time (i.e. compile errors have a weird delay)
|
||||
//thread.setPriority(Thread.MIN_PRIORITY);
|
||||
thread.setPriority(Thread.MAX_PRIORITY - 1);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// process data until we hit EOF; this will happily block
|
||||
// (effectively sleeping the thread) until new data comes in.
|
||||
// when the program is finally done, null will come through.
|
||||
//
|
||||
String currentLine;
|
||||
while (canRun && (currentLine = streamReader.readLine()) != null) {
|
||||
// \n is added again because readLine() strips it out
|
||||
//EditorConsole.systemOut.println("messaging in");
|
||||
consumer.message(currentLine + "\n");
|
||||
//EditorConsole.systemOut.println("messaging out");
|
||||
}
|
||||
//EditorConsole.systemOut.println("messaging thread done");
|
||||
} catch (NullPointerException npe) {
|
||||
// Fairly common exception during shutdown
|
||||
} catch (SocketException e) {
|
||||
// socket has been close while we were wainting for data. nothing to see here, move along
|
||||
} catch (Exception e) {
|
||||
// On Linux and sometimes on Mac OS X, a "bad file descriptor"
|
||||
// message comes up when closing an applet that's run externally.
|
||||
// That message just gets supressed here..
|
||||
String mess = e.getMessage();
|
||||
if ((mess != null) &&
|
||||
(mess.indexOf("Bad file descriptor") != -1)) {
|
||||
//if (e.getMessage().indexOf("Bad file descriptor") == -1) {
|
||||
//System.err.println("MessageSiphon err " + e);
|
||||
//e.printStackTrace();
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until the MessageSiphon thread is complete.
|
||||
public void join() throws java.lang.InterruptedException {
|
||||
// Grab a temp copy in case another thread nulls the "thread"
|
||||
// member variable
|
||||
Thread t = thread;
|
||||
if (t != null) t.join();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.canRun = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
||||
|
||||
/*
|
||||
Part of the Processing project - http://processing.org
|
||||
|
||||
Copyright (c) 2004-08 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;
|
||||
|
||||
|
||||
/**
|
||||
* An exception with a line number attached that occurs
|
||||
* during either compile time or run time.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class RunnerException extends Exception {
|
||||
protected String message;
|
||||
protected int codeIndex;
|
||||
protected int codeLine;
|
||||
protected int codeColumn;
|
||||
protected boolean showStackTrace;
|
||||
|
||||
|
||||
public RunnerException(String message) {
|
||||
this(message, true);
|
||||
}
|
||||
|
||||
public RunnerException(String message, boolean showStackTrace) {
|
||||
this(message, -1, -1, -1, showStackTrace);
|
||||
}
|
||||
|
||||
public RunnerException(String message, int file, int line) {
|
||||
this(message, file, line, -1, true);
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(String message, int file, int line, int column) {
|
||||
this(message, file, line, column, true);
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(String message, int file, int line, int column,
|
||||
boolean showStackTrace) {
|
||||
this.message = message;
|
||||
this.codeIndex = file;
|
||||
this.codeLine = line;
|
||||
this.codeColumn = column;
|
||||
this.showStackTrace = showStackTrace;
|
||||
}
|
||||
|
||||
|
||||
public RunnerException(Exception e) {
|
||||
super(e);
|
||||
this.showStackTrace = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override getMessage() in Throwable, so that I can set
|
||||
* the message text outside the constructor.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeIndex() {
|
||||
return codeIndex;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeIndex(int index) {
|
||||
codeIndex = index;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasCodeIndex() {
|
||||
return codeIndex != -1;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeLine() {
|
||||
return codeLine;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeLine(int line) {
|
||||
this.codeLine = line;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasCodeLine() {
|
||||
return codeLine != -1;
|
||||
}
|
||||
|
||||
|
||||
public void setCodeColumn(int column) {
|
||||
this.codeColumn = column;
|
||||
}
|
||||
|
||||
|
||||
public int getCodeColumn() {
|
||||
return codeColumn;
|
||||
}
|
||||
|
||||
|
||||
public void showStackTrace() {
|
||||
showStackTrace = true;
|
||||
}
|
||||
|
||||
|
||||
public void hideStackTrace() {
|
||||
showStackTrace = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Nix the java.lang crap out of an exception message
|
||||
* because it scares the children.
|
||||
* <P>
|
||||
* This function must be static to be used with super()
|
||||
* in each of the constructors above.
|
||||
*/
|
||||
/*
|
||||
static public final String massage(String msg) {
|
||||
if (msg.indexOf("java.lang.") == 0) {
|
||||
//int dot = msg.lastIndexOf('.');
|
||||
msg = msg.substring("java.lang.".length());
|
||||
}
|
||||
return msg;
|
||||
//return (dot == -1) ? msg : msg.substring(dot+1);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public void printStackTrace() {
|
||||
if (showStackTrace) {
|
||||
super.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package processing.app.helpers;
|
||||
|
||||
//import processing.app.Base;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.Base;
|
||||
|
||||
public class ProcessUtils {
|
||||
|
||||
public static Process exec(String[] command) throws IOException {
|
||||
// No problems on linux and mac
|
||||
if (!Base.isWindows()) {
|
||||
return Runtime.getRuntime().exec(command);
|
||||
}
|
||||
|
||||
// Brutal hack to workaround windows command line parsing.
|
||||
// http://stackoverflow.com/questions/5969724/java-runtime-exec-fails-to-escape-characters-properly
|
||||
// http://msdn.microsoft.com/en-us/library/a1y7w461.aspx
|
||||
// http://bugs.sun.com/view_bug.do?bug_id=6468220
|
||||
// http://bugs.sun.com/view_bug.do?bug_id=6518827
|
||||
String[] cmdLine = new String[command.length];
|
||||
for (int i = 0; i < command.length; i++)
|
||||
cmdLine[i] = command[i].replace("\"", "\\\"");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdLine);
|
||||
Map<String, String> env = pb.environment();
|
||||
env.put("CYGWIN", "nodosfilewarning");
|
||||
return pb.start();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue