1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-13 10:29:35 +01:00

Serial.dispose() throws IOException

SerialException extends IOException
SerialMonitor is now a subclass of a generic AbstractMonitor; introducing NetworkMonitor
UploaderFactory becomes PerPortObjectFactory and can build AbstractMonitors
favouring IOException over SerialException
collecting constants in Constants
made MessageSiphon stoppable
This commit is contained in:
Federico Fissore 2013-05-29 16:14:17 +02:00
parent 556c6ea5c1
commit 376b0f8b3f
16 changed files with 396 additions and 241 deletions

View File

@ -0,0 +1,183 @@
package processing.app;
import processing.app.debug.MessageConsumer;
import processing.core.PApplet;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DefaultCaret;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import static processing.app.I18n._;
public abstract class AbstractMonitor extends JFrame implements MessageConsumer {
protected JTextArea textArea;
protected JScrollPane scrollPane;
protected JTextField textField;
protected JButton sendButton;
protected JCheckBox autoscrollBox;
protected JComboBox lineEndings;
protected JComboBox serialRates;
protected int serialRate;
public AbstractMonitor(String title) {
super(title);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) {
try {
close();
} catch (IOException e) {
// ignore
}
}
});
// obvious, no?
KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(wc, "close");
getRootPane().getActionMap().put("close", (new AbstractAction() {
public void actionPerformed(ActionEvent event) {
try {
close();
} catch (IOException e) {
// ignore
}
setVisible(false);
}
}));
getContentPane().setLayout(new BorderLayout());
Font consoleFont = Theme.getFont("console.font");
Font editorFont = Preferences.getFont("editor.font");
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
textArea = new JTextArea(16, 40);
textArea.setEditable(false);
textArea.setFont(font);
// don't automatically update the caret. that way we can manually decide
// whether or not to do so based on the autoscroll checkbox.
((DefaultCaret) textArea.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
scrollPane = new JScrollPane(textArea);
getContentPane().add(scrollPane, BorderLayout.CENTER);
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
pane.setBorder(new EmptyBorder(4, 4, 4, 4));
textField = new JTextField(40);
sendButton = new JButton(_("Send"));
pane.add(textField);
pane.add(Box.createRigidArea(new Dimension(4, 0)));
pane.add(sendButton);
getContentPane().add(pane, BorderLayout.NORTH);
pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
pane.setBorder(new EmptyBorder(4, 4, 4, 4));
autoscrollBox = new JCheckBox(_("Autoscroll"), true);
lineEndings = new JComboBox(new String[]{_("No line ending"), _("Newline"), _("Carriage return"), _("Both NL & CR")});
lineEndings.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Preferences.setInteger("serial.line_ending", lineEndings.getSelectedIndex());
}
});
if (Preferences.get("serial.line_ending") != null) {
lineEndings.setSelectedIndex(Preferences.getInteger("serial.line_ending"));
}
lineEndings.setMaximumSize(lineEndings.getMinimumSize());
String[] serialRateStrings = {
"300", "1200", "2400", "4800", "9600",
"19200", "57600", "115200"
};
serialRates = new JComboBox();
for (int i = 0; i < serialRateStrings.length; i++)
serialRates.addItem(serialRateStrings[i] + " " + _("baud"));
serialRate = Preferences.getInteger("serial.debug_rate");
serialRates.setSelectedItem(serialRate + " " + _("baud"));
serialRates.setMaximumSize(serialRates.getMinimumSize());
pane.add(autoscrollBox);
pane.add(Box.createHorizontalGlue());
pane.add(lineEndings);
pane.add(Box.createRigidArea(new Dimension(8, 0)));
pane.add(serialRates);
getContentPane().add(pane, BorderLayout.SOUTH);
pack();
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (Preferences.get("last.screen.height") != null) {
// if screen size has changed, the window coordinates no longer
// make sense, so don't use them unless they're identical
int screenW = Preferences.getInteger("last.screen.width");
int screenH = Preferences.getInteger("last.screen.height");
if ((screen.width == screenW) && (screen.height == screenH)) {
String locationStr = Preferences.get("last.serial.location");
if (locationStr != null) {
int[] location = PApplet.parseInt(PApplet.split(locationStr, ','));
setPlacement(location);
}
}
}
}
public void onSerialRateChange(ActionListener listener) {
serialRates.addActionListener(listener);
}
public void onSendCommand(ActionListener listener) {
textField.addActionListener(listener);
sendButton.addActionListener(listener);
}
protected void setPlacement(int[] location) {
setBounds(location[0], location[1], location[2], location[3]);
}
protected int[] getPlacement() {
int[] location = new int[4];
// Get the dimensions of the Frame
Rectangle bounds = getBounds();
location[0] = bounds.x;
location[1] = bounds.y;
location[2] = bounds.width;
location[3] = bounds.height;
return location;
}
public void message(final String s) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(s);
if (autoscrollBox.isSelected()) {
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}
});
}
public abstract void open() throws IOException;
public abstract void close() throws IOException;
}

