package com.server;
import java.sql.*;
import java.security.SecureRandom;
import java.util.Base64;
import org.apache.commons.codec.digest.Crypt;
public class MessageDatabase_217230206 {
private static MessageDatabase_217230206 dbInstance = null;
private Connection dbconnection = null;
private SecureRandom secureRandom = new SecureRandom();
public static synchronized MessageDatabase_217230206 getInstance() {
if (dbInstance == null) {
dbInstance = new MessageDatabase_217230206();
}
return dbInstance;
}
public void open(String databaseName) throws SQLException {
if (dbconnection != null && !dbconnection.isClosed()) {
return;
}
String connectionString = "jdbc:sqlite:" + databaseName;
dbconnection = DriverManager.getConnection(connectionString);
System.out.println("Connected to database: " + databaseName);
initializeTables();
}
public void close() throws SQLException {
if (dbconnection != null && !dbconnection.isClosed()) {
dbconnection.close();
System.out.println("Database connection closed");
}
}
private void initializeTables() throws SQLException {
String createUsersTable = "CREATE TABLE IF NOT EXISTS users ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "username VARCHAR(50) UNIQUE NOT NULL, "
+ "password VARCHAR(255) NOT NULL, "
+ "email VARCHAR(50) NOT NULL, "
+ "userNickname VARCHAR(50) NOT NULL, "
+ "salt VARCHAR(100) NOT NULL"
+ ");";
String createMessagesTable = "CREATE TABLE IF NOT EXISTS messages ("
+ "locationID INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "locationName VARCHAR(100) NOT NULL, "
+ "locationDescription TEXT NOT NULL, "
+ "locationCity VARCHAR(50) NOT NULL, "
+ "locationCountry VARCHAR(50), "
+ "locationStreetAddress VARCHAR(100), "
+ "latitude REAL, "
+ "longitude REAL, "
+ "originalPostingTime BIGINT NOT NULL, "
+ "originalPoster VARCHAR(50) NOT NULL, "
+ "username VARCHAR(50) NOT NULL, "
+ "weather VARCHAR(50)"
+ ");";
try (Statement createStatement = dbconnection.createStatement()) {
createStatement.executeUpdate(createUsersTable);
createStatement.executeUpdate(createMessagesTable);
System.out.println("Database tables created successfully");
}
}
public boolean userExists(String username) throws SQLException {
final String sql = "SELECT COUNT(*) as count FROM users WHERE username = ?";
try (PreparedStatement pstmt = dbconnection.prepareStatement(sql)) {
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getInt("count") > 0;
}
return false;
}
}
private String hashPassword(String password) {
byte[] bytes = new byte[13];
secureRandom.nextBytes(bytes);
String saltBytes = Base64.getEncoder().encodeToString(bytes);
String salt = "$6$" + saltBytes;
return Crypt.crypt(password, salt);
}
public boolean addUser(String username, String password, String email, String userNickname) throws SQLException {
final String sql = "INSERT INTO users (username, password, email, userNickname, salt) VALUES (?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = dbconnection.prepareStatement(sql)) {
String hashedPassword = hashPassword(password);
pstmt.setString(1, username);
pstmt.setString(2, hashedPassword);
pstmt.setString(3, email);
pstmt.setString(4, userNickname);
pstmt.setString(5, hashedPassword.substring(0, 20));
pstmt.executeUpdate();
return true;
} catch (SQLException e) {
if (e.getErrorCode() == 19 || e.getMessage().contains("UNIQUE constraint failed")) {
return false;
}
throw e;
}
}
public boolean validateUser(String username, String password) throws SQLException {
final String sql = "SELECT password FROM users WHERE username = ?";
try (PreparedStatement pstmt = dbconnection.prepareStatement(sql)) {
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
String storedHashedPassword = rs.getString("password");
String computedHash = Crypt.crypt(password, storedHashedPassword);
return storedHashedPassword.equals(computedHash);
}
return false;
}
}
public String getUserNickname(String username) throws SQLException {
final String sql = "SELECT userNickname FROM users WHERE username = ?";
try (PreparedStatement pstmt = dbconnection.prepareStatement(sql)) {
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getString("userNickname");
}
return null;
}
}
public boolean addMessage(String locationName, String locationDescription,
String locationCity, String locationCountry,
String locationStreetAddress, Double latitude,
Double longitude, long originalPostingTime,
String username, String weather) throws SQLException {
if (!userExists(username)) {
System.out.println("User " + username + " does not exist");
return false;
}
String userNickname = getUserNickname(username);
if (userNickname == null) {
userNickname = username;
}
final String sql = "INSERT INTO messages (locationName, locationDescription, locationCity, " +
"locationCountry, locationStreetAddress, latitude, longitude, " +
"originalPostingTime, originalPoster, username, weather) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try (PreparedStatement pstmt = dbconnection.prepareStatement(sql)) {
pstmt.setString(1, locationName);
pstmt.setString(2, locationDescription);
pstmt.setString(3, locationCity);
pstmt.setString(4, locationCountry);
pstmt.setString(5, locationStreetAddress);
if (latitude != null) {
pstmt.setDouble(6, latitude);
} else {
pstmt.setNull(6, Types.DOUBLE);
}
if (longitude != null) {
pstmt.setDouble(7, longitude);
} else {
pstmt.setNull(7, Types.DOUBLE);
}
pstmt.setLong(8, originalPostingTime);
pstmt.setString(9, userNickname);
pstmt.setString(10, username);
if (weather != null) {
pstmt.setString(11, weather);
} else {
pstmt.setNull(11, Types.VARCHAR);
}
pstmt.executeUpdate();
return true;
} catch (SQLException e) {
System.err.println("Error adding message: " + e.getMessage());
e.printStackTrace();
return false;
}
}
public ResultSet getAllMessages() throws SQLException {
final String sql = "SELECT locationID, locationName, locationDescription, locationCity, " +
"locationCountry, locationStreetAddress, latitude, longitude, " +
"originalPostingTime, originalPoster, weather " +
"FROM messages " +
"ORDER BY originalPostingTime DESC";
Statement statement = dbconnection.createStatement();
return statement.executeQuery(sql);
}
}package com.server;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.stream.Collectors;
import org.json.JSONException;
import org.json.JSONObject;
public class RegistrationHandler_217230206 implements HttpHandler{
private final UserAuthenticator_217230206 userAuthenticator;
private final MessageDatabase_217230206 database;
public RegistrationHandler_217230206(UserAuthenticator_217230206 userAuthenticator, MessageDatabase_217230206 database) {
this.userAuthenticator = userAuthenticator;
this.database = database;
}
@Override
public void handle(HttpExchange exchange) throws IOException {
String requestMethod = exchange.getRequestMethod();
try {
if (requestMethod.equalsIgnoreCase("POST")) {
handlePostRequest(exchange);
} else {
handleUnsupportedRequest(exchange);
}
} catch (Exception e) {
sendErrorResponse(exchange, 500, "Internal Server Error");
}
}
private void handlePostRequest(HttpExchange exchange) throws IOException {
String contentType = exchange.getRequestHeaders().getFirst("Content-Type");
if (contentType == null || !contentType.equals("application/json")) {
sendErrorResponse(exchange, 400, "Content-Type must be application/json");
return;
}
String content;
try (InputStream stream = exchange.getRequestBody();
InputStreamReader isr = new InputStreamReader(stream, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
content = br.lines().collect(Collectors.joining("\n"));
}
try {
JSONObject json = new JSONObject(content);
if (!json.has("username") || !json.has("password") ||
!json.has("email") || !json.has("userNickname")) {
sendErrorResponse(exchange, 400, "Missing required fields: username, password, email, userNickname");
return;
}
String username = json.getString("username").trim();
String password = json.getString("password").trim();
String email = json.getString("email").trim();
String userNickname = json.getString("userNickname").trim();
if (username.isEmpty() || password.isEmpty() || email.isEmpty() || userNickname.isEmpty()) {
sendErrorResponse(exchange, 400, "All fields must not be empty");
return;
}
boolean dbSuccess = database.addUser(username, password, email, userNickname);
if (dbSuccess) {
userAuthenticator.addUser(username, password, email, userNickname);
JSONObject responseJson = new JSONObject();
responseJson.put("message", "User registered successfully");
responseJson.put("username", username);
sendJsonResponse(exchange, 200, responseJson);
} else {
sendErrorResponse(exchange, 409, "User already registered");
}
} catch (JSONException e) {
sendErrorResponse(exchange, 400, "Invalid JSON format: " + e.getMessage());
} catch (SQLException e) {
if (e.getMessage() != null &&
(e.getMessage().contains("UNIQUE constraint failed") ||
e.getMessage().contains("unique constraint") ||
e.getErrorCode() == 19)) {
sendErrorResponse(exchange, 409, "User already registered");
} else {
System.err.println("Database error during registration: " + e.getMessage());
sendErrorResponse(exchange, 500, "Database error: " + e.getMessage());
}
} catch (Exception e) {
System.err.println("Unexpected error during registration: " + e.getMessage());
sendErrorResponse(exchange, 500, "Internal server error");
}
}
private void handleUnsupportedRequest(HttpExchange exchange) throws IOException {
sendErrorResponse(exchange, 400, "Not supported");
}
private void sendErrorResponse(HttpExchange exchange, int code, String message) throws IOException {
JSONObject errorJson = new JSONObject();
errorJson.put("error", message);
sendJsonResponse(exchange, code, errorJson);
}
private void sendJsonResponse(HttpExchange exchange, int code, JSONObject json) throws IOException {
String response = json.toString();
byte[] bytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
exchange.sendResponseHeaders(code, bytes.length);
try (OutputStream outputStream = exchange.getResponseBody()) {
outputStream.write(bytes);
}
}
}
package com.server;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Base64;
public class RequestHandler_217230206 implements HttpHandler {
private final MessageDatabase_217230206 database;
private final WeatherServiceClient_217230206 weatherClient;
public RequestHandler_217230206(MessageDatabase_217230206 database) {
this.database = database;
this.weatherClient = new WeatherServiceClient_217230206("http://localhost:4001/weather");
}
@Override
public void handle(HttpExchange exchange) throws IOException {
String requestMethod = exchange.getRequestMethod();
try {
if (requestMethod.equalsIgnoreCase("GET")) {
handleGetRequest(exchange);
} else if (requestMethod.equalsIgnoreCase("POST")) {
handlePostRequest(exchange);
} else {
sendErrorResponse(exchange, 405, "Method Not Allowed");
}
} catch (Exception e) {
sendErrorResponse(exchange, 500, "Internal Server Error");
}
}
private void handleGetRequest(HttpExchange exchange) throws IOException {
if (!authenticateUser(exchange)) {
return;
}
try {
ResultSet rs = database.getAllMessages();
JSONArray responseArray = new JSONArray();
boolean hasMessages = false;
while (rs.next()) {
hasMessages = true;
JSONObject messageJson = new JSONObject();
messageJson.put("locationID", rs.getInt("locationID"));
messageJson.put("locationName", rs.getString("locationName"));
messageJson.put("locationCountry", rs.getString("locationCountry"));
messageJson.put("locationDescription", rs.getString("locationDescription"));
messageJson.put("locationCity", rs.getString("locationCity"));
messageJson.put("longitude", rs.getDouble("longitude"));
messageJson.put("latitude", rs.getDouble("latitude"));
String locationCountry = rs.getString("locationCountry");
if (locationCountry != null && !rs.wasNull()) {
messageJson.put("locationCountry", locationCountry);
} else {
messageJson.put("locationCountry", "");
}
String locationStreetAddress = rs.getString("locationStreetAddress");
if (locationStreetAddress != null && !rs.wasNull()) {
messageJson.put("locationStreetAddress", locationStreetAddress);
} else {
messageJson.put("locationStreetAddress", "");
}
double latitude = rs.getDouble("latitude");
if (!rs.wasNull()) {
messageJson.put("latitude", latitude);
}
double longitude = rs.getDouble("longitude");
if (!rs.wasNull()) {
messageJson.put("longitude", longitude);
}
messageJson.put("originalPoster", rs.getString("originalPoster"));
long epochMillis = rs.getLong("originalPostingTime");
String isoTime = convertEpochToISO(epochMillis);
messageJson.put("originalPostingTime", isoTime);
String weather = rs.getString("weather");
if (!rs.wasNull() && weather != null) {
messageJson.put("weather", weather);
}
responseArray.put(messageJson);
}
try {
if (rs != null) {
Statement stmt = rs.getStatement();
rs.close();
if (stmt != null) {
stmt.close();
}
}
} catch (SQLException e) {
System.err.println("Error closing resources: " + e.getMessage());
}
if (!hasMessages) {
exchange.sendResponseHeaders(204, -1);
} else {
sendJsonResponse(exchange, 200, responseArray);
}
} catch (SQLException e) {
sendErrorResponse(exchange, 500, "Database error: " + e.getMessage());
}
}
private void handlePostRequest(HttpExchange exchange) throws IOException {
if (!authenticateUser(exchange)) {
return;
}
String contentType = exchange.getRequestHeaders().getFirst("Content-Type");
if (contentType == null || !contentType.equals("application/json")) {
sendErrorResponse(exchange, 400, "Content-Type must be application/json");
return;
}
String requestBody = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
try {
JSONObject json = new JSONObject(requestBody);
if (!json.has("locationName") || !json.has("locationDescription") ||
!json.has("locationCity") || !json.has("originalPostingTime")) {
sendErrorResponse(exchange, 400, "Missing required fields: locationName, locationDescription, locationCity, originalPostingTime");
return;
}
String locationName = json.getString("locationName").trim();
String locationDescription = json.getString("locationDescription").trim();
String locationCity = json.getString("locationCity").trim();
String originalPostingTimeStr = json.getString("originalPostingTime").trim();
String locationCountry = json.optString("locationCountry", "").trim();
String locationStreetAddress = json.optString("locationStreetAddress", "").trim();
Double latitude = null;
Double longitude = null;
if (json.has("latitude") && !json.isNull("latitude")) {
try {
latitude = json.getDouble("latitude");
} catch (Exception e) {
}
}
if (json.has("longitude") && !json.isNull("longitude")) {
try {
longitude = json.getDouble("longitude");
} catch (Exception e) {
}
}
String weather = null;
boolean hasWeatherInRequest = json.has("weather") && !json.isNull("weather");
if (hasWeatherInRequest) {
weather = json.optString("weather", null);
}
if (locationName.isEmpty() || locationDescription.isEmpty() || locationCity.isEmpty()) {
sendErrorResponse(exchange, 400, "All required fields must not be empty");
return;
}
long epochMillis = validateAndParseTimestamp(exchange, originalPostingTimeStr);
if (epochMillis == -1) {
return;
}
String authHeader = exchange.getRequestHeaders().getFirst("Authorization");
String username = extractUsernameFromAuth(authHeader);
if (latitude != null && longitude != null) {
String weatherInfo = weatherClient.getWeather(latitude, longitude);
if (weatherInfo != null) {
weather = weatherInfo;
System.out.println("Retrieved weather: " + weatherInfo);
} else {
System.out.println("Failed to retrieve weather information");
}
}
boolean success = database.addMessage(locationName, locationDescription,
locationCity, locationCountry,
locationStreetAddress, latitude,
longitude, epochMillis, username, weather);
if (success) {
JSONObject responseJson = new JSONObject();
responseJson.put("message", "Message stored successfully");
responseJson.put("locationName", locationName);
responseJson.put("originalPostingTime", originalPostingTimeStr);
if (latitude != null) {
responseJson.put("latitude", latitude);
}
if (longitude != null) {
responseJson.put("longitude", longitude);
}
if (weather != null) {
responseJson.put("weather", weather);
}
sendJsonResponse(exchange, 200, responseJson);
} else {
sendErrorResponse(exchange, 500, "Failed to store message");
}
} catch (JSONException e) {
sendErrorResponse(exchange, 400, "Invalid JSON format: " + e.getMessage());
} catch (SQLException e) {
sendErrorResponse(exchange, 500, "Database error: " + e.getMessage());
}
}
private boolean authenticateUser(HttpExchange exchange) throws IOException {
String authHeader = exchange.getRequestHeaders().getFirst("Authorization");
if (authHeader == null || !authHeader.startsWith("Basic ")) {
sendErrorResponse(exchange, 401, "Authentication required");
return false;
}
try {
String encodedCredentials = authHeader.substring("Basic ".length()).trim();
byte[] decodedBytes = Base64.getDecoder().decode(encodedCredentials);
String credentials = new String(decodedBytes, StandardCharsets.UTF_8);
String[] parts = credentials.split(":", 2);
if (parts.length != 2) {
sendErrorResponse(exchange, 401, "Invalid authentication credentials");
return false;
}
String userName = parts[0];
String password = parts[1];
if (database.validateUser(userName, password)) {
return true;
} else {
sendErrorResponse(exchange, 401, "Invalid username or password");
return false;
}
} catch (Exception e) {
sendErrorResponse(exchange, 401, "Invalid authentication credentials");
return false;
}
}
private String extractUsernameFromAuth(String authHeader) {
try {
String encodedCredentials = authHeader.substring("Basic ".length()).trim();
byte[] decodedBytes = Base64.getDecoder().decode(encodedCredentials);
String credentials = new String(decodedBytes, StandardCharsets.UTF_8);
String[] parts = credentials.split(":", 2);
if (parts.length == 2) {
return parts[0];
}
} catch (Exception e) {
}
return null;
}
private long validateAndParseTimestamp(HttpExchange exchange, String timestampStr) throws IOException {
if (timestampStr == null || timestampStr.trim().isEmpty()) {
sendErrorResponse(exchange, 400, "Timestamp cannot be empty");
return -1;
}
try {
Instant instant = Instant.parse(timestampStr);
long epochMillis = instant.toEpochMilli();
if (!isValidTimestamp(epochMillis)) {
sendErrorResponse(exchange, 400, "Invalid timestamp value");
return -1;
}
return epochMillis;
} catch (DateTimeParseException e) {
sendErrorResponse(exchange, 400, "Invalid timestamp format. Use ISO 8601 UTC format like: 2024-01-15T10:30:00.000Z");
return -1;
}
}
private boolean isValidTimestamp(long epochMillis) {
long currentTime = System.currentTimeMillis();
long reasonablePast = currentTime - (100L * 365 * 24 * 60 * 60 * 1000);
long reasonableFuture = currentTime + (10L * 365 * 24 * 60 * 60 * 1000);
return epochMillis >= reasonablePast && epochMillis <= reasonableFuture;
}
private String convertEpochToISO(long epochMillis) {
return ZonedDateTime.ofInstant(
java.time.Instant.ofEpochMilli(epochMillis),
ZoneId.of("UTC")
).format(DateTimeFormatter.ISO_INSTANT);
}
private void sendJsonResponse(HttpExchange exchange, int statusCode, Object json) throws IOException {
String response = json.toString();
byte[] responseBytes = response.getBytes(StandardCharsets.UTF_8);
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
exchange.sendResponseHeaders(statusCode, responseBytes.length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(responseBytes);
}
}
private void sendErrorResponse(HttpExchange exchange, int code, String message) throws IOException {
JSONObject errorJson = new JSONObject();
errorJson.put("error", message);
sendJsonResponse(exchange, code, errorJson);
}
}package com.server;
import com.sun.net.httpserver.HttpsServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpContext;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import java.io.*;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.sql.SQLException;
import javax.net.ssl.KeyManagerFactory;
import java.util.concurrent.Executors;
public class Server {
private static SSLContext myServerSSLContext(String keystorePath, String keystorePassword) throws Exception {
KeyStore ks = KeyStore.getInstance("JKS");
File keystoreFile = new File(keystorePath);
if (!keystoreFile.exists()) {
throw new FileNotFoundException("Keystore file not found: " + keystorePath);
}
try (FileInputStream fis = new FileInputStream(keystoreFile)) {
ks.load(fis, keystorePassword.toCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keystorePassword.toCharArray());
SSLContext ssl = SSLContext.getInstance("TLS");
ssl.init(kmf.getKeyManagers(), null, null);
return ssl;
}
public static void main(String[] args) throws IOException {
try {
System.out.println("Starting server initialization...");
Class.forName("org.sqlite.JDBC");
String keystorePath;
String keystorePassword;
if (args.length < 2) {
System.out.println("No arguments provided, using default keystore.jks and password 'password'");
keystorePath = "keystore.jks";
keystorePassword = "password";
} else {
keystorePath = args[0];
keystorePassword = args[1];
}
File keystoreFile = new File(keystorePath);
if (!keystoreFile.exists()) {
System.out.println("Keystore file not found: " + keystorePath);
System.out.println("Please generate keystore.jks file first");
return;
}
MessageDatabase_217230206 database = MessageDatabase_217230206.getInstance();
database.open("MessageDB.db");
System.out.println("Database opened successfully");
try {
if (database.userExists("test")) {
System.out.println("Database connection test passed");
}
} catch (SQLException e) {
System.err.println("Database connection test failed: " + e.getMessage());
}
HttpsServer server = HttpsServer.create(new InetSocketAddress(8001), 0);
SSLContext sslContext = myServerSSLContext(keystorePath, keystorePassword);
server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
@Override
public void configure(HttpsParameters params) {
SSLParameters sslparams = getSSLContext().getDefaultSSLParameters();
params.setSSLParameters(sslparams);
}
});
server.setExecutor(Executors.newCachedThreadPool());
System.out.println("Multi-threaded executor enabled");
UserAuthenticator_217230206 authenticator = new UserAuthenticator_217230206(database);
HttpContext infoContext = server.createContext("/info", new RequestHandler_217230206(database));
infoContext.setAuthenticator(authenticator);
server.createContext("/registration", new RegistrationHandler_217230206(authenticator, database));
server.start();
System.out.println("HTTPS Server started on port 8001");
System.out.println("Database: MessageDB.db");
System.out.println("Available endpoints:");
System.out.println("- /info (requires authentication)");
System.out.println("- /registration (user registration)");
System.out.println("Server is ready for testing");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("Shutting down server...");
try {
database.close();
} catch (SQLException e) {
System.err.println("Error closing database: " + e.getMessage());
}
server.stop(0);
System.out.println("Server stopped gracefully");
}));
} catch (FileNotFoundException e) {
System.out.println("Certificate file not found!");
e.printStackTrace();
} catch (Exception e) {
System.out.println("Error starting server: " + e.getMessage());
e.printStackTrace();
}
}
}package com.server;
public class User_217230206 {
private String username;
private String password;
private String email;
private String userNickname;
public User_217230206(String username, String password, String email, String userNickname) {
this.username = username;
this.password = password;
this.email = email;
this.userNickname = userNickname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUserNickname() {
return userNickname;
}
public void setUserNickname(String userNickname) {
this.userNickname = userNickname;
}
}package com.server;
import com.sun.net.httpserver.BasicAuthenticator;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Map;
public class UserAuthenticator_217230206 extends BasicAuthenticator {
private Map<String, User_217230206> users = null;
private MessageDatabase_217230206 database;
public UserAuthenticator_217230206(MessageDatabase_217230206 database) {
super("info");
this.database = database;
users = new Hashtable<>();
}
@Override
public boolean checkCredentials(String username, String password) {
try {
return database.validateUser(username, password);
} catch (SQLException e) {
return false;
}
}
public boolean addUser(String userName, String password, String email, String userNickname) {
try {
boolean dbSuccess = database.addUser(userName, password, email, userNickname);
if (dbSuccess) {
users.put(userName, new User_217230206(userName, password, email, userNickname));
return true;
}
return false;
} catch (SQLException e) {
return false;
}
}
}package com.server;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class UserMessage_217230206 {
private String locationName;
private String locationDescription;
private String locationCity;
private long originalPostingTime;
public UserMessage_217230206(String locationName, String locationDescription, String locationCity) {
this.locationName = locationName;
this.locationDescription = locationDescription;
this.locationCity = locationCity;
this.originalPostingTime = ZonedDateTime.now(ZoneId.of("UTC")).toInstant().toEpochMilli();
}
public UserMessage_217230206(String locationName, String locationDescription, String locationCity, long originalPostingTime) {
this.locationName = locationName;
this.locationDescription = locationDescription;
this.locationCity = locationCity;
this.originalPostingTime = originalPostingTime;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public String getLocationDescription() {
return locationDescription;
}
public void setLocationDescription(String locationDescription) {
this.locationDescription = locationDescription;
}
public String getLocationCity() {
return locationCity;
}
public void setLocationCity(String locationCity) {
this.locationCity = locationCity;
}
public long getOriginalPostingTime() {
return originalPostingTime;
}
public void setOriginalPostingTime(long originalPostingTime) {
this.originalPostingTime = originalPostingTime;
}
public String getOriginalPostingTimeISO() {
return ZonedDateTime.ofInstant(
java.time.Instant.ofEpochMilli(originalPostingTime),
ZoneId.of("UTC")
).format(DateTimeFormatter.ISO_INSTANT);
}
}
package com.server;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class WeatherServiceClient_217230206 {
private final String weatherServiceUrl;
private final HttpClient httpClient;
public WeatherServiceClient_217230206(String weatherServiceUrl) {
this.weatherServiceUrl = weatherServiceUrl;
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
}
public String getWeather(double latitude, double longitude) {
try {
String xmlBody = String.format(
"<coordinates><latitude>%f</latitude><longitude>%f</longitude></coordinates>",
latitude, longitude
);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(weatherServiceUrl))
.header("Content-Type", "application/xml")
.POST(HttpRequest.BodyPublishers.ofString(xmlBody))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
return extractTemperatureFromXml(response.body());
} else {
System.err.println("Weather service returned error: " + response.statusCode());
return null;
}
} catch (Exception e) {
System.err.println("Error calling weather service: " + e.getMessage());
return null;
}
}
private String extractTemperatureFromXml(String xmlResponse) {
try {
int tempStart = xmlResponse.indexOf("<temperature>") + "<temperature>".length();
int tempEnd = xmlResponse.indexOf("</temperature>");
if (tempStart > 0 && tempEnd > tempStart) {
String temperature = xmlResponse.substring(tempStart, tempEnd);
int unitStart = xmlResponse.indexOf("<Unit>") + "<Unit>".length();
int unitEnd = xmlResponse.indexOf("</Unit>");
String unit = unitStart > 0 && unitEnd > unitStart ?
xmlResponse.substring(unitStart, unitEnd) : "C";
return temperature + unit;
}
} catch (Exception e) {
System.err.println("Error parsing weather XML: " + e.getMessage());
}
return null;
}
}这是已经写的代码,但是没有办法通过测试,有下面两个错误org.opentest4j.AssertionFailedError: Test failed, Object {"locationStreetAddress":"Street of D","locationName":"Place A","locationCountry":"In a C country","locationDescription":"Some random place A","latitude":1.3670745662396455,"originalPoster":"Tallaaja_123","originalPostingTime":"2025-11-18T06:52:31.570Z","locationCity":"City of B","longitude":148.53484155175929} could not be found in response ==] expected: [true] but was: [false]
at com.tests.Week5.testCoordinateDescription(Week5.java:284)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)org.opentest4j.AssertionFailedError: Test failed, user registration returned code 409 ==] expected: [true] but was: [false]
at com.tests.Week5.testRegisterUser(Week5.java:79)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)