screameth
This commit is contained in:
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
@@ -42,6 +43,19 @@ public class ClientConnect extends JFrame {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
logger.info("Triggered a Connection request.");
|
||||
// Connection logic would go here (e.g., retrieve values and initiate connection)
|
||||
try {
|
||||
Socket socket = new Socket(getSanitizedText(hostname), Integer.valueOf(getSanitizedText(portNumber)));
|
||||
logger.info("socket connection has been successfully established by the client");
|
||||
dispose();
|
||||
if(socket.isConnected()){
|
||||
Dashboard dashboard = new Dashboard(socket);
|
||||
}
|
||||
//pass a socket with a worker thread to a new variable so that the dashboard can get access to a consumer of messages
|
||||
//make sure those messages are in turn written to the ServerDaemon socket. The Dashboard will make the messages
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
53
src/main/java/net/ayyalasomayajula/net/client/Dashboard.form
Normal file
53
src/main/java/net/ayyalasomayajula/net/client/Dashboard.form
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="net.ayyalasomayajula.net.client.Dashboard">
|
||||
<grid id="27dc6" binding="main" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="d5ffa" class="javax.swing.JTextField" binding="textField1" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="150" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="e594b" class="javax.swing.JLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Search Field"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="2bac" class="javax.swing.JButton" binding="findEHRButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Find EHR"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="674f5" class="javax.swing.JButton" binding="findXrayButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Find xray"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="d567f" class="javax.swing.JButton" binding="generateEHRButton" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Generate EHR"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
141
src/main/java/net/ayyalasomayajula/net/client/Dashboard.java
Normal file
141
src/main/java/net/ayyalasomayajula/net/client/Dashboard.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package net.ayyalasomayajula.net.client;
|
||||
|
||||
import net.ayyalasomayajula.net.shared.Message;
|
||||
import net.ayyalasomayajula.net.shared.MessageVariant;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* The Dashboard class represents the user interface for interacting with the client after a successful connection.
|
||||
* It provides buttons to trigger different actions (e.g., searching for Electronic Health Records (EHRs), finding X-ray files),
|
||||
* and sends relevant messages to the server for processing. It also listens for incoming responses from the server.
|
||||
*/
|
||||
public class Dashboard extends JFrame {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Dashboard.class);
|
||||
|
||||
private JTextField textField1;
|
||||
private JPanel main;
|
||||
private JButton findEHRButton;
|
||||
private JButton findXrayButton;
|
||||
private JButton generateEHRButton;
|
||||
private JTextArea messageDisplayArea;
|
||||
private Socket connection;
|
||||
private ObjectOutputStream outputStream;
|
||||
private ObjectInputStream inputStream;
|
||||
private List<Message> receivedMessages;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Dashboard} frame, initializing the GUI components and setting up
|
||||
* the button actions to send requests to the server. It also starts a background thread to listen
|
||||
* for incoming messages from the server.
|
||||
*
|
||||
* @param connection The active socket connection to the server.
|
||||
*/
|
||||
public Dashboard(Socket connection) {
|
||||
this.connection = connection;
|
||||
this.receivedMessages = new CopyOnWriteArrayList<>(); // Store messages
|
||||
|
||||
try {
|
||||
this.outputStream = new ObjectOutputStream(connection.getOutputStream());
|
||||
this.inputStream = new ObjectInputStream(connection.getInputStream());
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to create output/input streams: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// Setup GUI components (buttons, text fields, etc.)
|
||||
setTitle("Client Dashboard");
|
||||
setContentPane(main);
|
||||
setSize(800, 600);
|
||||
setVisible(true);
|
||||
|
||||
// Action listener for "Find EHR" button
|
||||
findEHRButton.addActionListener(e -> sendMessage("EHR", textField1.getText()));
|
||||
|
||||
// Action listener for "Find X-ray" button
|
||||
findXrayButton.addActionListener(e -> sendMessage("XRAY", textField1.getText()));
|
||||
|
||||
// Action listener for "Generate EHR" button
|
||||
generateEHRButton.addActionListener(e -> generateEHR());
|
||||
|
||||
// Start the thread to listen for incoming messages
|
||||
new Thread(this::listenForMessages).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the server with the specified asset type and asset ID.
|
||||
* The message is wrapped in a {@link Message} object and sent to the server via the output stream.
|
||||
*
|
||||
* @param assetType The type of asset (either "EHR" or "XRAY").
|
||||
* @param assetId The ID of the asset, typically the UUID or path.
|
||||
*/
|
||||
private void sendMessage(String assetType, String assetId) {
|
||||
try {
|
||||
String query = assetType + " " + assetId;
|
||||
logger.info("Query: {}", query);
|
||||
Message message = new Message(MessageVariant.GET, query, 5, new byte[]{});
|
||||
|
||||
// Ensure the message is written to the output stream
|
||||
outputStream.writeObject(message);
|
||||
outputStream.flush(); // Flush to ensure the message is sent
|
||||
logger.info("Sent {} request for asset ID: {}", assetType, assetId);
|
||||
|
||||
// Wait for a response from the server
|
||||
Message response = (Message) inputStream.readObject();
|
||||
updateMessageDisplay(response); // Update the display with the server's response
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
logger.error("Failed to send message: {}", e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the server to generate an EHR. This simulates the generation of a new EHR.
|
||||
*/
|
||||
private void generateEHR() {
|
||||
try {
|
||||
String query = "EHR generate";
|
||||
Message message = new Message(MessageVariant.GET, query, 5, new byte[]{});
|
||||
outputStream.writeObject(message);
|
||||
logger.info("Sent request to generate new EHR.");
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to send EHR generation request: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for incoming messages from the server and stores them in the list of received messages.
|
||||
* It also updates the message display area in the GUI to show new messages.
|
||||
*/
|
||||
private void listenForMessages() {
|
||||
try {
|
||||
while (true) {
|
||||
// Read the next message from the server
|
||||
Message receivedMessage = (Message) inputStream.readObject();
|
||||
receivedMessages.add(receivedMessage);
|
||||
updateMessageDisplay(receivedMessage); // Update the GUI with the new message
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
logger.error("Error while listening for messages: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the message display area in the GUI with the received message.
|
||||
* This method is called whenever a new message is received from the server.
|
||||
*
|
||||
* @param receivedMessage The message received from the server.
|
||||
*/
|
||||
private void updateMessageDisplay(Message receivedMessage) {
|
||||
String displayText = "Received: " + receivedMessage.messageQuery() + "\n";
|
||||
messageDisplayArea.append(displayText); // Append the message to the display area
|
||||
messageDisplayArea.setCaretPosition(messageDisplayArea.getDocument().getLength()); // Auto-scroll to the bottom
|
||||
}
|
||||
}
|
||||
105
src/main/java/net/ayyalasomayajula/net/server/EHRUtils.java
Normal file
105
src/main/java/net/ayyalasomayajula/net/server/EHRUtils.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package net.ayyalasomayajula.net.server;
|
||||
|
||||
import net.ayyalasomayajula.net.shared.EHR;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.UUID;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class for handling EHR operations: serialization, deserialization, and searching.
|
||||
*/
|
||||
public class EHRUtils {
|
||||
|
||||
/**
|
||||
* Constructs the file path for a given EHR based on its UUID.
|
||||
*
|
||||
* @param dirPath The base directory for storing EHRs.
|
||||
* @param ehrUUID The UUID of the EHR.
|
||||
* @return The full path to the EHR file.
|
||||
*/
|
||||
public static Path getEHRFilePath(Path dirPath, UUID ehrUUID) {
|
||||
return dirPath.resolve(ehrUUID.toString() + ".ehr");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an EHR object to a file.
|
||||
*
|
||||
* @param ehr The EHR object to write.
|
||||
* @param dirPath The directory where the file will be stored.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public static void writeEHRToFile(EHR ehr, Path dirPath) throws IOException {
|
||||
if (!Files.exists(dirPath)) {
|
||||
Files.createDirectories(dirPath);
|
||||
}
|
||||
|
||||
Path filePath = getEHRFilePath(dirPath, ehr.getUuid());
|
||||
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath.toFile()))) {
|
||||
oos.writeObject(ehr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and deserializes an EHR object from a file.
|
||||
*
|
||||
* @param dirPath The directory containing the EHR files.
|
||||
* @param ehrUUID The UUID of the EHR to retrieve.
|
||||
* @return The deserialized EHR object, or null if not found.
|
||||
*/
|
||||
public static EHR readEHRFromFile(Path dirPath, UUID ehrUUID) {
|
||||
Path filePath = getEHRFilePath(dirPath, ehrUUID);
|
||||
if (!Files.exists(filePath)) return null;
|
||||
|
||||
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath.toFile()))) {
|
||||
return (EHR) ois.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for the closest matching EHR based on an asset ID (UUID or patient name).
|
||||
*
|
||||
* @param assetId The UUID string or patient name to search for.
|
||||
* @param dirPath The directory containing serialized EHR files.
|
||||
* @return The closest matching EHR, or null if none are found.
|
||||
*/
|
||||
public static EHR searchClosestEHR(String assetId, Path dirPath) {
|
||||
File[] ehrFiles = dirPath.toFile().listFiles((dir, name) -> name.endsWith(".ehr"));
|
||||
if (ehrFiles == null || ehrFiles.length == 0) return null;
|
||||
|
||||
return List.of(ehrFiles).stream()
|
||||
.map(file -> readEHRFromFile(dirPath, UUID.fromString(file.getName().replace(".ehr", ""))))
|
||||
.filter(ehr -> ehr != null)
|
||||
.min(Comparator.comparingInt(ehr -> Math.min(
|
||||
levenshteinDistance(ehr.getUuid().toString(), assetId),
|
||||
levenshteinDistance(ehr.getPatientName(), assetId)
|
||||
)))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the Levenshtein distance between two strings.
|
||||
*
|
||||
* @param s1 First string.
|
||||
* @param s2 Second string.
|
||||
* @return The Levenshtein distance between s1 and s2.
|
||||
*/
|
||||
private static int levenshteinDistance(String s1, String s2) {
|
||||
int[][] dp = new int[s1.length() + 1][s2.length() + 1];
|
||||
|
||||
for (int i = 0; i <= s1.length(); i++)
|
||||
for (int j = 0; j <= s2.length(); j++)
|
||||
if (i == 0) dp[i][j] = j;
|
||||
else if (j == 0) dp[i][j] = i;
|
||||
else dp[i][j] = Math.min(dp[i - 1][j - 1] + (s1.charAt(i - 1) == s2.charAt(j - 1) ? 0 : 1),
|
||||
Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1));
|
||||
|
||||
return dp[s1.length()][s2.length()];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package net.ayyalasomayajula.net.server;
|
||||
|
||||
import net.ayyalasomayajula.net.shared.EHR;
|
||||
import net.ayyalasomayajula.net.shared.Message;
|
||||
import net.ayyalasomayajula.net.shared.MessageVariant;
|
||||
import net.ayyalasomayajula.net.shared.SerializationUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -12,6 +16,8 @@ import java.util.Scanner;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* The ServerDaemon class implements a server daemon that listens for incoming client connections.
|
||||
@@ -19,8 +25,9 @@ import java.util.concurrent.TimeUnit;
|
||||
* and handles incoming socket connections using a thread pool for concurrency.
|
||||
*/
|
||||
public class ServerDaemon implements Runnable {
|
||||
private static final String patientEhrs = "patients/";
|
||||
private static final Logger logger = LoggerFactory.getLogger(ServerDaemon.class);
|
||||
|
||||
private String basePath = "";
|
||||
/**
|
||||
* The entry point of the server daemon that sets up the server, initializes root paths,
|
||||
* and listens for client connections.
|
||||
@@ -40,7 +47,7 @@ public class ServerDaemon implements Runnable {
|
||||
boolean success = initRootPath(path);
|
||||
if (!success) throw new RuntimeException("Your Path is dysfunctional");
|
||||
}
|
||||
|
||||
basePath=path.toString();
|
||||
try {
|
||||
ServerSocket serverSocket = new ServerSocket(8475);
|
||||
logger.info("Server to handle connections has been made at: {} on 0.0.0.0", serverSocket.getLocalPort());
|
||||
@@ -55,7 +62,7 @@ public class ServerDaemon implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
handleConnections(socketToPass);
|
||||
} catch (IOException e) {
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +116,7 @@ public class ServerDaemon implements Runnable {
|
||||
}
|
||||
|
||||
// Create the patient directory
|
||||
String patientEhrs = "patients/";
|
||||
|
||||
Path patientPath = path.resolve(patientEhrs);
|
||||
File dir = patientPath.toFile();
|
||||
|
||||
@@ -147,10 +154,76 @@ public class ServerDaemon implements Runnable {
|
||||
* @param socket The socket for the incoming connection.
|
||||
* @throws IOException If an I/O error occurs while setting up the streams.
|
||||
*/
|
||||
private void handleConnections(Socket socket) throws IOException {
|
||||
private void handleConnections(Socket socket) throws IOException, ClassNotFoundException {
|
||||
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
objectOutputStream.flush(); // Important to flush the stream to avoid issues on the first write
|
||||
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
|
||||
|
||||
// Further processing can be added here
|
||||
logger.info("Got a handle running on the socket. Will await new message objects.");
|
||||
|
||||
Object readBuffer = objectInputStream.readObject();
|
||||
|
||||
while (socket.isConnected()) {
|
||||
if (readBuffer instanceof Message intercepted) {
|
||||
// Handle the received Message
|
||||
Message toPush = handleMessage(intercepted);
|
||||
objectOutputStream.writeObject(toPush);
|
||||
objectOutputStream.flush(); // Ensure the response is sent
|
||||
}
|
||||
// Keep reading from the input stream
|
||||
readBuffer = objectInputStream.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
private Message handleMessage(Message in) throws IOException {
|
||||
switch (in.messageVariant()) {
|
||||
case GET: {
|
||||
// Format of GET query:
|
||||
// <asset_type> <asset_id> | asset types: EHR, XRAY | asset id: uuid field or the path
|
||||
|
||||
// Define regex pattern with capture groups
|
||||
Pattern pattern = Pattern.compile("^(EHR|XRAY) (.+)$");
|
||||
|
||||
Matcher matcher = pattern.matcher(in.messageQuery());
|
||||
if (matcher.matches()) {
|
||||
String assetType = matcher.group(1); // Captures EHR or XRAY
|
||||
String assetId = matcher.group(2); // Captures UUID or path
|
||||
logger.debug("Asset Type: {}", assetType);
|
||||
logger.debug("Asset ID: {}", assetId);
|
||||
|
||||
switch (assetType) {
|
||||
case "EHR":
|
||||
logger.info("EHR caught");
|
||||
EHR found = EHRUtils.searchClosestEHR(assetId, Path.of(basePath));
|
||||
return new Message(MessageVariant.SET, "", 5, SerializationUtils.toBytes(found));
|
||||
case "XRAY":
|
||||
logger.info("XRAY caught");
|
||||
// Construct full file path for XRAY asset
|
||||
Path xrayFilePath = Path.of(basePath, assetId);
|
||||
File xrayFile = xrayFilePath.toFile();
|
||||
|
||||
// Check if the file exists and is a valid file
|
||||
if (xrayFile.exists() && xrayFile.isFile()) {
|
||||
// Read the file into a byte array and return it
|
||||
try (FileInputStream fis = new FileInputStream(xrayFile)) {
|
||||
byte[] fileBytes = fis.readAllBytes();
|
||||
return new Message(MessageVariant.SET, "", 5, fileBytes);
|
||||
} catch (IOException e) {
|
||||
logger.error("Error reading XRAY file: {}", e.getMessage());
|
||||
return new Message(MessageVariant.SET, "ERROR: Failed to read XRAY file.", 5, new byte[]{});
|
||||
}
|
||||
} else {
|
||||
logger.error("XRAY file not found or invalid path: {}", xrayFilePath);
|
||||
return new Message(MessageVariant.SET, "ERROR: XRAY file not found.", 5, new byte[]{});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("No match found for: {}", in.messageQuery());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Message(MessageVariant.SET, "THROW;", 5, new byte[]{});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
package net.ayyalasomayajula.net.shared;
|
||||
|
||||
import net.ayyalasomayajula.net.shared.Appointment;
|
||||
import net.ayyalasomayajula.net.shared.Message;
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.ayyalasomayajula.net.shared;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Utility class for serializing and deserializing objects to and from byte arrays.
|
||||
* This class provides methods for converting an object into a byte array and vice versa.
|
||||
*/
|
||||
public class SerializationUtils {
|
||||
|
||||
/**
|
||||
* Serializes an object to a byte array.
|
||||
*
|
||||
* @param obj the object to serialize
|
||||
* @return a byte array representing the serialized object
|
||||
* @throws IOException if an I/O error occurs during serialization
|
||||
*/
|
||||
public static byte[] toBytes(Object obj) throws IOException {
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
|
||||
oos.writeObject(obj);
|
||||
oos.flush();
|
||||
return bos.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a byte array to an object.
|
||||
*
|
||||
* @param bytes the byte array to deserialize
|
||||
* @return the deserialized object
|
||||
* @throws IOException if an I/O error occurs during deserialization
|
||||
* @throws ClassNotFoundException if the class of a serialized object cannot be found
|
||||
*/
|
||||
public static Object fromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(bis)) {
|
||||
return ois.readObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
target/classes/net/ayyalasomayajula/net/client/Dashboard.class
Normal file
BIN
target/classes/net/ayyalasomayajula/net/client/Dashboard.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user