I'm creating a client window that retrieves from a javaSpace, this is the code I'm using.
/**
* Create the frame.
*/
public Client()
{
space = SpaceUtils.getSpace();
if (space == null)
{
System.err.println("Failed to find the javaspace");
System.exit(1);
}
initFrame();
setVisible(true);
processPrintJobs();
}
The window is generated inside of initFrame(); and then processPrintJobs checks to see if there are any new messages. If I comment out the processPrintJobs() method call then the window draws correctly but if the method call is there, the window just shows a blank square.
Its like the window is not being created correctly due to the process being checked lots of times, which makes no sense as the window is created before the while loop is run.
public void processPrintJobs()
{
while (true)
{
try
{
Message template = new Message();
if (channel == null)
{
System.out.println("No channel given");
} else
{
template.Channel = channel;
// System.out.println(channel);
template.position = new Integer(getNumber() + 1);
Message msg = (Message) space.read(template, null,
Long.MAX_VALUE);
messageList.append(msg.execute());
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}
This infinite while loop will block the EDT.
while (true)
Simply calling
setVisible(true);
does not guarantee that the JFrame will be painted immediately. Any long-lived processes should be handled by a SwingWorker.
Use
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
processPrintJobs();
}
}
But in general, the architecture of your application is missing some aspects.
Like a thread or whatever.
More:
You could for instance use a swing Timer, for one single job every tick.
import javax.swing.Timer;
To be called at the end of the Client constructor.
Timer printJobsTimer = new Timer(100, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Process a print job:
if (channel != null) {
Message template = new Message();
template.Channel = channel;
template.position = new Integer(getNumber() + 1);
Message msg = (Message) space.read(template, null,
Long.MAX_VALUE);
messageList.append(msg.execute());
}
}
});
printJobsTimer.setInitialDelay(100);
printJobsTimer.start();
For the rest, consisting naming would have been fine: just class names starting with a capital and other names with a small letter.
Related
I am currently making a boardgame that allows two player through a socket. I am also trying to add in a game chat, but reguardless I need a way for the Frame class to act as normal (Jbuttons, enter text into a jscroll area, etc) but also send & look for incoming objects. I figured implementing runnable would be the best option.
here is my run method:
public void run() {
while(running){
Object obj = null;
try {
obj = connection.receiveObjects();
} catch (ClassNotFoundException) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
running = false;
if(obj != null){
if(obj instanceof String){
showMessage((String)obj);
}
}
}
}
My connection class is just a server or a client, and uses these methods:
public void sendObjects(Object obj) throws IOException{
output.writeObject(obj);
output.flush();
}
public Object receiveObjects() throws IOException, ClassNotFoundException{
return input.readObject();
}
At the Frame class's constructor I call
Thread thread = new Thread(this);
thread.start();
In hopes that the run method will not interfere with the actionPerformed method. But to my dismay, when I click a jbutton (all it does is call the send() method), the program freezes, and nothing is sent over.
Here is the other necessary code:
private JTextArea textBox;
private JScrollPane pane;
private JTextArea userText;
private JScrollPane userPane;
private void send(){
String message = "YOU- " + userText.getText();
userText.setText("");
String totalMessage = textBox.getText();
textBox.setText(totalMessage + "/n" + message);
try {
connection.sendObjects(message);
} catch (IOException e) {
e.printStackTrace();
}
}
public void showMessage(String s){
String totalMessage = "Opponent- " + textBox.getText();
textBox.setText(totalMessage + "/n" + s);
}
My hope is that once I get the chat working, I can also add in sending over the pieces and calling other methods to do everything else I need (via instanceof). I could probably make a separate class that implements runnable to just deal with data transfer, but I was hoping I could do it all in one class, and do not see why I cannot. I did spend at least an hour and a half looking up multithreading, but I could not figure my problem out. I apologize If I am looking over anything apparent, but mutithreading and sockets are far beyond my comfort zone and AP Comp sci class education.
Besides the UI thread, you need:
one thread to constantly listen for incoming data
one thread to send data
You have #1 but not #2, so modify send() method as follows:
private void send() {
// Do the UI tasks on the UI thread
final String message = "YOU- " + userText.getText();
userText.setText("");
String totalMessage = textBox.getText();
textBox.setText(totalMessage + "\n" + message);
// Start new thread to do the networking (send data)
new Thread(new Runnable() {
#Override
public void run() {
try {
connection.sendObjects(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
I am creating an IRC bot in Java. I made a class called "loginHandler" which asks the user to input the login info, such as nick/pass/server/etc... When the user is done, the "Connect" button is clicked, which initializes the IRC handler class, bot. See the code:
package irc_bot;
import java.awt.BorderLayout;
//more imports are here but they are irrelevant right now
public class loginHandler extends JFrame {
private static final long serialVersionUID = 6742568354533287421L;
private bot irc_bot;
private String username;
private String password;
private int[] ports={80,6667};
//.....
//gui vars
private final JTextField usernameInput;
private final JTextField passwordInput;
//......
public loginHandler(){
super("Login data");
Panel = new JPanel(new BorderLayout());
Panel.setLayout(new GridLayout(13, 1));
JLabel label = new JLabel("Hover over labels for information!!");
Panel.add(label);
label = new JLabel("Username: ");
label.setToolTipText("Type in your username!");
Panel.add(label);
usernameInput=new JTextField("");
usernameInput.setEditable(true);
Panel.add(usernameInput);
label = new JLabel("Password: ");
label.setToolTipText("Type in your password! Starts with 'oauth:'");
Panel.add(label);
passwordInput=new JPasswordField("");
passwordInput.setEditable(true);
Panel.add(passwordInput);
//.......
//the other textfields are here but they are irrelevant right now
//The important part:
JButton okButton=new JButton("Connect");
okButton.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
//set data method
setData();
dispose();
//bot object:
try {
irc_bot=new bot(username, password, master_channel, master_admin);
} catch (Exception e) {
e.printStackTrace();
}
//initiate the bot:
try {
irc_bot.initiate(server, ports);
} catch (Exception e) {
e.printStackTrace();
}
}
}
);
add(okButton, BorderLayout.SOUTH);
add(new JScrollPane(Panel), BorderLayout.NORTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,400);
setVisible(true);
}
private void setData(){
username=usernameInput.getText();
password=passwordInput.getText();
server=serverInput.getText();
master_channel=master_channelInput.getText();
master_admin=master_adminInput.getText();
port=portsInput.getText();
//set up the ports: TO-DO
}
}
My problem is that the bot.initiate() method blocks the GUI of the bot object. When the bot.initiate() is not called, the GUI works as intended. When the bot.initiate() stops, the GUI will be functional again. The problem is that the initiate() method contains an infinite loop which reads the lines from the irc server (this is in irc_bot.mainMethod()).
The GUI window shows up, but it is blank, and it does not respond to me trying to close it or anything else.
The program is actually not frozen, I can still communicate with the bot via irc.
The weird thing is that if I initiate the bot object in main() for example, it works as intended, the initiate() method does not block the gui.
Take a look at the bot class (I copied only the relevant parts):
package irc_bot;
//import stuff
public class bot {
//gui vars
private JFrame mainWindow;
//.....
//irc variables
private String server;
//.....
//lists
private List<String> botadminlist;
//.......
//for communicating with IRC
private Socket socket;
private BufferedWriter writer;//write to IRC
//.....
pritate bot_msg_handler handler;
private String line;//the received line from the IRC server is stored in this
//-----methods-----
//constructor: does the basic setup
public bot(String nick, String password, String master_channel, String master_admin) throws Exception {
//gui stuff
mainWindow=new JFrame("irc_bot");
//setup the menu
menuBar = new JMenuBar();
//first menu
menu = new JMenu("Commands");
menu.setMnemonic(KeyEvent.VK_C);
menuBar.add(menu);
//ide jön a menü kifejtése
menuItem = new JMenuItem("Show/Edit commands",
KeyEvent.VK_S);
//event handling
menuItem.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
showCommands();
}
}
);
menu.add(menuItem);
menuItem = new JMenuItem("Add command",
KeyEvent.VK_A);
//event handling
menuItem.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
addCommand();
}
}
);
menu.add(menuItem);
//more menus.......
//more GUI elements
//.......
//setup the window
mainWindow.add(bottomPanel,BorderLayout.SOUTH);
mainWindow.add(menuBar, BorderLayout.NORTH);
mainWindow.add(new JScrollPane(textBox), BorderLayout.CENTER);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(800,600);
mainWindow.setVisible(true);
sendBotMsg=false;
//setup lists
modlist=new ArrayList<mod_element>();
//.....
//user settings
this.nick=nick;
this.password=password;
this.master_channel=master_channel;
this.master_admin=master_admin;
//create the message handler object
handler = new bot_msg_handler(this.nick, this.master_channel, this.master_admin, modlist,
botadminlist, stafflist, adminlist, active_channels, cooldown, commands);
handler.setTextBox(textBox);
textBox.append("Constructor setup complete\n");
}//constructor
//IRC SPECIFIC STUFF
public void initiate(String server, int... ports) throws Exception{
this.server=server;
if(connect(server, ports)==-1){
JOptionPane.showMessageDialog(null, "Bot couldn't connect to the server!");
mainWindow.dispose();
return;
}
if(logon()==-1){
JOptionPane.showMessageDialog(null, "Bot couldn't log in!");
mainWindow.dispose();
return;
}
join(master_channel);
mainMethod();
}
private int connect(String server, int... ports) throws Exception {
// Connect directly to the IRC server.
//this.server=server;
boolean connected=false;
for(int port:ports){
textBox.append("Trying to connect to "+server+" on port "+port+"...\n");
try{
socket = new Socket();
socket.setSoTimeout(1000);//if nothing happens in 1000 milliseconds, it is gonna advance in the code. IMPORTANT!
socket.connect(new InetSocketAddress(server, port), 2000);//2000 is the timeout value in milliseconds for the connection
textBox.append("Connected to "+server+":"+port+"\n");
connected=true;
this.port=port;
break;
}
catch(SocketTimeoutException e1){
textBox.append("Connection timed out\n");
}
}
if(connected){
writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream( ), "UTF-8"));//utf-8 (international characters)
reader = new BufferedReader(
new InputStreamReader(socket.getInputStream( ), "UTF-8"));
handler.setWriter(writer);
return 1;//connection successful
}else{
textBox.append("Connection timed out, cannot connect to the IRC server\nApp will shut down now.\n");
return -1;//this means that the connection failed
}
}//connect
private int logon() throws Exception {//logs the bot in the irc
writer.write("PASS " + password + "\r\n");//twitch specific stuff
writer.write("NICK " + nick + "\r\n");
writer.flush( );
// Read lines from the server until it tells us we have connected.
String line = null;
while ((line = reader.readLine()) != null) {
rawBox.append(line+"\n");
if (line.contains("004")) {
// We are now logged in.
textBox.append("The bot is successfully logged in\n------------------\n");
return 1;
}
else if (line.contains("Login unsuccessful")) {
textBox.append("Login was unsuccessful.\n");
return -1;
}
}
return -1;
}//logon
private void join(String channel) throws Exception {
// Join the channel. Only for initial use.
writer.write("JOIN " + channel + "\r\n");
writer.flush( );
writer.write("TWITCHCLIENT 3"+"\r\n");
writer.flush();
}//join
private void mainMethod() throws Exception{
// Keep reading lines from the server.
//-------MAIN PROCESS------
msgInput.setEditable(true);//the textbox is ready to be used
while (true){
try{
line = reader.readLine( );//waits for a line for 1000 millisecs
handler.setLine(line);
}catch(SocketTimeoutException e7){
//if there is no incoming line in a second, it's gonna create an exception
//we want nothing to do with the exception though
}
if(line!=null){
handler.set_msg_type(0);//default for each line
if (line.startsWith("PING ")) {
// We must respond to PINGs to avoid being disconnected.
handler.sendPONG();
}
//Print the raw line received by the bot to the rawBox
rawBox.append(line+"\n");
//analyze the line and gather information
handler.msgAnalyzer();
//message handling:
handler.msgHandler();
//update channellist and other lists
updateLists();
}//if
//other tasks
handler.otherTasks();
line=null;
//send the message
if(sendBotMsg){
handler.sendPRIVMSG(channelToSend, msgToSend);
sendBotMsg=false;
}
}//while
}//mainMethod
//Methods called from the gui are here, but they are irrelevant now
I have tried adding SwingWorker so the initiate stuff runs in the background, but it still freezes the gui.
The program works as intended when I ...
Do not call the initiate method. I still create the object in the actionPerformed method, and I get a functioning GUI.
Do not call the initiate function from the actionPerformed.
For example, when I do this, the bot works as intended:
public static void main(String[] args) throws Exception {
String server="irc.twitch.tv";
int[] ports={80,6667};
String nick ="test";
String password = "test";
String master_channel = "#master";
String master_admin="master";
//bot object:
bot irc_bot=new bot(nick, password, master_channel, master_admin);//this is gonna be our irc_bot object
//initiate the bot:
irc_bot.initiate(server, ports);
}
I suspect the thread in which the initiate() runs is blocking the GUI thread somehow. The thing that I do not understand is why it only happens when I call said method from the action listener/window listener/any listener. Any ideas as to how I can fix this?
The button click anonymous class's actionPerformed() method is executed on the Swing thread, so while the code in that block is executed, the GUI cannot do anything else. You need to execute the initiate() method in some other thread.
To prove to yourself that this is the case, use this (terrible) code:
new Thread(){
public void run() {
//initiate the bot:
try {
irc_bot.initiate(server, ports);
} catch (Exception e) {
e.printStackTrace();
}
}}.start();
That should achieve what you are looking for, albeit with terrible code. Then you need to work out how you are going to create and manage that thread. You'll need a way to signal, from your GUI, to the background thread that you want it to stop, probably by interrupting it.
The reason that you do not get this issue when executing the code from the main() method is that you are getting a new Thread for free. When you start your app with main(), you call the constructor on bot and this spawns the UI. Your main method, in its main thread then start executing the bot initiate() method and gets into that loop, whilst the Swing thread is responsible for running the UI.
For button clicks, actionPerformed, is called on the event dispatching thread, and one should return from actionPerformed as fast as possible. Use the invokeLater to do long work a bit later. Otherwise the event queue is blocked (single thread), and the GUI is not responsive.
public void actionPerformed(ActionEvent event){
SwingUtilites.invokeLater(new Runnable() {
#Override
public void run() {
... the work
}
});
}
EventQueue.invokeLater(() -> {
... the work
});
The second alternative uses the alternative class for invokeLater, and shortens the code using java 8's lambdas.
I have tried adding SwingWorker so the initiate stuff runs in the
background, but it still freezes the gui.
You must call execute() on SwingWorker, not run() method (common mistake).
Like this:
new SwingWorker<Void, Void>() {
#Override
public Void doInBackground() {
irc_bot.initiate(server, ports);
return null;
}
}.execute();
I have written a code snippet to cpature ping using JPCAP. the code I have written is given below :
while (true) {
try {
PacketCapture m_pcap;
m_pcap = new PacketCapture();
m_pcap.open("\\Device\\NPF_{007262BD-....-7EE83D72EBEA}",true);//param 1 is actual device ID
m_pcap.setFilter("proto ICMP", true);
pktlistener a = new pktlistener(); //handles the packet
m_pcap.addPacketListener(a);
System.out.println("going to sleep");
Thread.sleep(1 * 1000);// Waiting for 1 second before ending capture
System.out.println("woken up");
m_pcap.removePacketListener(a);
m_pcap.endCapture();
m_pcap.close();
a = null;
m_pcap = null;
} catch (Exception e) {
e.printStackTrace();
}
}
Now the above code starts a new capture after every one second. The problem with the above is that after 10 runs of the loop, it throws the exception :
Exception in thread "Thread-6" java.lang.Error: Too many instances, exceeds 10
at net.sourceforge.jpcap.capture.PacketCapture.<init>(PacketCapture.java:51)
Q1. How do i prevent this. I need to start a new PacketCapture every second.
Q2. Is there any other simpler way to capture ping messages recived on a system through java?
You cannot use the constructor of PacketCapture more than ten times. This behavior is hardcoded as the constructor looks like this:
/**
* Create a new packet capture instance.
*/
public PacketCapture() {
if (nextInstance >= INSTANCE_MAX) {
throw new Error("Too many instances, exceeds " + INSTANCE_MAX);
}
instanceNum = nextInstance++;
}
To capture ping requests, you should try the following code
public class Main {
public static void main(String[] args) throws CaptureDeviceLookupException {
Capture cap = new Capture();
cap.doCapture();
}
}
class PingListener implements PacketListener {
#Override
public void packetArrived(Packet packet) {
try {
// only ICMP packages
if (packet instanceof ICMPPacket) {
ICMPPacket tcpPacket = (ICMPPacket) packet;
int data = tcpPacket.getMessageCode();
// only echo request packages
if (data == ICMPMessages.ECHO) {
// print source and destination.
String srcHost = tcpPacket.getSourceAddress();
String dstHost = tcpPacket.getDestinationAddress();
System.out.println("Ping from: " + srcHost + " to " + dstHost);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Capture {
public void doCapture() {
// create capture instance
PacketCapture capture = new PacketCapture();
// add listener that handles incomming and outgoing packages
PingListener pingListener = new PingListener();
capture.addPacketListener(pingListener);
// m_pcap.setFilter("filter here or in handler", true);
try {
capture.open("\\Device\\NPF_{...}", true); // connect capture to device
while (true) {
capture.capture(1); // capture one package
}
} catch (Exception e) {
e.printStackTrace(); // exception during capture or handling of
// packages
} finally {
// technically never reached as the loop goes on forever.
// if loop terminates after a while then:
// remove listener
capture.removePacketListener(pingListener);
// end capture (only necessary, if PacketCapture still waits for
// other packages)
capture.endCapture();
// close connection to capture device
capture.close();
}
}
}
I think there is a misunderstanding of the class PacketCapture. It does not actually capture one package and is then discarded. It opens a connection to the device you want to capture packages of and then starts listening for as long as you hold that connection. You then start capturing n packages by calling capture.capture(n). For each package arriving while "capture" blocks your program, the listener is called.
Alternatively you can drop the while-loop and use capture.capture(-1). This will block your program forever until you close the capture from another device.
I made a simple program in Processing, and it works great. Im now attempting to bring my beginner Java skills to Eclipse to make the same program over again. The program takes a Rs232 string that comes from the Com port and sends it over Xmpp.
The issue I'm having is that i cant call newChat.sendMessage(message) like i can in processing from any of the Classes/Tabs. Can someone clue me in to what i should look for to fix this issue. I'm guessing Extending, or implementing the Xmpp class is what i need to do. I love how simple processing handles it..
Any help will be greatly appreciated.
Fyi: the Smack library's are in the code folder for processing.
Main Application:
import processing.net.*;
void setup() {
size(400, 200);
noStroke();
background(0);
LoadSerialPort();
OpenChatConnection();
setupFilterThread ();
}
void draw() {
}
String timestampTime() {
Calendar now = Calendar.getInstance();
return String.format("%1$tH:%1$tM:%1$tS", now);
}
String timestampDate() {
Calendar now = Calendar.getInstance();
return String.format("%1$tm/%1$td/%1$tY", now);
}
Filter Class/Tab:
FilterThread thread1;
List FilteredArchAddressList = new ArrayList();
ArrayList CallList = new ArrayList();
void setupFilterThread () {
thread1 = new FilterThread(100, "a");
thread1.start();
}
void checkForNewCalls() {
if (CallList.size() >=1) {
println("New Call In List, Size: "+CallList.size());
FilterComPortString((String) CallList.get(0));
CallList.remove(0);
}
}
void FilterComPortString(String s) {
Message message = new Message("icu1#broadcast.server", Message.Type.normal);
//message.setTo("icu1#broadcast.x-dev");
message.setSubject("MSG_TYPE_NORMAL");
message.setBody(s);
message.setProperty("systemID", "JS1");
message.setProperty("serverTime", trim(timestampTime()));
message.setProperty("serverDate", trim(timestampDate()));
try {
newChat.sendMessage(message);
}
catch (Exception e) {
println(e);
}
}
}
class FilterThread extends Thread {
boolean running; // Is the thread running? Yes or no?
int wait; // How many milliseconds should we wait in between executions?
String id; // Thread name
int count; // counter
// Constructor, create the thread
// It is not running by default
FilterThread (int w, String s) {
wait = w;
running = false ;
id = s;
count = 0;
}
int getCount() {
return count;
}
// Overriding "start()"
void start () {
// Set running equal to true
running = true ;
// Print messages
println ("Starting thread (will execute every " + wait + " milliseconds.)");
// Do whatever start does in Thread, don't forget this!
super .start();
}
// We must implement run, this gets triggered by start()
void run () {
while (running) {
checkForNewCalls();
// Ok, let's wait for however long we should wait
try {
sleep((long )(wait));
}
catch (Exception e) {
}
}
System.out.println (id + " thread is done!"); // The thread is done when we get to the end of run()
}
// Our method that quits the thread
void quit() {
System.out.println ("Quitting.");
running = false ; // Setting running to false ends the loop in run()
// IUn case the thread is waiting. . .
interrupt();
}
}
Rs232 Class/Tab:
import processing.serial.*;
Serial myPort; // Rs232, Serial Port
String inString; // Input string from serial port:
int lf = 10; // ASCII linefeed
String SelectedCom;
void LoadSerialPort() {
println(Serial.list());
println("________________________________________________________");
try {
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil(lf);
SelectedCom = Serial.list()[0];
println("Connected to Serial Port:");
println("________________________________________________________");
}
catch (ArrayIndexOutOfBoundsException e) {
String exception = e.toString();
if (exception.contains("ArrayIndexOutOfBoundsException: 0")) {
println("NO AVAILABLE COM PORT FOUND");
}
else {
println(e);
}
}
}
void serialEvent(Serial p) {
inString = p.readString();
CallList.add(new String(inString));
}
Xmpp Class/Tab:
String FromXmpp = "";
Chat newChat;
ChatManager chatmanager;
XMPPConnection connection;
public void OpenChatConnection() {
// This is the connection to google talk. If you use jabber, put other stuff in here.
ConnectionConfiguration config = new ConnectionConfiguration("192.168.0.103", 5222, "Jabber/XMPP");
config.setSASLAuthenticationEnabled(false);
configure(ProviderManager.getInstance());
connection = new XMPPConnection(config);
println("Connecting");
try {
//connection.DEBUG_ENABLED = true;
connection.connect();
println("Connected to: "+connection.getServiceName() );
}
catch (XMPPException e1) {
println("NOT Connected");
}
if (connection.isConnected()) {
try {
// This is the username and password of the chat client that is to run within Processing.
println("Connecting");
connection.login("System1", "test");
//connection.login("inside_processing_username#gmail.com", "yourpassword");
}
catch (XMPPException e1) {
// would probably be a good idea to put some user friendly action here.
e1.printStackTrace();
}
println("Logged in as: "+connection.getUser() );
}
chatmanager = connection.getChatManager();
// Eventhandler, to catch incoming chat events
newChat = chatmanager.createChat("icu#broadcast.server", new MessageListener() { //icu1#broadcast.x-dev //admin#x-dev
public void processMessage(Chat chat, Message message) {
// Here you do what you do with the message
FromXmpp = message.getBody();
// Process commands
//println(FromXmpp);
}
}
);
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
System.out.println(entry);
}
}
public void configure(ProviderManager pm) {
// Private Data Storage
pm.addIQProvider("query", "jabber:iq:private", new PrivateDataManager.PrivateDataIQProvider());
// Time
try {
pm.addIQProvider("query", "jabber:iq:time", Class.forName("org.jivesoftware.smackx.packet.Time"));
}
catch (ClassNotFoundException e) {
println(("TestClient "+" Can't load class for org.jivesoftware.smackx.packet.Time"));
}
// Roster Exchange
pm.addExtensionProvider("x", "jabber:x:roster", new RosterExchangeProvider());
// Message Events
pm.addExtensionProvider("x", "jabber:x:event", new MessageEventProvider());
// Chat State
pm.addExtensionProvider("active", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("composing", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("paused", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("inactive", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
pm.addExtensionProvider("gone", "http://jabber.org/protocol/chatstates", new ChatStateExtension.Provider());
// XHTML
pm.addExtensionProvider("html", "http://jabber.org/protocol/xhtml-im", new XHTMLExtensionProvider());
// Group Chat Invitations
pm.addExtensionProvider("x", "jabber:x:conference", new GroupChatInvitation.Provider());
// Service Discovery # Items
pm.addIQProvider("query", "http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
// Service Discovery # Info
pm.addIQProvider("query", "http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
// Data Forms
pm.addExtensionProvider("x", "jabber:x:data", new DataFormProvider());
// MUC User
pm.addExtensionProvider("x", "http://jabber.org/protocol/muc#user", new MUCUserProvider());
// MUC Admin
pm.addIQProvider("query", "http://jabber.org/protocol/muc#admin", new MUCAdminProvider());
// MUC Owner
pm.addIQProvider("query", "http://jabber.org/protocol/muc#owner", new MUCOwnerProvider());
// Delayed Delivery
pm.addExtensionProvider("x", "jabber:x:delay", new DelayInformationProvider());
// Version
try {
pm.addIQProvider("query", "jabber:iq:version", Class.forName("org.jivesoftware.smackx.packet.Version"));
}
catch (ClassNotFoundException e) {
// Not sure what's happening here.
}
// VCard
pm.addIQProvider("vCard", "vcard-temp", new VCardProvider());
// Offline Message Requests
pm.addIQProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageRequest.Provider());
// Offline Message Indicator
pm.addExtensionProvider("offline", "http://jabber.org/protocol/offline", new OfflineMessageInfo.Provider());
// Last Activity
pm.addIQProvider("query", "jabber:iq:last", new LastActivity.Provider());
// User Search
pm.addIQProvider("query", "jabber:iq:search", new UserSearch.Provider());
// SharedGroupsInfo
pm.addIQProvider("sharedgroup", "http://www.jivesoftware.org/protocol/sharedgroup", new SharedGroupsInfo.Provider());
// JEP-33: Extended Stanza Addressing
pm.addExtensionProvider("addresses", "http://jabber.org/protocol/address", new MultipleAddressesProvider());
// FileTransfer
pm.addIQProvider("si", "http://jabber.org/protocol/si", new StreamInitiationProvider());
pm.addIQProvider("query", "http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
// Privacy
pm.addIQProvider("query", "jabber:iq:privacy", new PrivacyProvider());
pm.addIQProvider("command", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider());
pm.addExtensionProvider("malformed-action", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.MalformedActionError());
pm.addExtensionProvider("bad-locale", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadLocaleError());
pm.addExtensionProvider("bad-payload", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadPayloadError());
pm.addExtensionProvider("bad-sessionid", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.BadSessionIDError());
pm.addExtensionProvider("session-expired", "http://jabber.org/protocol/commands", new AdHocCommandDataProvider.SessionExpiredError());
}
If you know your way around eclipse, first you need to create a new Java project and add Processing's core.jar to the build path and start by creating a sublcass of PApplet. If not, there's a really easy to work with eclipse plugin called Proclipsing and video guide to get started with it.
Bringing your code from Processing to eclipse:
You need to understand that all the code you have in a Processing sketch (including tabs) gets merged into a single .java file and the sketch name is the class name. Any classes you define in tabs in the sketch become nested classes in a main single class. Easiest way to see this is to export an applet and have a look in the generated folder for the SketchName.java file. Remember, a tab is not a class (although it can contain one).
So you've got a few options. Here are two basic approaches:
Create a new PApplet subclass and start pasting your whole code in it (including content of tabs). You will need to de explicit about accessors (e.g. public void setup() instead of just void setup()) and be careful with double/float values (e.g. if eclipse complains about 1.0, be explicit: 1.0f)
The other option is to create multiple classes, as I imagine you intend to do if you're using eclipse. The catch is, in Processing, variables defined in tabs are actually 'global' variables. Your code would work the same way if you declare those in the main tab at the top. Also, using PApplet functions needs to be refactored. Some functions can be called using Java's classes (not PApplet's) to break the dependency: e.g. System.out.println() instead of println(), but of others you might want your classes to have access to a PApplet instance:
e.g.
public class FilterThread extends Thread {
boolean running; // Is the thread running? Yes or no?
int wait; // How many milliseconds should we wait in between executions?
String id; // Thread name
int count; // counter
YourSketchClass parent;
// Constructor, create the thread
// It is not running by default
FilterThread (int w, String s,YourSketchClass p) {
wait = w;
running = false ;
id = s;
count = 0;
parent = p;
}
int getCount() {
return count;
}
// Overriding "start()"
public void start () {
// Set running equal to true
running = true ;
// Print messages
System.out.println ("Starting thread (will execute every " + wait + " milliseconds.)");
// Do whatever start does in Thread, don't forget this!
super .start();
}
// We must implement run, this gets triggered by start()
public void run () {
while (running) {
parent.checkForNewCalls();
// Ok, let's wait for however long we should wait
try {
sleep((long )(wait));
}
catch (Exception e) {
}
}
System.out.println (id + " thread is done!"); // The thread is done when we get to the end of run()
}
// Our method that quits the thread
void quit() {
System.out.println ("Quitting.");
running = false ; // Setting running to false ends the loop in run()
// IUn case the thread is waiting. . .
interrupt();
}
}
Every class which uses the chat-functionality, needs to know the chat-object. You can put all your variables and functions which are not in a separate class in the main source-file.
When you declare a variable in Processing, it can be used from any tab, in java global variables do not exist. You can get a similar functionality like this: Create a new file GlobalVars.java with this content:
public class GlobalVars {
public static Chat myChat;
}
Now everytime you want to access the Chat-functions, you have to write e.g. GlobalVars.myChat.sendMessage("Hi!");
Btw, You have to include the net.jar-file. On Mac this is located here:
Processing.app/Contents/Resources/Java/modes/java/libraries/net/library/net.jar
**** Please note that my question is regarding the answers in another thread. However, when I posted the question in that thread, it was deleted. So I'm reposting the question here (with a link to the exact post that I'm referring to). ****
I have a couple of questions that go along with this thread. If I have a Timer (updateTimer), which I want to cancel when the window is closing, can I put that in place of the System.out.println("Windows Closing"); statement? Or would I have to put it in the actual "View" class (I have three classes DesktopApplication.App, DesktopApplication.View, and DesktopApplication.AboutBox and the configure Window method is in the .App class).
Along that line, if I can put the updateTimer.cancel(); line in, then does this mean I can read/write from a file, and popluate textboxes also (WindowOpen event) and write the information to the file in the closing event?
What I want to do is the following: When my application starts (and the main window opens) I want to check for a configuration file. If it exists, then I want to get the username, password, tunnel ID, and IP Address from that file--and populate their respective text boxes in the main jPanel. If it doesn't exist, then I won't do anything with it.
On closing the application, I want two things to happen: 1) any UpdateTimers that are running will be cancelled (to effectively and cleanly close the application) and 2) write the username, password, tunnel ID and IP Address to the configuration file for the next run.
I've created the file in Netbeans, so the "exitMenu" is automatically generated, and there is no "close button" configured. So I need to use WindowClosing to accomplish this (or hack the "exitMenu" method in a text editor and hope it doesn't create issues with Netbeans).
I should also add that the username and password are actually MD5 hashes of the real username and password. So, while someone can possibly open the text file and read them, they'll only see something like this:
c28de38997efb893872d893982ac
3289ab83ce8f398289d938999cab
12345
192.168.2.2
Thanks, and have a great day:)
Patrick.
Edited to include information about the "Username and Password" that will be stored.
can I put that in place of the System.out.println("Windows Closing"); statement?
Yes, you can put arbitrary code in your listener
Along that line, if I can put the updateTimer.cancel(); line in, then does this mean I can read/write from a file, and popluate textboxes also (WindowOpen event) and write the information to the file in the closing event?
Yes
How I ended up accomplishing this is like this.
In my "TunnelbrokerUpdateView" class (the one that actually handles the main frame), I added the following code:
WindowListener wl = new WindowListener(){
public void windowOpened(WindowEvent e)
{
try
{
FileReader fr = new FileReader (new File("userinfo.txt"));
BufferedReader br = new BufferedReader (fr);
jTextField1.setText(br.readLine());
jPasswordField1.setText(br.readLine());
jTextField2.setText(br.readLine());
oldIPAddress = br.readLine();
br.close();
}
catch (FileNotFoundException ex) {
// Pop up a dialog box explaining that this information will be saved
// and propogated in the future.. "First time running this?"
int result = JOptionPane.showConfirmDialog((Component)
null, "After you enter your user information, this box will no longer show.", "First Run", JOptionPane.DEFAULT_OPTION);
}
catch (java.io.IOException ea)
{
Logger.getLogger(TunnelbrokerUpdateView.class.getName()).log(Level.SEVERE, null, ea);
}
}
public void windowClosing(WindowEvent e) {
updateTimer.cancel();
BufferedWriter userData;
//Handle saving the user information to a file "userinfo.txt"
try
{
userData = new BufferedWriter(new FileWriter("userinfo.txt"));
StringBuffer sb = new StringBuffer();
sb.append(jTextField1.getText());
sb.append(System.getProperty("line.separator"));
sb.append(jPasswordField1.getText());
sb.append(System.getProperty("line.separator"));
sb.append(jTextField2.getText());
sb.append(System.getProperty("line.separator"));
sb.append(oldIPAddress);
userData.write(sb.toString());
userData.close();
}
catch (java.io.IOException ex)
{
Logger.getLogger(TunnelbrokerUpdateView.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void windowClosed(WindowEvent e) {
System.exit(0);
}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
};
super.getFrame().addWindowListener(wl);
}
I added this into the "public TunnelbrokerUpdateView(SingleFrameApplication app)" method. So, everything works as I wanted it to. I'm sure there are better ways of incorporating the user information, but this was quick and dirty. In the future, I do plan on encrypting the data (or making it into a format that isn't readable normally), since there's a password hash involved.
Hopefully this will help someone else in the future.
(for reference, here's the entire method (including the stuff that Netbeans automatically puts in)
public TunnelbrokerUpdateView(SingleFrameApplication app) {
super(app);
initComponents();
// status bar initialization - message timeout, idle icon and busy animation, etc
ResourceMap resourceMap = getResourceMap();
int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
messageTimer = new Timer(messageTimeout, new ActionListener() {
public void actionPerformed(ActionEvent e) {
statusMessageLabel.setText("");
}
});
messageTimer.setRepeats(false);
int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
for (int i = 0; i < busyIcons.length; i++) {
busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
}
busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
public void actionPerformed(ActionEvent e) {
busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
}
});
idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
// connecting action tasks to status bar via TaskMonitor
TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
public void propertyChange(java.beans.PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if ("started".equals(propertyName)) {
if (!busyIconTimer.isRunning()) {
statusAnimationLabel.setIcon(busyIcons[0]);
busyIconIndex = 0;
busyIconTimer.start();
}
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
} else if ("done".equals(propertyName)) {
busyIconTimer.stop();
statusAnimationLabel.setIcon(idleIcon);
progressBar.setVisible(false);
progressBar.setValue(0);
} else if ("message".equals(propertyName)) {
String text = (String)(evt.getNewValue());
statusMessageLabel.setText((text == null) ? "" : text);
messageTimer.restart();
} else if ("progress".equals(propertyName)) {
int value = (Integer)(evt.getNewValue());
progressBar.setVisible(true);
progressBar.setIndeterminate(false);
progressBar.setValue(value);
}
}
});
// This will take care of Opening and Closing
WindowListener wl = new WindowListener(){
public void windowOpened(WindowEvent e)
{
try
{
FileReader fr = new FileReader (new File("userinfo.txt"));
BufferedReader br = new BufferedReader (fr);
jTextField1.setText(br.readLine());
jPasswordField1.setText(br.readLine());
jTextField2.setText(br.readLine());
oldIPAddress = br.readLine();
br.close();
}
catch (FileNotFoundException ex) {
// Pop up a dialog box explaining that this information will be saved
// and propogated in the future.. "First time running this?"
int result = JOptionPane.showConfirmDialog((Component)
null, "After you enter your user information, this box will no longer show.", "First Run", JOptionPane.DEFAULT_OPTION);
}
catch (java.io.IOException ea)
{
Logger.getLogger(TunnelbrokerUpdateView.class.getName()).log(Level.SEVERE, null, ea);
}
}
public void windowClosing(WindowEvent e) {
updateTimer.cancel();
BufferedWriter userData;
//Handle saving the user information to a file "userinfo.txt"
try
{
userData = new BufferedWriter(new FileWriter("userinfo.txt"));
StringBuffer sb = new StringBuffer();
sb.append(jTextField1.getText());
sb.append(System.getProperty("line.separator"));
sb.append(jPasswordField1.getText());
sb.append(System.getProperty("line.separator"));
sb.append(jTextField2.getText());
sb.append(System.getProperty("line.separator"));
sb.append(oldIPAddress);
userData.write(sb.toString());
userData.close();
}
catch (java.io.IOException ex)
{
Logger.getLogger(TunnelbrokerUpdateView.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void windowClosed(WindowEvent e) {
System.exit(0);
}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
};
super.getFrame().addWindowListener(wl);
}
Have a great day:)
Patrick.