View File

@ -936,7 +936,11 @@ public class Base {
// This will store the sketch count as zero
editors.remove(editor);
Editor.serialMonitor.closeSerialPort();
try {
Editor.serialMonitor.close();
} catch (IOException e) {
//ignore
}
storeSketches();
// Save out the current prefs state
@ -974,7 +978,11 @@ public class Base {
// If quit is canceled, this will be replaced anyway
// by a later handleQuit() that is not canceled.
storeSketches();
Editor.serialMonitor.closeSerialPort();
try {
Editor.serialMonitor.close();
} catch (IOException e) {
// ignore
}
if (handleQuitEach()) {
// make sure running sketches close before quitting

View File

@ -0,0 +1,9 @@
package processing.app;
import java.util.regex.Pattern;
public class Constants {
public static final Pattern IPV4_ADDRESS = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
}

View File

@ -99,7 +99,7 @@ public class Editor extends JFrame implements RunnerListener {
static List<JMenu> boardsMenus;
static JMenu serialMenu;
static SerialMonitor serialMonitor;
static AbstractMonitor serialMonitor;
EditorHeader header;
EditorStatus status;
@ -204,7 +204,7 @@ public class Editor extends JFrame implements RunnerListener {
//sketchbook = new Sketchbook(this);
if (serialMonitor == null) {
serialMonitor = new SerialMonitor(Preferences.get("serial.port"));
serialMonitor = new PerPortObjectFactory().newMonitor(Preferences.get("serial.port"), base);
serialMonitor.setIconImage(getIconImage());
}
@ -964,9 +964,13 @@ public class Editor extends JFrame implements RunnerListener {
Preferences.set("serial.port.file", name.substring(5));
else
Preferences.set("serial.port.file", name);
serialMonitor.closeSerialPort();
try {
serialMonitor.close();
} catch (IOException e) {
// ignore
}
serialMonitor.setVisible(false);
serialMonitor = new SerialMonitor(Preferences.get("serial.port"));
serialMonitor = new PerPortObjectFactory().newMonitor(Preferences.get("serial.port"), base);
onBoardOrPortChange();
@ -2401,7 +2405,7 @@ public class Editor extends JFrame implements RunnerListener {
public void run() {
try {
serialMonitor.closeSerialPort();
serialMonitor.close();
serialMonitor.setVisible(false);
uploading = true;
@ -2437,7 +2441,7 @@ public class Editor extends JFrame implements RunnerListener {
public void run() {
try {
serialMonitor.closeSerialPort();
serialMonitor.close();
serialMonitor.setVisible(false);
uploading = true;
@ -2507,9 +2511,11 @@ public class Editor extends JFrame implements RunnerListener {
if (uploading) return;
try {
serialMonitor.openSerialPort();
serialMonitor.open();
serialMonitor.setVisible(true);
} catch (SerialException e) {
} catch (ConnectException e) {
statusError(_("Unable to connect: is the sketch using the bridge?"));
} catch (IOException e) {
statusError(e);
}
}

View File

@ -0,0 +1,73 @@
package processing.app;
import processing.app.debug.MessageSiphon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.regex.Matcher;
public class NetworkMonitor extends AbstractMonitor {
private static final int MAX_CONNECT_RETRIES = 3;
private final String ipAddress;
private final Base base;
private Socket socket;
private MessageSiphon consumer;
public NetworkMonitor(String port, Base base) {
super(port);
this.base = base;
Matcher matcher = Constants.IPV4_ADDRESS.matcher(port);
matcher.find();
this.ipAddress = matcher.group();
onSendCommand(new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
socket.getOutputStream().write(textField.getText().getBytes());
socket.getOutputStream().write('\n');
socket.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
textField.setText("");
}
});
}
@Override
public void open() throws IOException {
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, 6571), 5000);
consumer = new MessageSiphon(socket.getInputStream(), this);
return;
} catch (IOException e) {
socket = null;
throw e;
}
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
// ignore
}
}
@Override
public void close() throws IOException {
if (socket != null) {
consumer.stop();
socket.close();
textArea.setText("");
}
}
}

View File

@ -0,0 +1,28 @@
package processing.app;
import processing.app.debug.BasicUploader;
import processing.app.debug.HttpUploader;
import processing.app.debug.TargetBoard;
import processing.app.debug.Uploader;
import java.util.regex.Pattern;
public class PerPortObjectFactory {
public Uploader newUploader(TargetBoard board, String port) {
if ("true".equals(board.getPreferences().get("upload.via_http")) && Constants.IPV4_ADDRESS.matcher(port).find()) {
return new HttpUploader(port);
}
return new BasicUploader();
}
public AbstractMonitor newMonitor(String port, Base base) {
if (Constants.IPV4_ADDRESS.matcher(port).find()) {
return new NetworkMonitor(port, base);
}
return new SerialMonitor(port);
}
}

View File

@ -219,24 +219,15 @@ public class Serial implements SerialPortEventListener {
//public void key(java.awt.event.KeyEvent e) { }
public void dispose() {
try {
// do io streams need to be closed first?
if (input != null) input.close();
if (output != null) output.close();
public void dispose() throws IOException {
// do io streams need to be closed first?
if (input != null) input.close();
if (output != null) output.close();
} catch (Exception e) {
e.printStackTrace();
}
input = null;
output = null;
try {
if (port != null) port.close(); // close the port
} catch (Exception e) {
e.printStackTrace();
}
if (port != null) port.close(); // close the port
port = null;
}

View File

@ -20,7 +20,9 @@
package processing.app;
public class SerialException extends Exception {
import java.io.IOException;
public class SerialException extends IOException {
public SerialException() {
super();
}

View File

@ -18,200 +18,74 @@
package processing.app;
import processing.app.debug.MessageConsumer;
import processing.core.*;
import static processing.app.I18n._;
import processing.core.PApplet;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
public class SerialMonitor extends JFrame implements MessageConsumer {
public class SerialMonitor extends AbstractMonitor {
private final String port;
private Serial serial;
private String port;
private JTextArea textArea;
private JScrollPane scrollPane;
private JTextField textField;
private JButton sendButton;
private JCheckBox autoscrollBox;
private JComboBox lineEndings;
private JComboBox serialRates;
private int serialRate;
public SerialMonitor(String port) {
super(port);
this.port = port;
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeSerialPort();
}
});
// obvious, no?
KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE;
getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(wc, "close");
getRootPane().getActionMap().put("close", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
closeSerialPort();
setVisible(false);
}});
getContentPane().setLayout(new BorderLayout());
Font consoleFont = Theme.getFont("console.font");
Font editorFont = Preferences.getFont("editor.font");
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
textArea = new JTextArea(16, 40);
textArea.setEditable(false);
textArea.setFont(font);
// don't automatically update the caret. that way we can manually decide
// whether or not to do so based on the autoscroll checkbox.
((DefaultCaret)textArea.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
scrollPane = new JScrollPane(textArea);
getContentPane().add(scrollPane, BorderLayout.CENTER);
JPanel pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
pane.setBorder(new EmptyBorder(4, 4, 4, 4));
textField = new JTextField(40);
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send(textField.getText());
textField.setText("");
}});
sendButton = new JButton(_("Send"));
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send(textField.getText());
textField.setText("");
}});
pane.add(textField);
pane.add(Box.createRigidArea(new Dimension(4, 0)));
pane.add(sendButton);
getContentPane().add(pane, BorderLayout.NORTH);
pane = new JPanel();
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
pane.setBorder(new EmptyBorder(4, 4, 4, 4));
autoscrollBox = new JCheckBox(_("Autoscroll"), true);
lineEndings = new JComboBox(new String[] { _("No line ending"), _("Newline"), _("Carriage return"), _("Both NL & CR") });
lineEndings.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
Preferences.setInteger("serial.line_ending", lineEndings.getSelectedIndex());
}
});
if (Preferences.get("serial.line_ending") != null) {
lineEndings.setSelectedIndex(Preferences.getInteger("serial.line_ending"));
}
lineEndings.setMaximumSize(lineEndings.getMinimumSize());
String[] serialRateStrings = {
"300","1200","2400","4800","9600",
"19200","57600","115200"
};
serialRates = new JComboBox();
for (int i = 0; i < serialRateStrings.length; i++)
serialRates.addItem(serialRateStrings[i] + " " + _("baud"));
serialRate = Preferences.getInteger("serial.debug_rate");
serialRates.setSelectedItem(serialRate + " " + _("baud"));
serialRates.addActionListener(new ActionListener() {
onSerialRateChange(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String wholeString = (String) serialRates.getSelectedItem();
String rateString = wholeString.substring(0, wholeString.indexOf(' '));
serialRate = Integer.parseInt(rateString);
Preferences.set("serial.debug_rate", rateString);
closeSerialPort();
try {
close();
Thread.sleep(100); // Wait for serial port to properly close
openSerialPort();
} catch (SerialException e) {
open();
} catch (IOException e) {
System.err.println(e);
} catch (InterruptedException e) {
e.printStackTrace();
}
}});
serialRates.setMaximumSize(serialRates.getMinimumSize());
pane.add(autoscrollBox);
pane.add(Box.createHorizontalGlue());
pane.add(lineEndings);
pane.add(Box.createRigidArea(new Dimension(8, 0)));
pane.add(serialRates);
getContentPane().add(pane, BorderLayout.SOUTH);
pack();
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (Preferences.get("last.screen.height") != null) {
// if screen size has changed, the window coordinates no longer
// make sense, so don't use them unless they're identical
int screenW = Preferences.getInteger("last.screen.width");
int screenH = Preferences.getInteger("last.screen.height");
if ((screen.width == screenW) && (screen.height == screenH)) {
String locationStr = Preferences.get("last.serial.location");
if (locationStr != null) {
int[] location = PApplet.parseInt(PApplet.split(locationStr, ','));
setPlacement(location);
}
}
}
}
protected void setPlacement(int[] location) {
setBounds(location[0], location[1], location[2], location[3]);
}
});
protected int[] getPlacement() {
int[] location = new int[4];
// Get the dimensions of the Frame
Rectangle bounds = getBounds();
location[0] = bounds.x;
location[1] = bounds.y;
location[2] = bounds.width;
location[3] = bounds.height;
return location;
onSendCommand(new ActionListener() {
public void actionPerformed(ActionEvent e) {
send(textField.getText());
textField.setText("");
}
});
}
private void send(String s) {
if (serial != null) {
switch (lineEndings.getSelectedIndex()) {
case 1: s += "\n"; break;
case 2: s += "\r"; break;
case 3: s += "\r\n"; break;
case 1:
s += "\n";
break;
case 2:
s += "\r";
break;
case 3:
s += "\r\n";
break;
}
serial.write(s);
}
}
public void openSerialPort() throws SerialException {
public void open() throws IOException {
if (serial != null) return;
serial = new Serial(port, serialRate);
serial.addListener(this);
}
public void closeSerialPort() {
public void close() throws IOException {
if (serial != null) {
int[] location = getPlacement();
String locationStr = PApplet.join(PApplet.str(location), ",");
@ -221,14 +95,4 @@ public class SerialMonitor extends JFrame implements MessageConsumer {
serial = null;
}
}
public void message(final String s) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(s);
if (autoscrollBox.isSelected()) {
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}});
}
}

