Problem when using code from a jar file - java

I run the following code:
public class Sign {
private static final PrivateKey priv = Util.loadPrivate();
private static final PublicKey pub = Util.loadPublic();
private static final HexBinaryAdapter adp = new HexBinaryAdapter();
public static String sign(String in) {
try {
Signature sign = Signature.getInstance(Util.ALG);
sign.initSign(priv);
sign.update(in.getBytes());
return adp.marshal(sign.sign());
} catch (Exception e) {e.printStackTrace();}
return null;
}
public static boolean verify(String data, String sign) {
try {
Signature verify = Signature.getInstance(Util.ALG);
verify.initVerify(pub);
verify.update(data.getBytes());
return verify.verify(adp.unmarshal(sign));
} catch (Exception e) {e.printStackTrace();}
return false;
}
}
and the main function looks like this:
public static void main(String[] args) {
String in = "lala";
String sign = Sign.sign(in);
System.out.println(sign);
System.out.println(Sign.verify(in, sign));
}
Everything goes well when I run it from within Eclipse (the output is "true"), but when I pack it into a jar (without the main function) and run it then the output is false.
This is how I load the keys:
public static PrivateKey loadPrivate() {
try {
URLConnection con = Util.class.getResource("private.key").openConnection();
byte[] bs = new byte[con.getContentLength()];
con.getInputStream().read(bs);
return KeyFactory.getInstance(ALG).generatePrivate(new PKCS8EncodedKeySpec(bs));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static PublicKey loadPublic() {
try {
URLConnection con = Util.class.getResource("public.key").openConnection();
byte[] bs = new byte[con.getContentLength()];
con.getInputStream().read(bs);
return KeyFactory.getInstance(ALG).generatePublic(new X509EncodedKeySpec(bs));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I checked and loading the keys works fine.
Any idea ?

Just run like this:
java Main -classpath=/path/to/libraryk.jar

Related

Increment number every time program runs

I want to increment the count every time my program runs. I tried running below code but it keeps on printing 1 every time i run the program. Also anything special i need to do to increase the date.
public class CounterTest {
int count = 0;
public static void main(String[] args) {
CounterTest test1 = new CounterTest();
test1.doMethod();
}
public void doMethod() {
count++;
System.out.println(count);
}
}
You could simply create a properties file for your application to keep track of such things and application configuration details. This of course would be a simple text file containing property names (keys) and their respective values.
Two small methods can get you going:
The setProperty() Method:
With is method you can create a properties file and apply whatever property names and values you like. If the file doesn't already exist then it is automatically created at the file path specified:
public static boolean setProperty(String propertiesFilePath,
String propertyName, String value) {
java.util.Properties prop = new java.util.Properties();
if (new java.io.File(propertiesFilePath).exists()) {
try (java.io.FileInputStream in = new java.io.FileInputStream(propertiesFilePath)) {
prop.load(in);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); }
catch (java.io.IOException ex) { System.err.println(ex); }
}
try (java.io.FileOutputStream outputStream = new java.io.FileOutputStream(propertiesFilePath)) {
prop.setProperty(propertyName, value);
prop.store(outputStream, null);
outputStream.close();
return true;
}
catch (java.io.FileNotFoundException ex) {
System.err.println(ex);
}
catch (java.io.IOException ex) {
System.err.println(ex);
}
return false;
}
If you don't already contain a specific properties file then it would be a good idea to call the above method as soon as the application starts (perhaps after initialization) so that you have default values to play with if desired, for example:
if (!new File("config.properties").exists()) {
setProperty("config.properties", "ApplicationRunCount", "0");
}
The above code checks to see if the properties file named config.properties already exists (you should always use the .properties file name extension). If it doesn't then it is created and the property name (Key) is applied to it along with the supplied value for that property. Above we are creating the ApplicationRunCount property which is basically for your specific needs. When you look into the config.properties file created you will see:
#Mon Sep 28 19:07:08 PDT 2020
ApplicationRunCount=0
The getProperty() Method:
This method can retrieve a value from a specific property name (key). Whenever you need the value from a particular property contained within your properties file then this method can be used:
public static String getProperty(String propertiesFilePath, String key) {
try (java.io.InputStream ips = new java.io.FileInputStream(propertiesFilePath)) {
java.util.Properties prop = new java.util.Properties();
prop.load(ips);
return prop.getProperty(key);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); }
catch (java.io.IOException ex) { System.err.println(ex); }
return null;
}
Your Task:
What is confusing here is you say you want to keep track of the number of times your Program is run yet you increment your counter variable named count within a method named doMethod(). This would work if you can guarantee that this method will only run once during the entire time your application runs. If this will indeed be the case then you're okay. If it isn't then you would possibly get a count total that doesn't truly represent the actual number of times your application was started.
In any case, with the scheme you're currently using, you could do this:
public class CounterTest {
// Class Constructor
public CounterTest() {
/* If the config.properties file does not exist
then create it and apply the ApplicationRunCount
property with the value of 0. */
if (!new java.io.File("config.properties").exists()) {
setProperty("config.properties", "ApplicationRunCount", "0");
}
}
public static void main(String[] args) {
new CounterTest().doMethod(args);
}
private void doMethod(String[] args) {
int count = Integer.valueOf(getProperty("config.properties",
"ApplicationRunCount"));
count++;
setProperty("config.properties", "ApplicationRunCount",
String.valueOf(count));
System.out.println(count);
}
public static String getProperty(String propertiesFilePath, String key) {
try (java.io.InputStream ips = new
java.io.FileInputStream(propertiesFilePath)) {
java.util.Properties prop = new java.util.Properties();
prop.load(ips);
return prop.getProperty(key);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); }
catch (java.io.IOException ex) { System.err.println(ex); }
return null;
}
public static boolean setProperty(String propertiesFilePath,
String propertyName, String value) {
java.util.Properties prop = new java.util.Properties();
if (new java.io.File(propertiesFilePath).exists()) {
try (java.io.FileInputStream in = new java.io.FileInputStream(propertiesFilePath)) {
prop.load(in);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); }
catch (java.io.IOException ex) { System.err.println(ex); }
}
try (java.io.FileOutputStream outputStream = new java.io.FileOutputStream(propertiesFilePath)) {
prop.setProperty(propertyName, value);
prop.store(outputStream, null);
return true;
}
catch (java.io.FileNotFoundException ex) {
System.err.println(ex);
}
catch (java.io.IOException ex) {
System.err.println(ex);
}
return false;
}
}
Whenever you start your application you will see the run count within the Console Window. Other useful methods might be removeProperty() and renameProperty(). Here they are:
/**
* Removes (deletes) the supplied property name from the supplied property
* file.<br>
*
* #param propertiesFilePath (String) The full path and file name of the
* properties file you want to remove a property name from.<br>
*
* #param propertyName (String) The property name you want to remove from
* the properties file.<br>
*
* #return (Boolean) Returns true if successful and false if not.
*/
public static boolean removeProperty(String propertiesFilePath,
String propertyName) {
java.util.Properties prop = new java.util.Properties();
if (new java.io.File(propertiesFilePath).exists()) {
try (java.io.FileInputStream in = new java.io.FileInputStream(propertiesFilePath)) {
prop.load(in);
prop.remove(propertyName);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); return false; }
catch (java.io.IOException ex) { System.err.println(ex); return false; }
}
try (java.io.FileOutputStream out = new java.io.FileOutputStream(propertiesFilePath)) {
prop.store(out, null);
return true;
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); }
catch (java.io.IOException ex) { System.err.println(ex); }
return false;
}
/**
* Renames the supplied property name within the supplied property file.<br>
*
* #param propertiesFilePath (String) The full path and file name of the
* properties file you want to rename a property in.<br>
*
* #param oldPropertyName (String) The current name of the property you want
* to rename.<br>
*
* #param newPropertyName (String) The new property name you want to use.<br>
*
* #return (Boolean) Returns true if successful and false if not.
*/
public static boolean renameProperty(String propertiesFilePath, String oldPropertyName,
String newPropertyName) {
String propertyValue = getProperty(propertiesFilePath, oldPropertyName);
if (propertyValue == null) { return false; }
java.util.Properties prop = new java.util.Properties();
if (new java.io.File(propertiesFilePath).exists()) {
try (java.io.FileInputStream in = new java.io.FileInputStream(propertiesFilePath)) {
prop.load(in);
prop.remove(oldPropertyName);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); return false; }
catch (java.io.IOException ex) { System.err.println(ex); return false ;}
}
try (java.io.FileOutputStream out = new java.io.FileOutputStream(propertiesFilePath)) {
prop.store(out, null);
}
catch (java.io.FileNotFoundException ex) { System.err.println(ex); return false; }
catch (java.io.IOException ex) { System.err.println(ex); return false; }
return setProperty(propertiesFilePath, newPropertyName, propertyValue);
}
Try this.
public class CounterTest {
static final Path path = Path.of("counter.txt");
int count;
CounterTest() throws IOException {
try {
count = Integer.valueOf(Files.readString(path));
} catch (NoSuchFileException | NumberFormatException e) {
count = 0;
}
}
public void doMethod() throws IOException {
++count;
System.out.println(count);
Files.writeString(path, "" + count);
}
public static void main(String[] args) throws IOException {
CounterTest c = new CounterTest();
c.doMethod();
}
}
You can't the only way is to use a Database or simpler use a txt file to save the number and every time you run your app reads the txt file and gets the number.
Here is How to do it:
This is the Main class:
package main;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
String path = "C:\\Example.txt";
int number = 0;
try {
ReadFile file = new ReadFile(path);
String[] aryLines = file.OpenFile();
try {
number = Integer.parseInt(aryLines[0]);
} catch (Exception e) {
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
System.out.println(number);
number++;
File txtfile = new File(path);
if (txtfile.exists()) {
txtfile.delete();
try {
txtfile.createNewFile();
WriteFile data = new WriteFile(path, true);
data.writeToFile(number + "");
} catch (IOException ex) {
}
} else {
try {
System.out.println("no yei");
txtfile.createNewFile();
WriteFile data = new WriteFile(path, true);
data.writeToFile(number + "");
} catch (IOException ex) {
}
}
}
}
the class that writes anything you need:
package main;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
public class WriteFile {
public String path;
public boolean append_to_file = false;
public WriteFile(String file_path) {
path = file_path;
}
public WriteFile(String file_path, boolean append_value) {
path = file_path;
append_to_file = append_value;
}
public void writeToFile(String textline) throws IOException {
FileWriter write = new FileWriter(path, append_to_file);
PrintWriter print_line = new PrintWriter(write);
print_line.printf("%s" + "%n", textline);
print_line.close();
}
}
And this one is the one that gets the text on the file:
package main;
import java.io.IOException;
import java.io.FileReader;
import java.io.BufferedReader;
public class ReadFile {
private static String path;
public ReadFile(String file_path){
path = file_path;
}
public String[] OpenFile() throws IOException {
FileReader fr = new FileReader(path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines();
String[] textData = new String[numberOfLines];
for (int j = 0; j < numberOfLines; j++) {
textData[j] = textReader.readLine();
}
textReader.close();
return textData;
}
static int readLines() throws IOException {
FileReader file_to_read = new FileReader(path);
BufferedReader bf = new BufferedReader(file_to_read);
String aLine;
int numberOfLines = 0;
while((aLine = bf.readLine()) != null){
numberOfLines++;
}
bf.close();
return numberOfLines;
}
}

Cannot load properties file in java

I try to load properties file as below,
public class A_Main {
private static FileReader reader = new FileReader("D:\\Selenium_Workspace\\SeleniumTEST\\lists.properties");
private static Properties properties = new Properties();
private static properties.load(reader);
public static String UserName = properties.getProperty("lists.user");
public static String Passwd = properties.getProperty("lists.password");
......
......
......
public static void main(String[] args) throws IOException {
Configuration_Report conf = new Configuration_Report();
try {
conf.conf_report(UserName, Passwd);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
......
......
......
However, in eclipse it marked an error under below code,
private static properties.load(reader);
I try to change everything to public static also, however it seem the properties file cannot be load as reader seem not recognize.
As shared by Elliott above, you need to call the load function either from the static block. If you call it from the static block then you will have to take care that you initialize username and password (and any other dependencies) as well in the static block. Or the other option would be to initialize them at the starting of the main function:
Static Block:
public class A_Main {
private static Properties properties = new Properties();
public static String UserName = null;
public static String Passwd = null;
static{
try (FileReader reader = new FileReader("D:\\Selenium_Workspace\\SeleniumTEST\\lists.properties"))
{
properties.load(reader);
UserName = properties.getProperty("lists.user");
Passwd = properties.getProperty("lists.password");
} catch (IOException e) {
e.printStackTrace();
}
}
......
......
......
public static void main(String[] args) throws IOException {
Configuration_Report conf = new Configuration_Report();
try {
conf.conf_report(UserName, Passwd);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
......
......
......
Inside Main Function:
public class A_Main {
private static Properties properties = new Properties();
public static String UserName = null;
public static String Passwd = null;
......
......
......
public static void main(String[] args) throws IOException {
try (FileReader reader = new FileReader("D:\\Selenium_Workspace\\SeleniumTEST\\lists.properties"))
{
properties.load(reader);
UserName = properties.getProperty("lists.user");
Passwd = properties.getProperty("lists.password");
Configuration_Report conf = new Configuration_Report();
conf.conf_report(UserName, Passwd);
} catch (IOException | InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
......
......
......
That is not valid syntax for invoking a function on a class member. You could use a static initialization block. And that FileReader constructor can also throw an Exception. You could move that initialization into the same block. Like,
private static FileReader reader;
private static Properties properties = new Properties();
static {
try {
reader = new FileReader("D:\\Selenium_Workspace\\SeleniumTEST\\lists.properties");
properties.load(reader);
} catch (IOException e) {
e.printStackTrace();
}
}

"Endless" AudioInputStream from socket

I have a problem with creation of AudioInputStream from Socket.
Here are the important parts:
public class SoundStream extends Thread {
private int port;
private String IP;
private Socket socket;
private SoundObject soundObject;
private OpenAL openAL;
private Source source;
private boolean run = true;
public SoundStream(int port, String IP, SoundObject soundObject) {
this.soundObject = soundObject;
this.port = port;
this.IP = IP;
}
public void run() {
try {
this.socket = new Socket(this.IP, this.port);
this.openAL = new OpenAL();
} catch (Exception e) {
e.printStackTrace();
}
this.mainCycleMethod();
}
private void mainCycleMethod() {
while (run) {
this.soundObject.blockAndWait();
switch (this.soundObject.getAndResetEvent()) {
case 0:
this.run = false;
this.close();
break;
case 1:
this.setPitch();
break;
case 2:
this.closeSource();
this.play();
break;
case 3:
this.pause(true);
break;
case 4:
this.pause(false);
break;
}
}
}
private BufferedInputStream getInputStream() throws Exception {
return new BufferedInputStream(socket.getInputStream());
}
private void setPitch() {
if(this.source != null) {
try {
this.source.setPitch(this.soundObject.getPitch());
} catch (ALException e) {
e.printStackTrace();
}
}
}
private void play() {
try {
AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), AudioSystem.NOT_SPECIFIED);
// AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream());
// AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(this.soundObject.getAudioFormat(), audioInputStream_tmp);
this.source = openAL.createSource(audioInputStream);
this.source.setGain(1f);
this.source.play();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void close() {
this.closeSource();
this.openAL.close();
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void closeSource() {
if(this.source!=null) {
this.source.close();
}
}
private void pause(boolean pause) {
if(this.source != null) {
try {
if (pause) {
this.source.pause();
} else {
this.source.play();
}
} catch (ALException ex) {
ex.printStackTrace();
}
}
}
}
public class SoundObject extends AbstractEventObject {
public AudioFormat getAudioFormat() {
boolean signed = false;
//true,false
boolean bigEndian = false;
//true,false
return new AudioFormat(this.frequency, this.bits, this.channels, signed, bigEndian);
}
.
.
.
.
}
This code throws UnsupportedAudioFileException at this line:
AudioInputStream audioInputStream_tmp = AudioSystem.getAudioInputStream(this.getInputStream());
However when I use this code:
AudioInputStream audioInputStream = new AudioInputStream(this.getInputStream(), this.soundObject.getAudioFormat(), 100000);
it plays the sound but only after it loads those 100000 sample frames to the audioinputstream. After it plays all the 100000 frames it finishes.
I guess that I would solve this issue if I could pass the AudioFormat directly as a parameter during the first AudioInputStream inicialization, but it doesn't seem to be possible.
I'm receiving the audio format specifications from server.
I think that one possible solution would be to create a dataline which I can pass as a parametr to AudioInputStream constructor. However I'm not sure how to get the data from the socket directly to dataline. I know of a solution that uses infinite loop, in which it reads the data and writes them to the dataline. But it seems to be wasteful. Is there a more direct approach?
I hope it's possible to solve using java-openAL library, because I need to change the speed and I hope I won't have to do it myself.
Thanks
I've finally solved the issue. As it turned out java-openAL has streaming support built in, but it wasn't in the documentation on GitHub so I didn't notice at first. There is a createOutputStream method in the Source class, which returns the OutputStream. You can write the bytes directly to the OutputStream.
Here is my code:
In this snippet I initialize OpenAL:
public void run() {
try {
this.socket = new Socket(this.IP, this.port);
this.openAL = new OpenAL();
} catch (Exception ex) {
Log.severe(ex.toString());
}
this.mainCycleMethod();
}
Here is my play method which is called when the InputStream is available:
private void play() {
try {
this.source = openAL.createSource();
this.outputWriter = new OutputWriter(this.socket.getInputStream(), this.source, this.soundObject.getAudioFormat());
this.source.setGain(1f);
this.outputWriter.start();
} catch (Exception ex) {
Log.severe(ex.toString());
}
}
You have to use createSource method without parameters, it returns new instance of Source. Don't call the play method on source, it's handled by the SourceOutputStream class which instance is returned by the createOutputStream method. There is nothing wrong with calling the play method manually but I had a bad experience doing so when the buffers are empty. Basically it doesn't start playing later on when you begin streaming the data to OpenAL.
Here is my OutputWriter code which takes care of passing the bytes from InputStream to OutputStream:
package cz.speechtech.sound;
import org.urish.openal.ALException;
import org.urish.openal.Source;
import javax.sound.sampled.AudioFormat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Created by honza on 16.12.15.
*/
public class OutputWriter extends Thread {
private InputStream inputStream;
private OutputStream outputStream;
private int STREAMING_BUFFER_SIZE = 24000;
private int NUMBER_OF_BUFFERS = 4;
private boolean run = true;
public OutputWriter(InputStream inputStream, Source source, AudioFormat audioFormat) {
this.inputStream = inputStream;
try {
this.outputStream = source.createOutputStream(audioFormat, this.NUMBER_OF_BUFFERS, 1024);
} catch (ALException e) {
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[this.STREAMING_BUFFER_SIZE];
int i;
try {
Thread.sleep(1000); // Might cause problems
while (this.run) {
i = this.inputStream.read(buffer);
if (i == -1) break;
outputStream.write(buffer, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void stopRunning() {
this.run = false;
try {
this.outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Have a nice day.

Can't open Object Arraylist with fileio function

I'm trying to use a function to open an arraylist of objects with fileIO but right now i'm stuck. I think there is something wrong with my setter function. (The file test.txt already exists)
The following classes I'm using to get the fileio function to work
Paslijst
public class Paslijst implements Serializable {
private ArrayList<Pas> paslijst;
public ArrayList<Pas> setPaslijst(ArrayList<Pas> paslijst){
this.paslijst = paslijst;
return paslijst;
}
FileIOPas
// This function opens a file
public Paslijst openen(String filenaam)
throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = new FileInputStream(filenaam);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
return (Paslijst) objectInputStream.readObject();
}
Main
public static void main(String[] args) {
FileIOPas fileiopas = new FileIOPas();
Paslijst paslijst = new Paslijst();
try {
paslijst.setPaslijst(fileiopas.openen("test.txt"));
}
catch (IOException e) {
System.out.println(" IO openen mislukt, want: " + e.toString());
}
catch (ClassNotFoundException e) {
System.out.println("class not found: " + e.toString());
}
}
You were passing wrong arguments in paslijst.setPaslijst().I have edited your class may this could Help.
public class Main {
public static void main(String[] args) {
FileIOPas fileiopas = new FileIOPas();
Paslijst paslijst = new Paslijst();
paslijst.setPaslijst(fileiopas.openen("test.txt"));
}
}
public class FileIOPas {
public ArrayList<Pas> openen(String filenaam) {
try (FileInputStream fileInputStream = new FileInputStream(filenaam);
ObjectInputStream objectInputStream = new ObjectInputStream(
fileInputStream);) {
return (ArrayList<Pas>) objectInputStream.readObject();
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
}
public class Paslijst implements Serializable {
private ArrayList<Pas> paslijst;
public ArrayList<Pas> getPaslijst() {
return paslijst;
}
public void setPaslijst(ArrayList<Pas> paslijst) {
this.paslijst = paslijst;
}
}

BufferReader going still running while connection is closed

I have a somewhat simple server meaning that i am trying to learn different design patterns by making a server as object orientated as possible. Suprisingly so far i havnt had a single problem untill i created the method close().
apprently when a client closes his connection with the database the BufferReader still wants input and throws an execption saying that Java.net.socketExecption: socket closed
since i have alot of different classes i will only post the ones that are failing at the moment if you need additional information please do not hesitate to send me a comment. Also since i am trying to learn from this project please comment on my code aswell if you feel like it :)
Code (all of my code)
public class ServerConnectionManager {
private static ServerSocket server;
private static Socket connection;
private static ServerInformation ai = new ServerInformation();
private static boolean connected = false;
private static final int portNumber = 7070;
private static int backLog = 100;
/**
* This method launches the server (and the application)!
* #param args
*/
public static void main(String[] args){
startServer();
waitForConnection();
}
/**
*This method sets the serverSocket to portNumber and also adds the backLog.
*/
private static void startServer() {
try {
server = new ServerSocket(portNumber, backLog);
connected = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* This method waits for a connection aslong as the serverSocket is connected.
* When a new client connects it creates an Object of the connection and starts the individual procedure.
*/
private static void waitForConnection() {
while (connected) {
try {
connection = server.accept();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connection c = new Connection(connection);
ai.addToConnectionList(c);
waitForConnection();
}
}
public void closeMe(Socket con) {
for (Connection conn : ai.getConnectionList()) {
if (conn.getConnection() == con) {
conn.close();
}
}
}
}
Connection
public class Connection{
private Socket connection;
public Connection(Socket connection){
this.connection = connection;
ServerListner cl = new ServerListner(Connection.this);
cl.start();
}
public Socket getConnection(){
return this.connection;
}
public void close() {
try {
connection.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ServerListner
public class ServerListner extends Thread {
private Socket connection;
private BufferedReader br;
private ChatPerson person;
private Connection con;
private ServerInformation ai = new ServerInformation();
private ServerConnectionManager scm = new ServerConnectionManager();
private ServerSender sender = new ServerSender();
public ServerListner(Connection con){
this.con = con;
connection = con.getConnection();
try {
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Socket getConnection(){
return this.connection;
}
public void run(){
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void processInput(String input){
if (input.equalsIgnoreCase("Connect")) {
sender.sendMessageToConnection(this.connection, "Accepted");
}
if (input.equalsIgnoreCase("UserInformation")) {
try {
String username = br.readLine();
person = new ChatPerson(username, connection);
ai.add(person);
System.out.println(ai.getList());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (input.equalsIgnoreCase("SearchByCon")) {
String name = ai.searchByConnection(connection);
System.out.println(name);
}
if (input.equals("Disconnect")) {
scm.closeMe(connection);
}
}
}
** Server Sender**
public class ServerSender {
private PrintWriter pw;
private ServerInformation ai = new ServerInformation();
public void addToList(){
}
public void sendToAll(String message){
for (Connection c : ai.getConnectionList()) {
try {
pw = new PrintWriter(c.getConnection().getOutputStream());
pw.print(message);
pw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
*
* #param con
* #param message
*/
/*
* Note - Denne metode gør også at jeg kan hviske til folk!:)
*/
public void sendMessageToConnection(Socket con, String message){
try {
PrintWriter print = new PrintWriter(con.getOutputStream());
print.println(message);
print.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
** Server Information**
public class ServerInformation {
private ArrayList<Connection> connectedClients = new ArrayList<Connection>();
private ArrayList<ChatPerson> list = new ArrayList<ChatPerson>();
public ArrayList<Connection> getConnectionList(){
return connectedClients;
}
public void addToConnectionList(Connection con){
connectedClients.add(con);
}
public String searchByConnection(Socket myConnection){
for (ChatPerson p : list) {
if (p.getConnection() == myConnection) {
return p.getName();
}
}
/*
* If none found!
*/
return null;
}
public void add(ChatPerson p){
list.add(p);
}
public void removeByName(String name){
for (ChatPerson p : list) {
if (p.getName().equalsIgnoreCase(name)) {
list.remove(p);
}
}
}
public String searchList(String name){
for (ChatPerson p : list) {
if (p.getName().equalsIgnoreCase(name)) {
return p.getName();
}
}
return null;
}
public ArrayList<ChatPerson>getList(){
return list;
}
}
** ChatPerson**
public class ChatPerson {
private String chatName;
private Socket connection;
/*
* This is for furture development
* private Integer adminLevel;
*/
public ChatPerson(String name, Socket connection){
this.chatName = name;
this.connection = connection;
}
public void setName(String name){
this.chatName = name;
}
public String getName(){
return chatName;
}
public String toString(){
return "Username: "+chatName;
}
public Socket getConnection(){
return connection;
}
}
I have tried the following thing(s):
try {
String inString;
while ((inString = br.readLine()) != null) {
if (inString.equalsIgnoreCase("Disconnect")) {
System.out.println(inString);
break;
}else {
processInput(inString);
}
}
scm.closeMe(connection);
This did not work still gave me the same execption.
while (con.getConnection().isConnected()) {
String inString;
try {
while ((inString = br.readLine()) != null) {
processInput(inString);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Having both these loops is meaningless. readLine() will return null as soon as EOS is reached, at which point you should close the socket and exit the loop. In any case isConnected() doesn't tell you anything about the state of the connection, only about which APIs you have called on your Socket which is the endpoint of it. Lose the outer loop.
The documentation on Socket says
Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.
You may want to break out of your readline() loop and close the connection outside of this.

Categories

Resources