View File

@ -1580,7 +1580,7 @@ public class Sketch {
* Handle export to applet.
*/
public boolean exportApplet(String appletPath, boolean usingProgrammer)
throws RunnerException, IOException, SerialException {
throws RunnerException, IOException {
prepare();
@ -1658,12 +1658,12 @@ public class Sketch {
System.out.println(_("Low memory available, stability problems may occur"));
}
protected boolean upload(String buildPath, String suggestedClassName, boolean usingProgrammer) throws RunnerException, SerialException {
protected boolean upload(String buildPath, String suggestedClassName, boolean usingProgrammer) throws RunnerException {
TargetPlatform target = Base.getTargetPlatform();
String board = Preferences.get("board");
Uploader uploader = new UploaderFactory().newUploader(target.getBoards().get(board), Preferences.get("serial.port"));
Uploader uploader = new PerPortObjectFactory().newUploader(target.getBoards().get(board), Preferences.get("serial.port"));
boolean success = false;
do {

View File

@ -45,7 +45,7 @@ public class BasicUploader extends Uploader {
public boolean uploadUsingPreferences(String buildPath, String className,
boolean usingProgrammer)
throws RunnerException, SerialException {
throws RunnerException {
// FIXME: Preferences should be reorganized
TargetPlatform targetPlatform = Base.getTargetPlatform();
PreferencesMap prefs = Preferences.getMap();
@ -152,7 +152,11 @@ public class BasicUploader extends Uploader {
Thread.sleep(250);
}
} else {
Serial.touchPort(uploadPort, 9600);
try {
Serial.touchPort(uploadPort, 9600);
} catch (SerialException e) {
throw new RunnerException(e);
}
}
}
} catch (InterruptedException ex) {

View File

@ -7,8 +7,8 @@ import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import processing.app.Base;
import processing.app.Constants;
import processing.app.Preferences;
import processing.app.SerialException;
import processing.app.helpers.PreferencesMap;
import java.io.*;
@ -19,7 +19,6 @@ import java.util.regex.Pattern;
public class HttpUploader extends Uploader {
private static final Pattern IPV4_ADDRESS = Pattern.compile("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})");
private static final String PROTOCOL = "http://";
/*
@ -34,11 +33,11 @@ public class HttpUploader extends Uploader {
public HttpUploader(String port) {
this.client = new HttpClient();
Matcher matcher = IPV4_ADDRESS.matcher(port);
Matcher matcher = Constants.IPV4_ADDRESS.matcher(port);
if (!matcher.find()) {
throw new IllegalArgumentException(port);
}
this.ipAddress = matcher.group(1);
this.ipAddress = matcher.group();
this.baseUrl = PROTOCOL + ipAddress + "/cgi-bin/luci/arduino";
}
@ -51,7 +50,7 @@ public class HttpUploader extends Uploader {
}
@Override
public boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) throws RunnerException, SerialException {
public boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer) throws RunnerException {
if (usingProgrammer) {
System.err.println("Http upload using programmer not supported");
return false;

View File

@ -23,27 +23,32 @@
package processing.app.debug;
import java.io.*;
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 {
BufferedReader streamReader;
Thread thread;
MessageConsumer consumer;
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.setPriority(Thread.MAX_PRIORITY - 1);
thread.start();
}
@ -55,36 +60,35 @@ public class MessageSiphon implements Runnable {
// when the program is finally done, null will come through.
//
String currentLine;
while ((currentLine = streamReader.readLine()) != null) {
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");
thread = null;
} catch (NullPointerException npe) {
// Fairly common exception during shutdown
thread = null;
} 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)) {
(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"
@ -93,7 +97,8 @@ public class MessageSiphon implements Runnable {
if (t != null) t.join();
}
public Thread getThread() {
return thread;
public void stop() {
this.canRun = false;
}
}

View File

@ -52,7 +52,7 @@ public abstract class Uploader implements MessageConsumer {
boolean verbose;
public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer)
throws RunnerException, SerialException;
throws RunnerException;
public abstract boolean burnBootloader() throws RunnerException;

View File

@ -1,18 +0,0 @@
package processing.app.debug;
import java.util.Map;
import java.util.regex.Pattern;
public class UploaderFactory {
private static final Pattern IPV4_ADDRESS = Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
public Uploader newUploader(TargetBoard board, String port) {
if ("true".equals(board.getPreferences().get("upload.via_http")) && IPV4_ADDRESS.matcher(port).find()) {
return new HttpUploader(port);
}
return new BasicUploader();
}
}

View File

@ -3,6 +3,7 @@ package processing.app.debug;
import org.junit.Before;
import org.junit.Test;
import processing.app.AbstractWithPreferencesTest;
import processing.app.PerPortObjectFactory;
import processing.app.helpers.PreferencesMap;
import java.io.File;
@ -23,7 +24,7 @@ public class UploaderFactoryTest extends AbstractWithPreferencesTest {
@Test
public void shouldCreateAnInstanceOfHttpUploader() throws Exception {
TargetBoard board = targetPackage.getPlatforms().get("avr").getBoards().get("yun");
Uploader uploader = new UploaderFactory().newUploader(board, "192.168.0.1 (yun)");
Uploader uploader = new PerPortObjectFactory().newUploader(board, "192.168.0.1 (yun)");
assertTrue(uploader instanceof HttpUploader);
}
@ -31,7 +32,7 @@ public class UploaderFactoryTest extends AbstractWithPreferencesTest {
@Test
public void shouldCreateAnInstanceOfBasicUploaderWhenHTTPIsUnsupported() throws Exception {
TargetBoard board = targetPackage.getPlatforms().get("avr").getBoards().get("uno");
Uploader uploader = new UploaderFactory().newUploader(board, "192.168.0.1 (myyun)");
Uploader uploader = new PerPortObjectFactory().newUploader(board, "192.168.0.1 (myyun)");
assertTrue(uploader instanceof BasicUploader);
}
@ -39,7 +40,7 @@ public class UploaderFactoryTest extends AbstractWithPreferencesTest {
@Test
public void shouldCreateAnInstanceOfBasicUploaderWhenPortIsSerial() throws Exception {
TargetBoard board = targetPackage.getPlatforms().get("avr").getBoards().get("uno");
Uploader uploader = new UploaderFactory().newUploader(board, "/dev/ttyACM0 (Arduino Leonardo)");
Uploader uploader = new PerPortObjectFactory().newUploader(board, "/dev/ttyACM0 (Arduino Leonardo)");
assertTrue(uploader instanceof BasicUploader);
}