Reformat all source files with new formatter

This commit is contained in:
2020-10-19 18:17:51 +02:00
parent 77a75fc37c
commit b2c3cf62c8
142 changed files with 2242 additions and 1591 deletions

View File

@ -6,10 +6,11 @@ import java.util.logging.Level;
import com.jenkov.nioserver.Server;
import envoy.util.EnvoyLog;
import envoy.server.data.*;
import envoy.server.net.*;
import envoy.server.processors.*;
import envoy.util.EnvoyLog;
/**
* Starts the server.
@ -27,8 +28,8 @@ public final class Startup {
/**
* Starts the server.
*
* @param args the run configuration. If it is "no-enter-to-stop" at position 0,
* no command to read in an enter press will be generated
* @param args the run configuration. If it is "no-enter-to-stop" at position 0, no command to
* read in an enter press will be generated
* @throws IOException if the server crashes
* @since Envoy Server Standalone v0.1-alpha
*/
@ -37,32 +38,34 @@ public final class Startup {
config.loadAll(Startup.class, "server.properties", args);
EnvoyLog.initialize(config);
} catch (final IllegalStateException e) {
EnvoyLog.getLogger(Startup.class).log(Level.SEVERE, "Error loading configuration values: ", e);
EnvoyLog.getLogger(Startup.class).log(Level.SEVERE,
"Error loading configuration values: ", e);
System.exit(1);
}
final var server = new Server(8080, ObjectMessageReader::new,
new ObjectMessageProcessor(Set.of(new LoginCredentialProcessor(),
new MessageProcessor(),
new GroupMessageProcessor(),
new GroupCreationProcessor(),
new MessageStatusChangeProcessor(),
new GroupMessageStatusChangeProcessor(),
new UserStatusChangeProcessor(),
new GroupResizeProcessor(),
new IDGeneratorRequestProcessor(),
new UserSearchProcessor(),
new UserOperationProcessor(),
new IsTypingProcessor(),
new NameChangeProcessor(),
new ProfilePicChangeProcessor(),
new PasswordChangeRequestProcessor(),
new IssueProposalProcessor())));
new ObjectMessageProcessor(Set.of(new LoginCredentialProcessor(),
new MessageProcessor(),
new GroupMessageProcessor(),
new GroupCreationProcessor(),
new MessageStatusChangeProcessor(),
new GroupMessageStatusChangeProcessor(),
new UserStatusChangeProcessor(),
new GroupResizeProcessor(),
new IDGeneratorRequestProcessor(),
new UserSearchProcessor(),
new UserOperationProcessor(),
new IsTypingProcessor(),
new NameChangeProcessor(),
new ProfilePicChangeProcessor(),
new PasswordChangeRequestProcessor(),
new IssueProposalProcessor())));
// Initialize the current message ID
final var persistenceManager = PersistenceManager.getInstance();
if (persistenceManager.getConfigItemByID("currentMessageId") == null)
persistenceManager.addConfigItem(new envoy.server.data.ConfigItem("currentMessageId", "0"));
persistenceManager
.addConfigItem(new envoy.server.data.ConfigItem("currentMessageId", "0"));
server.start();
server.getSocketProcessor().registerSocketIdListener(ConnectionManager.getInstance());

View File

@ -6,8 +6,7 @@ import java.util.Set;
import javax.persistence.*;
/**
* This class acts as a superclass for all contacts, being {@link User}s and
* {@link Group}s.
* This class acts as a superclass for all contacts, being {@link User}s and {@link Group}s.
*
* @author Maximilian Käfer
* @since Envoy Server Standalone v0.1-alpha
@ -30,18 +29,16 @@ public abstract class Contact {
protected Set<Contact> contacts;
/**
* @return a {@link envoy.data.Contact} object of this envoy.server.data.Contact
* object.
* @return a {@link envoy.data.Contact} object of this envoy.server.data.Contact object.
* @since Envoy Server Standalone v0.1-beta
*/
public abstract envoy.data.Contact toCommon();
/**
* Transforms this contact into a {@link envoy.data.Contact} where the contacts
* set of contacts is empty.
* Transforms this contact into a {@link envoy.data.Contact} where the contacts set of contacts
* is empty.
*
* @return a {@link envoy.data.Contact} object of this contact
* object.
* @return a {@link envoy.data.Contact} object of this contact object.
* @since Envoy Server Standalone v0.1-beta
*/
protected abstract envoy.data.Contact toFlatCommon();
@ -99,5 +96,8 @@ public abstract class Contact {
public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; }
@Override
public String toString() { return String.format("%s[id=%d,name=%s,%d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); }
public String toString() {
return String.format("%s[id=%d,name=%s,%d contact(s)]", getClass().getSimpleName(), id,
name, contacts.size());
}
}

View File

@ -5,22 +5,16 @@ import java.util.stream.Collectors;
import javax.persistence.*;
/**
* Represents a group inside the database. Referred to as "server group" as
* opposed to "group" from Envoy Common.
* Represents a group inside the database. Referred to as "server group" as opposed to "group" from
* Envoy Common.
*
* @author Maximilian K&auml;fer
* @since Envoy Server Standalone v0.1-alpha
*/
@Entity
@NamedQueries({
@NamedQuery(
name = Group.findByName,
query = "SELECT g FROM Group g WHERE g.name = :name"
),
@NamedQuery(
name = Group.findPendingGroups,
query = "SELECT g FROM Group g WHERE g.creationDate > :lastSeen AND :user MEMBER OF g.contacts"
)
@NamedQuery(name = Group.findByName, query = "SELECT g FROM Group g WHERE g.name = :name"),
@NamedQuery(name = Group.findPendingGroups, query = "SELECT g FROM Group g WHERE g.creationDate > :lastSeen AND :user MEMBER OF g.contacts")
})
public final class Group extends Contact {
@ -32,7 +26,8 @@ public final class Group extends Contact {
public static final String findByName = "Group.findByName";
/**
* Named query retrieving all pending groups for a specific user (parameter {@code :user}, {@code :lastSeen}).
* Named query retrieving all pending groups for a specific user (parameter {@code :user},
* {@code :lastSeen}).
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -40,9 +35,12 @@ public final class Group extends Contact {
@Override
public envoy.data.Group toCommon() {
return new envoy.data.Group(id, name, contacts.parallelStream().map(User.class::cast).map(User::toFlatCommon).collect(Collectors.toSet()));
return new envoy.data.Group(id, name, contacts.parallelStream().map(User.class::cast)
.map(User::toFlatCommon).collect(Collectors.toSet()));
}
@Override
protected envoy.data.Group toFlatCommon() { return toCommon(); }
protected envoy.data.Group toFlatCommon() {
return toCommon();
}
}

View File

@ -12,20 +12,17 @@ import envoy.data.Group;
* @since Envoy Server Standalone v0.1-beta
*/
@Entity
@NamedQuery(
name = GroupMessage.getPendingGroupMsg,
query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE KEY(s) = :userId AND (m.creationDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen "
+ "OR m.lastStatusChangeDate > :lastSeen)"
)
@NamedQuery(name = GroupMessage.getPendingGroupMsg, query = "SELECT m FROM GroupMessage m JOIN m.memberMessageStatus s WHERE KEY(s) = :userId AND (m.creationDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen "
+ "OR m.lastStatusChangeDate > :lastSeen)")
public final class GroupMessage extends Message {
/**
* Named query retrieving pending group messages sent to a group containing a
* specific user (parameter {@code userId}) that were sent after a certain time
* stamp (parameter {@code :lastSeen}).
*
* Named query retrieving pending group messages sent to a group containing a specific user
* (parameter {@code userId}) that were sent after a certain time stamp (parameter
* {@code :lastSeen}).
*
* @since Envoy Server Standalone v0.1-beta
*/
public static final String getPendingGroupMsg = "GroupMessage.getPendingGroupMsg";
@ -46,9 +43,8 @@ public final class GroupMessage extends Message {
/**
* Constructs a database groupMessage from a common groupMessage.
*
* @param groupMessage the {@link envoy.data.GroupMessage} to convert
* into a
* database {@link GroupMessage}
* @param groupMessage the {@link envoy.data.GroupMessage} to convert into a database
* {@link GroupMessage}
* @param lastStatusChangeDate the time stamp to set
* @since Envoy Server Standalone v0.2-beta
*/
@ -59,29 +55,31 @@ public final class GroupMessage extends Message {
}
/**
* Converts this groupMessage into an instance of
* {@link envoy.data.GroupMessage}.
* Converts this groupMessage into an instance of {@link envoy.data.GroupMessage}.
*
* @return a {@link envoy.data.GroupMessage} containing the same values as this
* groupMessage
* @return a {@link envoy.data.GroupMessage} containing the same values as this groupMessage
* @since Envoy Server Standalone v0.1-beta
*/
@Override
public envoy.data.GroupMessage toCommon() {
return prepareBuilder().buildGroupMessage((Group) recipient.toCommon(), new HashMap<>(memberMessageStatus));
return prepareBuilder().buildGroupMessage((Group) recipient.toCommon(),
new HashMap<>(memberMessageStatus));
}
/**
* @return the memberMessageStatus
* @since Envoy Server Standalone v0.1-beta
*/
public Map<Long, envoy.data.Message.MessageStatus> getMemberMessageStatus() { return memberMessageStatus; }
public Map<Long, envoy.data.Message.MessageStatus> getMemberMessageStatus() {
return memberMessageStatus;
}
/**
* @param memberMessageStatus the memberMessageStatus to set
* @since Envoy Server Standalone v0.1-beta
*/
public void setMemberMessageStatus(Map<Long, envoy.data.Message.MessageStatus> memberMessageStatus) {
public void setMemberMessageStatus(
Map<Long, envoy.data.Message.MessageStatus> memberMessageStatus) {
this.memberMessageStatus = memberMessageStatus;
}

View File

@ -12,14 +12,14 @@ import envoy.data.Attachment.AttachmentType;
import envoy.data.Message.MessageStatus;
/**
* This JPA entity, which will be referred to as database message, stores the
* information contained inside a {@link envoy.data.Message} inside the
* database, while having a slightly different data layout.
* This JPA entity, which will be referred to as database message, stores the information contained
* inside a {@link envoy.data.Message} inside the database, while having a slightly different data
* layout.
* <p>
* A message can be converted to a database message by using the
* {@link Message#Message(envoy.data.Message)} constructor. A database message
* can be converted to a regular message using the {@link Message#toCommon()}
* method. In both cases, the objects will not contain references to each other.
* {@link Message#Message(envoy.data.Message)} constructor. A database message can be converted to a
* regular message using the {@link Message#toCommon()} method. In both cases, the objects will not
* contain references to each other.
*
* @author Kai S. K. Engelbart
* @since Envoy Server Standalone v0.1-alpha
@ -27,22 +27,19 @@ import envoy.data.Message.MessageStatus;
@Entity
@Table(name = "messages")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@NamedQuery(
name = Message.getPending,
query = "SELECT m FROM Message m WHERE "
// Send to or by the user before last seen
+ "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen "
// SENT to the user
+ "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT "
// Sent by the user and RECEIVED / READ after last seen
+ "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)"
)
@NamedQuery(name = Message.getPending, query = "SELECT m FROM Message m WHERE "
// Send to or by the user before last seen
+ "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen "
// SENT to the user
+ "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT "
// Sent by the user and RECEIVED / READ after last seen
+ "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)")
public class Message {
/**
* Named query retrieving pending messages for a user (parameter {@code :user})
* which was last seen after a specific date (parameter {@code :lastSeen}).
* Named query retrieving pending messages for a user (parameter {@code :user}) which was last
* seen after a specific date (parameter {@code :lastSeen}).
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -85,8 +82,7 @@ public class Message {
/**
* Constructs a database message from a common message.
*
* @param message the {@link envoy.data.Message} to convert into a database
* {@link Message}
* @param message the {@link envoy.data.Message} to convert into a database {@link Message}
* @since Envoy Server Standalone v0.1-alpha
*/
public Message(envoy.data.Message message) {
@ -111,11 +107,12 @@ public class Message {
/**
* Converts this message into an instance of {@link envoy.data.Message}.
*
* @return a {@link envoy.data.Message} containing the same values as this
* message
* @return a {@link envoy.data.Message} containing the same values as this message
* @since Envoy Server Standalone v0.1-alpha
*/
public envoy.data.Message toCommon() { return prepareBuilder().build(); }
public envoy.data.Message toCommon() {
return prepareBuilder().build();
}
/**
* @return a message builder containing the state of this message
@ -128,13 +125,14 @@ public class Message {
.setReadDate(readDate)
.setStatus(status)
.setForwarded(forwarded);
if (attachment != null) builder.setAttachment(new Attachment(attachment, attachmentName, attachmentType));
if (attachment != null)
builder.setAttachment(new Attachment(attachment, attachmentName, attachmentType));
return builder;
}
/**
* Sets the message status to {@link MessageStatus#RECEIVED} and sets the
* current time stamp as the received date.
* Sets the message status to {@link MessageStatus#RECEIVED} and sets the current time stamp as
* the received date.
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -144,8 +142,8 @@ public class Message {
}
/**
* Sets the message status to {@link MessageStatus#READ} and sets the
* current time stamp as the read date.
* Sets the message status to {@link MessageStatus#READ} and sets the current time stamp as the
* read date.
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -207,8 +205,7 @@ public class Message {
public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; }
/**
* @return the date at which a {link envoy.data.Message} has been received by
* the server
* @return the date at which a {link envoy.data.Message} has been received by the server
* @since Envoy Server Standalone v0.2-beta
*/
public Instant getReceivedDate() { return receivedDate; }
@ -279,7 +276,9 @@ public class Message {
* @param attachmentType the attachmentType to set
* @since Envoy Server Standalone v0.1-beta
*/
public void setAttachmentType(AttachmentType attachmentType) { this.attachmentType = attachmentType; }
public void setAttachmentType(AttachmentType attachmentType) {
this.attachmentType = attachmentType;
}
/**
* @return the attachmentName
@ -291,7 +290,9 @@ public class Message {
* @param attachmentName the attachmentName to set
* @since Envoy Server v0.2-beta
*/
public void setAttachmentName(String attachmentName) { this.attachmentName = attachmentName; }
public void setAttachmentName(String attachmentName) {
this.attachmentName = attachmentName;
}
/**
* @return whether this message is a forwarded message

View File

@ -7,9 +7,10 @@ import java.util.logging.Level;
import javax.persistence.*;
import envoy.data.User.UserStatus;
import envoy.server.net.ConnectionManager;
import envoy.util.EnvoyLog;
import envoy.server.net.ConnectionManager;
/**
* Contains operations used for persistence.
*
@ -19,7 +20,8 @@ import envoy.util.EnvoyLog;
*/
public final class PersistenceManager {
private final EntityManager entityManager = Persistence.createEntityManagerFactory("envoy").createEntityManager();
private final EntityManager entityManager =
Persistence.createEntityManagerFactory("envoy").createEntityManager();
private final EntityTransaction transaction = entityManager.getTransaction();
private static final PersistenceManager persistenceManager = new PersistenceManager();
@ -35,7 +37,11 @@ public final class PersistenceManager {
.getOnlineUsers()
.stream()
.map(this::getUserByID)
.forEach(user -> { user.setStatus(UserStatus.OFFLINE); user.setLastSeen(Instant.now()); entityManager.merge(user); });
.forEach(user -> {
user.setStatus(UserStatus.OFFLINE);
user.setLastSeen(Instant.now());
entityManager.merge(user);
});
})));
}
@ -51,7 +57,9 @@ public final class PersistenceManager {
* @param contact the {@link Contact} to add to the database
* @since Envoy Server Standalone v0.1-alpha
*/
public void addContact(Contact contact) { persist(contact); }
public void addContact(Contact contact) {
persist(contact);
}
/**
* Adds a {@link Message} to the database.
@ -59,7 +67,9 @@ public final class PersistenceManager {
* @param message the {@link Message} to add to the database
* @since Envoy Server Standalone v0.1-alpha
*/
public void addMessage(Message message) { persist(message); }
public void addMessage(Message message) {
persist(message);
}
/**
* Adds a {@link ConfigItem} to the database.
@ -67,7 +77,9 @@ public final class PersistenceManager {
* @param configItem the {@link ConfigItem} to add to the database
* @since Envoy Server Standalone v0.1-alpha
*/
public void addConfigItem(ConfigItem configItem) { persist(configItem); }
public void addConfigItem(ConfigItem configItem) {
persist(configItem);
}
/**
* Updates a {@link Contact} in the database
@ -75,7 +87,9 @@ public final class PersistenceManager {
* @param contact the {@link Contact} to add to the database
* @since Envoy Server Standalone v0.1-alpha
*/
public void updateContact(Contact contact) { merge(contact); }
public void updateContact(Contact contact) {
merge(contact);
}
/**
* Updates a {@link Message} in the database.
@ -83,7 +97,9 @@ public final class PersistenceManager {
* @param message the message to update
* @since Envoy Server Standalone v0.1-alpha
*/
public void updateMessage(Message message) { merge(message); }
public void updateMessage(Message message) {
merge(message);
}
/**
* Updates a {@link ConfigItem} in the database.
@ -91,7 +107,9 @@ public final class PersistenceManager {
* @param configItem the configItem to update
* @since Envoy Server Standalone v0.1-alpha
*/
public void updateConfigItem(ConfigItem configItem) { merge(configItem); }
public void updateConfigItem(ConfigItem configItem) {
merge(configItem);
}
/**
* Deletes a {@link Contact} in the database.
@ -115,7 +133,9 @@ public final class PersistenceManager {
* @param message the {@link Message} to delete
* @since Envoy Server Standalone v0.1-alpha
*/
public void deleteMessage(Message message) { remove(message); }
public void deleteMessage(Message message) {
remove(message);
}
/**
* Searches for a {@link User} with a specific ID.
@ -124,7 +144,9 @@ public final class PersistenceManager {
* @return the user with the specified ID or {@code null} if none was found
* @since Envoy Server Standalone v0.1-alpha
*/
public User getUserByID(long id) { return entityManager.find(User.class, id); }
public User getUserByID(long id) {
return entityManager.find(User.class, id);
}
/**
* Searches for a {@link Group} with a specific ID.
@ -133,7 +155,9 @@ public final class PersistenceManager {
* @return the group with the specified ID or {@code null} if none was found
* @since Envoy Server Standalone v0.1-beta
*/
public Group getGroupByID(long id) { return entityManager.find(Group.class, id); }
public Group getGroupByID(long id) {
return entityManager.find(Group.class, id);
}
/**
* Searches for a {@link Contact} with a specific ID.
@ -142,7 +166,9 @@ public final class PersistenceManager {
* @return the contact with the specified ID or {@code null} if none was found
* @since Envoy Server Standalone v0.1-beta
*/
public Contact getContactByID(long id) { return entityManager.find(Contact.class, id); }
public Contact getContactByID(long id) {
return entityManager.find(Contact.class, id);
}
/**
* Searched for a {@link User} with a specific name.
@ -152,7 +178,8 @@ public final class PersistenceManager {
* @since Envoy Server Standalone v0.1-alpha
*/
public User getUserByName(String name) {
return (User) entityManager.createNamedQuery(User.findByName).setParameter("name", name).getSingleResult();
return (User) entityManager.createNamedQuery(User.findByName).setParameter("name", name)
.getSingleResult();
}
/**
@ -163,7 +190,8 @@ public final class PersistenceManager {
* @since Envoy Server Standalone v0.1-alpha
*/
public Group getGroupByName(String name) {
return (Group) entityManager.createNamedQuery(Group.findByName).setParameter("name", name).getSingleResult();
return (Group) entityManager.createNamedQuery(Group.findByName).setParameter("name", name)
.getSingleResult();
}
/**
@ -173,18 +201,21 @@ public final class PersistenceManager {
* @return the message with the specified ID or {@code null} if none is found
* @since Envoy Server Standalone v0.1-alpha
*/
public Message getMessageByID(long id) { return entityManager.find(Message.class, id); }
public Message getMessageByID(long id) {
return entityManager.find(Message.class, id);
}
/**
* @param key the name of this {@link ConfigItem}
* @return the {@link ConfigItem} with the given name
* @since Envoy Server Standalone v0.1-alpha
*/
public ConfigItem getConfigItemByID(String key) { return entityManager.find(ConfigItem.class, key); }
public ConfigItem getConfigItemByID(String key) {
return entityManager.find(ConfigItem.class, key);
}
/**
* Returns all messages received while being offline or the ones that have
* changed.
* Returns all messages received while being offline or the ones that have changed.
*
* @param user the user who wants to receive his unread messages
* @param lastSync the time stamp of the last synchronization
@ -192,17 +223,16 @@ public final class PersistenceManager {
* @since Envoy Server Standalone v0.2-beta
*/
public List<Message> getPendingMessages(User user, Instant lastSync) {
return entityManager.createNamedQuery(Message.getPending).setParameter("user", user).setParameter("lastSeen", lastSync).getResultList();
return entityManager.createNamedQuery(Message.getPending).setParameter("user", user)
.setParameter("lastSeen", lastSync).getResultList();
}
/**
* Returns all groupMessages received while being offline or the ones that have
* changed.
* Returns all groupMessages received while being offline or the ones that have changed.
*
* @param user the user who wants to receive his unread groupMessages
* @param lastSync the time stamp of the last synchronization
* @return all groupMessages that the client does not yet have (unread
* groupMessages)
* @return all groupMessages that the client does not yet have (unread groupMessages)
* @since Envoy Server Standalone v0.2-beta
*/
public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
@ -213,12 +243,11 @@ public final class PersistenceManager {
}
/**
* Searches for users matching a search phrase. Contacts of the attached user
* and the attached user is ignored.
* Searches for users matching a search phrase. Contacts of the attached user and the attached
* user is ignored.
*
* @param searchPhrase the search phrase
* @param userId the ID of the user in whose context the search is
* performed
* @param userId the ID of the user in whose context the search is performed
* @return a list of all users who matched the criteria
* @since Envoy Server Standalone v0.1-alpha
*/
@ -254,7 +283,10 @@ public final class PersistenceManager {
contact2.getContacts().add(contact1);
// Synchronize changes with the database
transaction(() -> { entityManager.merge(contact1); entityManager.merge(contact2); });
transaction(() -> {
entityManager.merge(contact1);
entityManager.merge(contact2);
});
}
/**
@ -282,7 +314,10 @@ public final class PersistenceManager {
contact2.getContacts().remove(contact1);
// Synchronize changes with the database
transaction(() -> { entityManager.merge(contact1); entityManager.merge(contact2); });
transaction(() -> {
entityManager.merge(contact1);
entityManager.merge(contact2);
});
}
/**
@ -291,21 +326,27 @@ public final class PersistenceManager {
* @since Envoy Server Standalone v0.1-alpha
*/
public List<User> getContacts(User user) {
return entityManager.createNamedQuery(User.findContacts).setParameter("user", user).getResultList();
return entityManager.createNamedQuery(User.findContacts).setParameter("user", user)
.getResultList();
}
private void persist(Object obj) { transaction(() -> entityManager.persist(obj)); }
private void persist(Object obj) {
transaction(() -> entityManager.persist(obj));
}
private void merge(Object obj) { transaction(() -> entityManager.merge(obj)); }
private void merge(Object obj) {
transaction(() -> entityManager.merge(obj));
}
private void remove(Object obj) { transaction(() -> entityManager.remove(obj)); }
private void remove(Object obj) {
transaction(() -> entityManager.remove(obj));
}
/**
* Performs a transaction with the given Runnable, that should somewhere call
* {@link EntityManager}.
*
* @param entityManagerRelatedAction the action that changes something in the
* database
* @param entityManagerRelatedAction the action that changes something in the database
* @since Envoy Server v0.3-beta
*/
private void transaction(Runnable entityManagerRelatedAction) {
@ -328,8 +369,10 @@ public final class PersistenceManager {
if (transaction.isActive()) {
transaction.rollback();
EnvoyLog.getLogger(PersistenceManager.class)
.log(Level.SEVERE, "Could not perform transaction, hence discarding it. It's likely that a serious issue exists.");
} else throw e2;
.log(Level.SEVERE,
"Could not perform transaction, hence discarding it. It's likely that a serious issue exists.");
} else
throw e2;
}
}
}

View File

@ -16,7 +16,9 @@ public final class ServerConfig extends Config {
* @return the singleton instance of the server config
* @since Envoy Client v0.1-beta
*/
public static ServerConfig getInstance() { return config == null ? config = new ServerConfig() : config; }
public static ServerConfig getInstance() {
return config == null ? config = new ServerConfig() : config;
}
private ServerConfig() {
super(".envoy-server");
@ -45,13 +47,17 @@ public final class ServerConfig extends Config {
* @return {@code true} if issue reporting is enabled
* @since Envoy Client v0.3-alpha
*/
public Boolean isIssueReportingEnabled() { return (Boolean) items.get("enableIssueReporting").get(); }
public Boolean isIssueReportingEnabled() {
return (Boolean) items.get("enableIssueReporting").get();
}
/**
* @return {@code true} if attachment support has been enabled
* @since Envoy Client v0.3-alpha
*/
public Boolean isAttachmentSupportEnabled() { return (Boolean) items.get("enableAttachments").get(); }
public Boolean isAttachmentSupportEnabled() {
return (Boolean) items.get("enableAttachments").get();
}
/**
* @return {@code true} if group support has been enabled
@ -85,9 +91,8 @@ public final class ServerConfig extends Config {
/**
* @return the authorization token used to authenticate to
* {@link ServerConfig#getIssueReportingURL()}. If null,
* authorization is expected to occur via a query_param or via a basic
* user-password-combination
* {@link ServerConfig#getIssueReportingURL()}. If null, authorization is expected to
* occur via a query_param or via a basic user-password-combination
* @since Envoy Server v0.2-beta
*/
public String getIssueAuthToken() { return (String) items.get("issueAuthToken").get(); }
@ -96,5 +101,7 @@ public final class ServerConfig extends Config {
* @return the amount of days after which user authentication tokens expire
* @since Envoy Server v0.2-beta
*/
public Integer getAuthTokenExpiration() { return (Integer) items.get("authTokenExpiration").get(); }
public Integer getAuthTokenExpiration() {
return (Integer) items.get("authTokenExpiration").get();
}
}

View File

@ -9,9 +9,9 @@ import javax.persistence.*;
import envoy.data.User.UserStatus;
/**
* This class enables the storage of user specific data inside a database using
* Hibernate. Its objects will be referred to as database users as opposed to
* the common user objects present on both the client and the server.
* This class enables the storage of user specific data inside a database using Hibernate. Its
* objects will be referred to as database users as opposed to the common user objects present on
* both the client and the server.
*
* @author Kai S. K. Engelbart
* @author Maximilian K&auml;fer
@ -19,18 +19,9 @@ import envoy.data.User.UserStatus;
*/
@Entity
@NamedQueries({
@NamedQuery(
name = User.findByName,
query = "SELECT u FROM User u WHERE u.name = :name"
),
@NamedQuery(
name = User.findContacts,
query = "SELECT u.contacts FROM User u WHERE u = :user"
),
@NamedQuery(
name = User.searchByName,
query = "SELECT u FROM User u WHERE (lower(u.name) LIKE lower(:searchPhrase) AND u <> :context AND :context NOT MEMBER OF u.contacts)"
)
@NamedQuery(name = User.findByName, query = "SELECT u FROM User u WHERE u.name = :name"),
@NamedQuery(name = User.findContacts, query = "SELECT u.contacts FROM User u WHERE u = :user"),
@NamedQuery(name = User.searchByName, query = "SELECT u FROM User u WHERE (lower(u.name) LIKE lower(:searchPhrase) AND u <> :context AND :context NOT MEMBER OF u.contacts)")
})
public final class User extends Contact {
@ -42,8 +33,7 @@ public final class User extends Contact {
public static final String findByName = "User.findByName";
/**
* Named query retrieving the contacts of a given user (parameter
* {@code :user}).
* Named query retrieving the contacts of a given user (parameter {@code :user}).
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -51,8 +41,8 @@ public final class User extends Contact {
/**
* Named query searching for users with a name like a search phrase (parameter
* {@code :searchPhrase}) that are not in the contact list of a given user
* (parameter {@code :context}).
* {@code :searchPhrase}) that are not in the contact list of a given user (parameter
* {@code :context}).
*
* @since Envoy Server Standalone v0.1-beta
*/
@ -77,11 +67,14 @@ public final class User extends Contact {
@Override
public envoy.data.User toCommon() {
return new envoy.data.User(id, name, status, contacts.parallelStream().map(Contact::toFlatCommon).collect(Collectors.toSet()));
return new envoy.data.User(id, name, status,
contacts.parallelStream().map(Contact::toFlatCommon).collect(Collectors.toSet()));
}
@Override
protected envoy.data.User toFlatCommon() { return new envoy.data.User(id, name, status, Set.of()); }
protected envoy.data.User toFlatCommon() {
return new envoy.data.User(id, name, status, Set.of());
}
/**
* @return the password hash
@ -114,11 +107,12 @@ public final class User extends Contact {
public Instant getAuthTokenExpiration() { return authTokenExpiration; }
/**
* @param authTokenExpiration the authentication token expiration timestamp to
* set
* @param authTokenExpiration the authentication token expiration timestamp to set
* @since Envoy Server v0.2-beta
*/
public void setAuthTokenExpiration(Instant authTokenExpiration) { this.authTokenExpiration = authTokenExpiration; }
public void setAuthTokenExpiration(Instant authTokenExpiration) {
this.authTokenExpiration = authTokenExpiration;
}
/**
* @return the last date the user has been online
@ -154,5 +148,7 @@ public final class User extends Contact {
* @param latestContactDeletion the latestContactDeletion to set
* @since Envoy Server v0.3-beta
*/
public void setLatestContactDeletion(Instant latestContactDeletion) { this.latestContactDeletion = latestContactDeletion; }
public void setLatestContactDeletion(Instant latestContactDeletion) {
this.latestContactDeletion = latestContactDeletion;
}
}

View File

@ -7,6 +7,7 @@ import java.util.stream.Collectors;
import com.jenkov.nioserver.ISocketIdListener;
import envoy.data.User.UserStatus;
import envoy.server.data.*;
import envoy.server.processors.UserStatusChangeProcessor;
@ -17,8 +18,8 @@ import envoy.server.processors.UserStatusChangeProcessor;
public final class ConnectionManager implements ISocketIdListener {
/**
* Contains all socket IDs that have not yet performed a handshake / acquired
* their corresponding user ID.
* Contains all socket IDs that have not yet performed a handshake / acquired their
* corresponding user ID.
*
* @since Envoy Server Standalone v0.1-alpha
*/
@ -46,7 +47,8 @@ public final class ConnectionManager implements ISocketIdListener {
if (!pendingSockets.remove(socketID)) {
// Notify contacts of this users offline-going
final envoy.server.data.User user = PersistenceManager.getInstance().getUserByID(getUserIDBySocketID(socketID));
final envoy.server.data.User user =
PersistenceManager.getInstance().getUserByID(getUserIDBySocketID(socketID));
user.setLastSeen(Instant.now());
UserStatusChangeProcessor.updateUserStatus(user, UserStatus.OFFLINE);
@ -56,7 +58,9 @@ public final class ConnectionManager implements ISocketIdListener {
}
@Override
public void socketRegistered(long socketID) { pendingSockets.add(socketID); }
public void socketRegistered(long socketID) {
pendingSockets.add(socketID);
}
/**
* Associates a socket ID with a user ID.
@ -75,7 +79,9 @@ public final class ConnectionManager implements ISocketIdListener {
* @return the ID of the socket
* @since Envoy Server Standalone v0.1-alpha
*/
public long getSocketID(long userID) { return sockets.get(userID); }
public long getSocketID(long userID) {
return sockets.get(userID);
}
/**
* @param socketID the id of the socket whose User is needed
@ -83,7 +89,8 @@ public final class ConnectionManager implements ISocketIdListener {
* @since Envoy Server Standalone v0.1-alpha
*/
public long getUserIDBySocketID(long socketID) {
return sockets.entrySet().stream().filter(entry -> entry.getValue().equals(socketID)).findFirst().get().getKey();
return sockets.entrySet().stream().filter(entry -> entry.getValue().equals(socketID))
.findFirst().get().getKey();
}
/**
@ -91,7 +98,9 @@ public final class ConnectionManager implements ISocketIdListener {
* @return {@code true} if the user is online
* @since Envoy Server Standalone v0.1-alpha
*/
public boolean isOnline(long userID) { return sockets.containsKey(userID); }
public boolean isOnline(long userID) {
return sockets.containsKey(userID);
}
/**
* @return the userIDs of all users who are currently online
@ -105,6 +114,7 @@ public final class ConnectionManager implements ISocketIdListener {
* @since Envoy Server Standalone v0.1-beta
*/
public Set<Long> getOnlineUsersOfGroup(Group group) {
return group.getContacts().stream().map(Contact::getID).filter(this::isOnline).collect(Collectors.toSet());
return group.getContacts().stream().map(Contact::getID).filter(this::isOnline)
.collect(Collectors.toSet());
}
}

View File

@ -7,9 +7,10 @@ import java.util.logging.*;
import com.jenkov.nioserver.*;
import envoy.server.processors.ObjectProcessor;
import envoy.util.EnvoyLog;
import envoy.server.processors.ObjectProcessor;
/**
* Handles incoming objects.
*
@ -28,12 +29,16 @@ public final class ObjectMessageProcessor implements IMessageProcessor {
* @param processors the {@link ObjectProcessor} to set
* @since Envoy Server Standalone v0.1-alpha
*/
public ObjectMessageProcessor(Set<ObjectProcessor<?>> processors) { this.processors = processors; }
public ObjectMessageProcessor(Set<ObjectProcessor<?>> processors) {
this.processors = processors;
}
@SuppressWarnings("unchecked")
@Override
public void process(Message message, WriteProxy writeProxy) {
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(message.sharedArray, message.offset + 4, message.length - 4))) {
try (ObjectInputStream in =
new ObjectInputStream(new ByteArrayInputStream(message.sharedArray, message.offset + 4,
message.length - 4))) {
Object obj = in.readObject();
if (obj == null) {
logger.warning("Received a null object");
@ -45,7 +50,8 @@ public final class ObjectMessageProcessor implements IMessageProcessor {
// Get processor and input class and process object
for (@SuppressWarnings("rawtypes")
ObjectProcessor p : processors) {
Class<?> c = (Class<?>) ((ParameterizedType) p.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
Class<?> c = (Class<?>) ((ParameterizedType) p.getClass().getGenericInterfaces()[0])
.getActualTypeArguments()[0];
if (c.equals(obj.getClass()))
try {
p.process(c.cast(obj), message.socketId, new ObjectWriteProxy(writeProxy));

View File

@ -16,9 +16,9 @@ import envoy.util.SerializationUtils;
*/
public final class ObjectMessageReader implements IMessageReader {
private List<Message> completeMessages = new ArrayList<>();
private Message nextMessage;
private MessageBuffer messageBuffer;
private final List<Message> completeMessages = new ArrayList<>();
private Message nextMessage;
private MessageBuffer messageBuffer;
@Override
public List<Message> getMessages() { return completeMessages; }
@ -43,7 +43,8 @@ public final class ObjectMessageReader implements IMessageReader {
buffer.clear();
// Get message length
if (nextMessage.length < 4) return;
if (nextMessage.length < 4)
return;
int length = SerializationUtils.bytesToInt(nextMessage.sharedArray, nextMessage.offset) + 4;
do {
@ -58,7 +59,8 @@ public final class ObjectMessageReader implements IMessageReader {
}
// Get message length
if (nextMessage.length < 4) return;
if (nextMessage.length < 4)
return;
length = SerializationUtils.bytesToInt(nextMessage.sharedArray, nextMessage.offset) + 4;
} while (nextMessage.length >= length);

View File

@ -7,9 +7,10 @@ import java.util.stream.Stream;
import com.jenkov.nioserver.*;
import envoy.server.data.Contact;
import envoy.util.*;
import envoy.server.data.Contact;
/**
* This class defines methods to send an object to a client.
*
@ -21,7 +22,8 @@ public final class ObjectWriteProxy {
private final WriteProxy writeProxy;
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(ObjectWriteProxy.class);
private static final Logger logger =
EnvoyLog.getLogger(ObjectWriteProxy.class);
/**
* Creates an instance of {@link ObjectWriteProxy}.
@ -29,13 +31,14 @@ public final class ObjectWriteProxy {
* @param writeProxy the {@link WriteProxy} to write objects to another client
* @since Envoy Server Standalone v0.1-alpha
*/
public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; }
public ObjectWriteProxy(WriteProxy writeProxy) {
this.writeProxy = writeProxy;
}
/**
* @param recipientSocketID the socket id of the recipient
* @param obj the object to return to the client
* @throws RuntimeException if the serialization of the object failed (this is
* highly unlikely)
* @throws RuntimeException if the serialization of the object failed (this is highly unlikely)
* @since Envoy Server Standalone v0.1-alpha
*/
public void write(long recipientSocketID, Object obj) {
@ -67,7 +70,9 @@ public final class ObjectWriteProxy {
* @param message the object to send
* @since Envoy Server Standalone v0.1-beta
*/
public void writeToOnlineContacts(Set<? extends Contact> contacts, Object message) { writeToOnlineContacts(contacts.stream(), message); }
public void writeToOnlineContacts(Set<? extends Contact> contacts, Object message) {
writeToOnlineContacts(contacts.stream(), message);
}
/**
* Sends an object to all contacts in a set that are online.
@ -77,6 +82,7 @@ public final class ObjectWriteProxy {
* @since Envoy Server Standalone v0.1-beta
*/
public void writeToOnlineContacts(Stream<? extends Contact> contacts, Object message) {
contacts.map(Contact::getID).filter(connectionManager::isOnline).map(connectionManager::getSocketID).forEach(id -> write(id, message));
contacts.map(Contact::getID).filter(connectionManager::isOnline)
.map(connectionManager::getSocketID).forEach(id -> write(id, message));
}
}

View File

@ -5,6 +5,7 @@ import static envoy.server.Startup.config;
import java.util.HashSet;
import envoy.event.*;
import envoy.server.data.PersistenceManager;
import envoy.server.net.*;
@ -32,7 +33,9 @@ public final class GroupCreationProcessor implements ObjectProcessor<GroupCreati
.stream()
.map(persistenceManager::getUserByID)
.forEach(member -> persistenceManager.addContactBidirectional(member, group));
persistenceManager.addContactBidirectional(persistenceManager.getUserByID(connectionManager.getUserIDBySocketID(socketID)), group);
writeProxy.writeToOnlineContacts(group.getContacts(), new GroupCreationResult(group.toCommon()));
persistenceManager.addContactBidirectional(
persistenceManager.getUserByID(connectionManager.getUserIDBySocketID(socketID)), group);
writeProxy.writeToOnlineContacts(group.getContacts(),
new GroupCreationResult(group.toCommon()));
}
}

View File

@ -11,9 +11,10 @@ import javax.persistence.EntityExistsException;
import envoy.data.GroupMessage;
import envoy.event.*;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.net.*;
import envoy.util.EnvoyLog;
/**
* @author Maximilian K&auml;fer
@ -23,14 +24,16 @@ public final class GroupMessageProcessor implements ObjectProcessor<GroupMessage
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(GroupCreationProcessor.class);
private static final Logger logger =
EnvoyLog.getLogger(GroupCreationProcessor.class);
@Override
public void process(GroupMessage groupMessage, long socketID, ObjectWriteProxy writeProxy) {
groupMessage.nextStatus();
// Update statuses to SENT / RECEIVED depending on online status
groupMessage.getMemberStatuses().replaceAll((memberID, status) -> connectionManager.isOnline(memberID) ? RECEIVED : SENT);
groupMessage.getMemberStatuses().replaceAll(
(memberID, status) -> connectionManager.isOnline(memberID) ? RECEIVED : SENT);
// Set status for sender to READ
groupMessage.getMemberStatuses().replace(groupMessage.getSenderID(), READ);
@ -44,7 +47,8 @@ public final class GroupMessageProcessor implements ObjectProcessor<GroupMessage
}
// message attachment will be automatically removed if disabled in config
final var groupMessageServer = new envoy.server.data.GroupMessage(groupMessage, Instant.now());
final var groupMessageServer =
new envoy.server.data.GroupMessage(groupMessage, Instant.now());
// Telling the server to reload the message without the attachment and telling
// the client not to send anymore attachments
if (!config.isAttachmentSupportEnabled() && groupMessage.hasAttachment()) {
@ -57,11 +61,11 @@ public final class GroupMessageProcessor implements ObjectProcessor<GroupMessage
final var groupMessageCopy = groupMessage;
// Deliver the message to the recipients that are online
writeProxy.writeToOnlineContacts(
persistenceManager.getGroupByID(groupMessageCopy.getRecipientID())
.getContacts()
.stream()
.filter(c -> c.getID() != groupMessageCopy.getSenderID()),
groupMessageCopy);
persistenceManager.getGroupByID(groupMessageCopy.getRecipientID())
.getContacts()
.stream()
.filter(c -> c.getID() != groupMessageCopy.getSenderID()),
groupMessageCopy);
try {
PersistenceManager.getInstance().addMessage(groupMessageServer);

View File

@ -8,22 +8,26 @@ import java.util.logging.*;
import envoy.data.Message.MessageStatus;
import envoy.event.*;
import envoy.util.EnvoyLog;
import envoy.server.data.*;
import envoy.server.net.*;
import envoy.util.EnvoyLog;
/**
* @author Maximilian K&auml;fer
* @since Envoy Server Standalone v0.1-beta
*/
public final class GroupMessageStatusChangeProcessor implements ObjectProcessor<GroupMessageStatusChange> {
public final class GroupMessageStatusChangeProcessor
implements ObjectProcessor<GroupMessageStatusChange> {
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(MessageStatusChangeProcessor.class);
private static final Logger logger =
EnvoyLog.getLogger(MessageStatusChangeProcessor.class);
@Override
public void process(GroupMessageStatusChange statusChange, long socketID, ObjectWriteProxy writeProxy) {
public void process(GroupMessageStatusChange statusChange, long socketID,
ObjectWriteProxy writeProxy) {
GroupMessage gmsg = (GroupMessage) persistenceManager.getMessageByID(statusChange.getID());
// Any other status than READ is not supposed to be sent to the server
@ -51,7 +55,7 @@ public final class GroupMessageStatusChangeProcessor implements ObjectProcessor<
// Notify online members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
persistenceManager.updateMessage(gmsg);
}

View File

@ -4,9 +4,10 @@ import java.time.Instant;
import java.util.logging.Level;
import envoy.event.GroupResize;
import envoy.util.EnvoyLog;
import envoy.server.data.*;
import envoy.server.net.ObjectWriteProxy;
import envoy.util.EnvoyLog;
/**
* @author Maximilian K&auml;fer
@ -35,16 +36,19 @@ public final class GroupResizeProcessor implements ObjectProcessor<GroupResize>
// The group has no more members and hence will be deleted
if (group.getContacts().isEmpty()) {
EnvoyLog.getLogger(GroupResizeProcessor.class).log(Level.INFO, "Deleting now empty group " + group.getName());
EnvoyLog.getLogger(GroupResizeProcessor.class).log(Level.INFO,
"Deleting now empty group " + group.getName());
persistenceManager.deleteContact(group);
} else {
// Informing the other members
writeProxy.writeToOnlineContacts(group.getContacts(), groupResize);
group.getContacts().forEach(c -> ((User) c).setLatestContactDeletion(Instant.now()));
group.getContacts()
.forEach(c -> ((User) c).setLatestContactDeletion(Instant.now()));
}
group.getContacts().remove(persistenceManager.getUserByID(groupResize.get().getID()));
group.getContacts()
.remove(persistenceManager.getUserByID(groupResize.get().getID()));
return;
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import envoy.data.IDGenerator;
import envoy.event.IDGeneratorRequest;
import envoy.server.data.*;
import envoy.server.net.ObjectWriteProxy;
@ -17,7 +18,8 @@ public final class IDGeneratorRequestProcessor implements ObjectProcessor<IDGene
private static final long ID_RANGE = 200;
@Override
public void process(IDGeneratorRequest input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(IDGeneratorRequest input, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
writeProxy.write(socketID, createIDGenerator());
}
@ -25,7 +27,9 @@ public final class IDGeneratorRequestProcessor implements ObjectProcessor<IDGene
* @return a new IDGenerator
* @since Envoy Server Standalone v0.1-beta
*/
public static IDGenerator createIDGenerator() { return createIDGenerator(ID_RANGE); }
public static IDGenerator createIDGenerator() {
return createIDGenerator(ID_RANGE);
}
/**
* @param range of IDs used by the new IDGenerator
@ -33,7 +37,8 @@ public final class IDGeneratorRequestProcessor implements ObjectProcessor<IDGene
* @since Envoy Server Standalone v0.1-beta
*/
public static IDGenerator createIDGenerator(long range) {
ConfigItem currentID = PersistenceManager.getInstance().getConfigItemByID("currentMessageId");
ConfigItem currentID =
PersistenceManager.getInstance().getConfigItemByID("currentMessageId");
IDGenerator generator = new IDGenerator(Integer.parseInt(currentID.getValue()), range);
currentID.setValue(String.valueOf(Integer.parseInt(currentID.getValue()) + range));
PersistenceManager.getInstance().updateConfigItem(currentID);

View File

@ -3,6 +3,7 @@ package envoy.server.processors;
import java.io.IOException;
import envoy.event.IsTyping;
import envoy.server.data.*;
import envoy.server.net.*;
@ -18,11 +19,14 @@ public final class IsTypingProcessor implements ObjectProcessor<IsTyping> {
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
@Override
public void process(IsTyping event, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(IsTyping event, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
final var contact = persistenceManager.getContactByID(event.get());
if (contact instanceof User) {
final var destinationID = event.getDestinationID();
if (connectionManager.isOnline(destinationID)) writeProxy.write(connectionManager.getSocketID(destinationID), event);
} else writeProxy.writeToOnlineContacts(contact.getContacts(), event);
if (connectionManager.isOnline(destinationID))
writeProxy.write(connectionManager.getSocketID(destinationID), event);
} else
writeProxy.writeToOnlineContacts(contact.getContacts(), event);
}
}

View File

@ -7,12 +7,13 @@ import java.net.*;
import java.util.logging.*;
import envoy.event.IssueProposal;
import envoy.server.net.ObjectWriteProxy;
import envoy.util.EnvoyLog;
import envoy.server.net.ObjectWriteProxy;
/**
* This processor handles incoming {@link IssueProposal}s and automatically
* creates a new issue on the gitea site, if not disabled by its administrator.
* This processor handles incoming {@link IssueProposal}s and automatically creates a new issue on
* the gitea site, if not disabled by its administrator.
*
* @author Leon Hofmeister
* @since Envoy Server v0.2-beta
@ -22,9 +23,11 @@ public final class IssueProposalProcessor implements ObjectProcessor<IssuePropos
private static final Logger logger = EnvoyLog.getLogger(IssueProposalProcessor.class);
@Override
public void process(IssueProposal issueProposal, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(IssueProposal issueProposal, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
// Do nothing if manually disabled
if (!config.isIssueReportingEnabled()) return;
if (!config.isIssueReportingEnabled())
return;
try {
final var url = new URL(config.getIssueReportingURL());
final var connection = (HttpURLConnection) url.openConnection();
@ -41,18 +44,22 @@ public final class IssueProposalProcessor implements ObjectProcessor<IssuePropos
connection.setDoOutput(true);
final var json = String.format("{\"title\":\"%s\",\"body\":\"%s\",\"labels\":[%s, %s]}",
issueProposal.get(),
issueProposal.getDescription(),
config.getUserMadeLabel(),
issueProposal.isBug() ? config.getBugLabel() : config.getFeatureLabel());
issueProposal.get(),
issueProposal.getDescription(),
config.getUserMadeLabel(),
issueProposal.isBug() ? config.getBugLabel() : config.getFeatureLabel());
try (final var os = connection.getOutputStream()) {
final byte[] input = json.getBytes("utf-8");
os.write(input, 0, input.length);
}
final var status = connection.getResponseCode();
if (status == 201) logger.log(Level.INFO, "Successfully created an issue");
else logger.log(Level.WARNING,
String.format("Tried creating an issue for %s but received status code %d - Request params:%s", url, status, json));
if (status == 201)
logger.log(Level.INFO, "Successfully created an issue");
else
logger.log(Level.WARNING,
String.format(
"Tried creating an issue for %s but received status code %d - Request params:%s",
url, status, json));
} catch (final IOException e) {
logger.log(Level.WARNING, "An error occurred while creating an issue: ", e);
}

View File

@ -14,10 +14,11 @@ import javax.persistence.NoResultException;
import envoy.data.LoginCredentials;
import envoy.event.*;
import envoy.event.contact.ContactsChangedSinceLastLogin;
import envoy.util.*;
import envoy.server.data.*;
import envoy.server.net.*;
import envoy.server.util.*;
import envoy.util.*;
/**
* This {@link ObjectProcessor} handles {@link LoginCredentials}.
@ -47,27 +48,29 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Acquire a user object (or reject the handshake if that's impossible)
User user = null;
if (!credentials.isRegistration()) try {
user = persistenceManager.getUserByName(credentials.getIdentifier());
if (!credentials.isRegistration())
try {
user = persistenceManager.getUserByName(credentials.getIdentifier());
// Check if the user is already online
if (connectionManager.isOnline(user.getID())) {
logger.warning(user + " is already online!");
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
return;
}
// Authenticate with password or token
if (credentials.usesToken()) {
// Check the token
if (user.getAuthToken() == null || user.getAuthTokenExpiration().isBefore(Instant.now())
|| !user.getAuthToken().equals(credentials.getPassword())) {
logger.info(user + " tried to use an invalid token.");
writeProxy.write(socketID, new HandshakeRejection(INVALID_TOKEN));
// Check if the user is already online
if (connectionManager.isOnline(user.getID())) {
logger.warning(user + " is already online!");
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
return;
}
} else
// Authenticate with password or token
if (credentials.usesToken()) {
// Check the token
if (user.getAuthToken() == null
|| user.getAuthTokenExpiration().isBefore(Instant.now())
|| !user.getAuthToken().equals(credentials.getPassword())) {
logger.info(user + " tried to use an invalid token.");
writeProxy.write(socketID, new HandshakeRejection(INVALID_TOKEN));
return;
}
} else
// Check the password hash
if (!PasswordUtil.validate(credentials.getPassword(), user.getPasswordHash())) {
@ -75,11 +78,11 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
return;
}
} catch (final NoResultException e) {
logger.info("The requested user does not exist.");
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
return;
}
} catch (final NoResultException e) {
logger.info("The requested user does not exist.");
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
return;
}
else {
// Validate user name
@ -131,12 +134,14 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
token = AuthTokenGenerator.nextToken();
user.setAuthToken(token);
}
user.setAuthTokenExpiration(Instant.now().plus(ServerConfig.getInstance().getAuthTokenExpiration().longValue(), ChronoUnit.DAYS));
user.setAuthTokenExpiration(Instant.now().plus(
ServerConfig.getInstance().getAuthTokenExpiration().longValue(), ChronoUnit.DAYS));
persistenceManager.updateContact(user);
writeProxy.write(socketID, new NewAuthToken(token));
}
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
final var pendingMessages =
PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
pendingMessages.removeIf(GroupMessage.class::isInstance);
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");
@ -156,19 +161,24 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Notify the sender about the delivery
if (connectionManager.isOnline(msg.getSender().getID())) {
msgCommon.nextStatus();
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()), new MessageStatusChange(msgCommon));
writeProxy.write(connectionManager.getSocketID(msg.getSender().getID()),
new MessageStatusChange(msgCommon));
}
} else writeProxy.write(socketID, new MessageStatusChange(msgCommon));
} else
writeProxy.write(socketID, new MessageStatusChange(msgCommon));
}
final List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance().getPendingGroupMessages(user, credentials.getLastSync());
logger.fine("Sending " + pendingGroupMessages.size() + " pending group messages to " + user + "...");
final List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance()
.getPendingGroupMessages(user, credentials.getLastSync());
logger.fine("Sending " + pendingGroupMessages.size() + " pending group messages to " + user
+ "...");
for (final var gmsg : pendingGroupMessages) {
final var gmsgCommon = gmsg.toCommon();
// Deliver the message to the user if he hasn't received it yet
if (gmsg.getCreationDate().isAfter(credentials.getLastSync()) || gmsg.getMemberMessageStatus().get(user.getID()) == SENT) {
if (gmsg.getCreationDate().isAfter(credentials.getLastSync())
|| gmsg.getMemberMessageStatus().get(user.getID()) == SENT) {
if (gmsg.getMemberMessageStatus().replace(user.getID(), RECEIVED) != RECEIVED) {
gmsg.setLastStatusChangeDate(Instant.now());
@ -177,14 +187,15 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Notify all online group members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, Instant.now(), connectionManager.getUserIDBySocketID(socketID)));
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, Instant.now(),
connectionManager.getUserIDBySocketID(socketID)));
if (Collections.min(gmsg.getMemberMessageStatus().values()) == RECEIVED) {
gmsg.received();
// Notify online members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
PersistenceManager.getInstance().updateMessage(gmsg);
@ -195,20 +206,25 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
} else {
// Sending group message status changes
if (gmsg.getStatus() == SENT && gmsg.getLastStatusChangeDate().isAfter(gmsg.getCreationDate())
|| gmsg.getStatus() == RECEIVED && gmsg.getLastStatusChangeDate().isAfter(gmsg.getReceivedDate()))
if (gmsg.getStatus() == SENT
&& gmsg.getLastStatusChangeDate().isAfter(gmsg.getCreationDate())
|| gmsg.getStatus() == RECEIVED
&& gmsg.getLastStatusChangeDate().isAfter(gmsg.getReceivedDate()))
gmsg.getMemberMessageStatus()
.forEach((memberID, memberStatus) -> writeProxy.write(socketID,
new GroupMessageStatusChange(gmsg.getID(), memberStatus, gmsg.getLastStatusChangeDate(), memberID)));
new GroupMessageStatusChange(gmsg.getID(), memberStatus,
gmsg.getLastStatusChangeDate(), memberID)));
// Deliver just a status change instead of the whole message
if (gmsg.getStatus() == RECEIVED && user.getLastSeen().isBefore(gmsg.getReceivedDate())
|| gmsg.getStatus() == READ && user.getLastSeen().isBefore(gmsg.getReadDate()))
if (gmsg.getStatus() == RECEIVED
&& user.getLastSeen().isBefore(gmsg.getReceivedDate())
|| gmsg.getStatus() == READ && user.getLastSeen().isBefore(gmsg.getReadDate()))
writeProxy.write(socketID, new MessageStatusChange(gmsgCommon));
}
}
// Notify the user if a contact deletion has happened since he last logged in
if (user.getLatestContactDeletion().isAfter(user.getLastSeen())) writeProxy.write(socketID, new ContactsChangedSinceLastLogin());
if (user.getLatestContactDeletion().isAfter(user.getLastSeen()))
writeProxy.write(socketID, new ContactsChangedSinceLastLogin());
// Complete the handshake
writeProxy.write(socketID, user.toCommon());

View File

@ -8,9 +8,10 @@ import javax.persistence.EntityExistsException;
import envoy.data.Message;
import envoy.event.*;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.net.*;
import envoy.util.EnvoyLog;
/**
* This {@link ObjectProcessor} handles incoming {@link Message}s.
@ -23,7 +24,8 @@ public final class MessageProcessor implements ObjectProcessor<Message> {
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(MessageProcessor.class);
private static final Logger logger =
EnvoyLog.getLogger(MessageProcessor.class);
@Override
public void process(Message message, long socketID, ObjectWriteProxy writeProxy) {

View File

@ -5,9 +5,10 @@ import java.util.logging.*;
import envoy.data.Message.MessageStatus;
import envoy.event.MessageStatusChange;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.net.*;
import envoy.util.EnvoyLog;
/**
* @author Leon Hofmeister
@ -17,10 +18,12 @@ public final class MessageStatusChangeProcessor implements ObjectProcessor<Messa
private final ConnectionManager connectionManager = ConnectionManager.getInstance();
private final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private final Logger logger = EnvoyLog.getLogger(MessageStatusChangeProcessor.class);
private final Logger logger =
EnvoyLog.getLogger(MessageStatusChangeProcessor.class);
@Override
public void process(MessageStatusChange statusChange, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(MessageStatusChange statusChange, long socketID,
ObjectWriteProxy writeProxy) throws IOException {
// Any other status than READ is not supposed to be sent to the server
if (statusChange.get() != MessageStatus.READ) {
@ -34,6 +37,7 @@ public final class MessageStatusChangeProcessor implements ObjectProcessor<Messa
// Notifies the sender of the message about the status-update to READ
final long senderID = msg.getSender().getID();
if (connectionManager.isOnline(senderID)) writeProxy.write(connectionManager.getSocketID(senderID), statusChange);
if (connectionManager.isOnline(senderID))
writeProxy.write(connectionManager.getSocketID(senderID), statusChange);
}
}

View File

@ -3,6 +3,7 @@ package envoy.server.processors;
import java.io.IOException;
import envoy.event.NameChange;
import envoy.server.data.*;
import envoy.server.net.ObjectWriteProxy;
@ -15,7 +16,8 @@ public final class NameChangeProcessor implements ObjectProcessor<NameChange> {
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
@Override
public void process(NameChange nameChange, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(NameChange nameChange, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
Contact toUpdate = persistenceManager.getContactByID(nameChange.getID());
toUpdate.setName(nameChange.get());
persistenceManager.updateContact(toUpdate);

View File

@ -5,8 +5,7 @@ import java.io.IOException;
import envoy.server.net.ObjectWriteProxy;
/**
* This interface defines methods for processing objects of a specific
* type incoming from a client.
* This interface defines methods for processing objects of a specific type incoming from a client.
*
* @author Kai S. K. Engelbart
* @param <T> type of the request object

View File

@ -4,27 +4,34 @@ import java.io.IOException;
import java.util.logging.Level;
import envoy.event.*;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.net.ObjectWriteProxy;
import envoy.server.util.PasswordUtil;
import envoy.util.EnvoyLog;
/**
* @author Leon Hofmeister
* @since Envoy Server v0.2-beta
*/
public final class PasswordChangeRequestProcessor implements ObjectProcessor<PasswordChangeRequest> {
public final class PasswordChangeRequestProcessor
implements ObjectProcessor<PasswordChangeRequest> {
@Override
public void process(PasswordChangeRequest event, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(PasswordChangeRequest event, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
final var persistenceManager = PersistenceManager.getInstance();
final var user = persistenceManager.getUserByID(event.getID());
final var logger = EnvoyLog.getLogger(PasswordChangeRequestProcessor.class);
final var correctAuthentication = PasswordUtil.validate(event.getOldPassword(), user.getPasswordHash());
final var logger =
EnvoyLog.getLogger(PasswordChangeRequestProcessor.class);
final var correctAuthentication =
PasswordUtil.validate(event.getOldPassword(), user.getPasswordHash());
if (correctAuthentication) {
user.setPasswordHash(PasswordUtil.hash(event.get()));
logger.log(Level.INFO, user + " changed his password");
} else logger.log(Level.INFO, user + " tried changing his password but provided insufficient authentication");
} else
logger.log(Level.INFO,
user + " tried changing his password but provided insufficient authentication");
writeProxy.write(socketID, new PasswordChangeResult(correctAuthentication));
}
}

View File

@ -3,6 +3,7 @@ package envoy.server.processors;
import java.io.IOException;
import envoy.event.ProfilePicChange;
import envoy.server.net.ObjectWriteProxy;
/**
@ -12,5 +13,6 @@ import envoy.server.net.ObjectWriteProxy;
public final class ProfilePicChangeProcessor implements ObjectProcessor<ProfilePicChange> {
@Override
public void process(ProfilePicChange event, long socketID, ObjectWriteProxy writeProxy) throws IOException {}
public void process(ProfilePicChange event, long socketID, ObjectWriteProxy writeProxy)
throws IOException {}
}

View File

@ -5,9 +5,10 @@ import java.util.logging.*;
import envoy.event.ElementOperation;
import envoy.event.contact.UserOperation;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.net.*;
import envoy.util.EnvoyLog;
/**
* @author Kai S. K. Engelbart
@ -16,7 +17,8 @@ import envoy.util.EnvoyLog;
public final class UserOperationProcessor implements ObjectProcessor<UserOperation> {
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(UserOperationProcessor.class);
private static final Logger logger =
EnvoyLog.getLogger(UserOperationProcessor.class);
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
@Override
@ -26,12 +28,14 @@ public final class UserOperationProcessor implements ObjectProcessor<UserOperati
final var sender = persistenceManager.getUserByID(userID);
switch (evt.getOperationType()) {
case ADD:
logger.log(Level.FINE, String.format("Adding %s to the contact list of user %d.", evt.get(), userID));
logger.log(Level.FINE,
String.format("Adding %s to the contact list of user %d.", evt.get(), userID));
persistenceManager.addContactBidirectional(userID, contactID);
// Notify the contact if online
if (connectionManager.isOnline(contactID))
writeProxy.write(connectionManager.getSocketID(contactID), new UserOperation(sender.toCommon(), ElementOperation.ADD));
writeProxy.write(connectionManager.getSocketID(contactID),
new UserOperation(sender.toCommon(), ElementOperation.ADD));
break;
case REMOVE:
@ -45,7 +49,8 @@ public final class UserOperationProcessor implements ObjectProcessor<UserOperati
// Notify the removed contact if online
if (connectionManager.isOnline(contactID))
writeProxy.write(connectionManager.getSocketID(contactID), new UserOperation(sender.toCommon(), ElementOperation.REMOVE));
writeProxy.write(connectionManager.getSocketID(contactID),
new UserOperation(sender.toCommon(), ElementOperation.REMOVE));
break;
}
}

View File

@ -5,6 +5,7 @@ import java.util.stream.Collectors;
import envoy.data.Contact;
import envoy.event.contact.*;
import envoy.server.data.*;
import envoy.server.net.*;
@ -16,19 +17,21 @@ import envoy.server.net.*;
public final class UserSearchProcessor implements ObjectProcessor<UserSearchRequest> {
/**
* Writes a list of contacts to the client containing all {@link Contact}s
* matching the search phrase contained inside the request. The client and their
* contacts are excluded from the result.
* Writes a list of contacts to the client containing all {@link Contact}s matching the search
* phrase contained inside the request. The client and their contacts are excluded from the
* result.
*
* @since Envoy Server Standalone v0.1-alpha
*/
@Override
public void process(UserSearchRequest request, long socketID, ObjectWriteProxy writeProxy) throws IOException {
public void process(UserSearchRequest request, long socketID, ObjectWriteProxy writeProxy)
throws IOException {
writeProxy.write(socketID,
new UserSearchResult(PersistenceManager.getInstance()
.searchUsers(request.get(), ConnectionManager.getInstance().getUserIDBySocketID(socketID))
.stream()
.map(User::toCommon)
.collect(Collectors.toList())));
new UserSearchResult(PersistenceManager.getInstance()
.searchUsers(request.get(),
ConnectionManager.getInstance().getUserIDBySocketID(socketID))
.stream()
.map(User::toCommon)
.collect(Collectors.toList())));
}
}

View File

@ -4,9 +4,10 @@ import java.util.logging.Logger;
import envoy.data.User.UserStatus;
import envoy.event.UserStatusChange;
import envoy.util.EnvoyLog;
import envoy.server.data.*;
import envoy.server.net.ObjectWriteProxy;
import envoy.util.EnvoyLog;
/**
* This processor handles incoming {@link UserStatusChange}.
@ -19,7 +20,8 @@ public final class UserStatusChangeProcessor implements ObjectProcessor<UserStat
private static ObjectWriteProxy writeProxy;
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private static final Logger logger = EnvoyLog.getLogger(UserStatusChangeProcessor.class);
private static final Logger logger =
EnvoyLog.getLogger(UserStatusChangeProcessor.class);
@Override
public void process(UserStatusChange input, long socketID, ObjectWriteProxy writeProxy) {
@ -32,8 +34,8 @@ public final class UserStatusChangeProcessor implements ObjectProcessor<UserStat
}
/**
* Sets the {@link UserStatus} for a given user. Both offline contacts and
* currently online contacts are notified.
* Sets the {@link UserStatus} for a given user. Both offline contacts and currently online
* contacts are notified.
*
* @param user the user whose status has changed
* @param newStatus the new status of that user
@ -47,19 +49,21 @@ public final class UserStatusChangeProcessor implements ObjectProcessor<UserStat
persistenceManager.updateContact(user);
// Handling for contacts that are already online
writeProxy.writeToOnlineContacts(user.getContacts(), new UserStatusChange(user.getID(), user.getStatus()));
writeProxy.writeToOnlineContacts(user.getContacts(),
new UserStatusChange(user.getID(), user.getStatus()));
}
/**
* This method is only called by the LoginCredentialProcessor because every
* user needs to login (open a socket) before changing his status.
* Needed to ensure propagation of events because an uninitialized writeProxy
* would cause problems.
* This method is only called by the LoginCredentialProcessor because every user needs to login
* (open a socket) before changing his status. Needed to ensure propagation of events because an
* uninitialized writeProxy would cause problems.
*
* @param writeProxy the writeProxy that is used to send objects back to clients
* @since Envoy Server Standalone v0.1-alpha
*/
public static void setWriteProxy(ObjectWriteProxy writeProxy) { UserStatusChangeProcessor.writeProxy = writeProxy; }
public static void setWriteProxy(ObjectWriteProxy writeProxy) {
UserStatusChangeProcessor.writeProxy = writeProxy;
}
// TODO may cause an problem if two clients log in at the same time.
// Change Needed.
}

View File

@ -1,6 +1,5 @@
/**
* This package contains all classes that process data received from client
* connections.
* This package contains all classes that process data received from client connections.
*
* @author Kai S. K. Engelbart
* @author Leon Hofmeister

View File

@ -11,7 +11,8 @@ import java.security.SecureRandom;
public final class AuthTokenGenerator {
private static final int TOKEN_LENGTH = 128;
private static final char[] CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private static final char[] CHARACTERS =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private static final char[] BUFF = new char[TOKEN_LENGTH];
private static final SecureRandom RANDOM = new SecureRandom();

View File

@ -7,9 +7,9 @@ import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
/**
* Provides a password hashing and comparison mechanism using the
* {@code PBKDF2WithHmacSHA1} algorithm.
*
* Provides a password hashing and comparison mechanism using the {@code PBKDF2WithHmacSHA1}
* algorithm.
*
* @author Kai S. K. Engelbart
* @since Envoy Server Standalone v0.1-beta
*/
@ -37,7 +37,8 @@ public final class PasswordUtil {
byte[] salt = fromHex(parts[1]);
byte[] hash = fromHex(parts[2]);
var spec = new PBEKeySpec(current.toCharArray(), salt, iterations, KEY_LENGTH);
var spec =
new PBEKeySpec(current.toCharArray(), salt, iterations, KEY_LENGTH);
var skf = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM);
byte[] testHash = skf.generateSecret(spec).getEncoded();
@ -53,7 +54,7 @@ public final class PasswordUtil {
/**
* Creates a parameterized salted password hash.
*
*
* @param password the password to hash
* @return a result string in the form of {@code iterations:salt:hash}
* @since Envoy Server Standalone v0.1-beta

View File

@ -3,8 +3,8 @@ package envoy.server.util;
import java.util.regex.Pattern;
/**
* Implements a comparison algorithm between Envoy versions and defines minimal
* and maximal client versions compatible with this server.
* Implements a comparison algorithm between Envoy versions and defines minimal and maximal client
* versions compatible with this server.
*
* @author Kai S. K. Engelbart
* @since Envoy Server Standalone v0.1-beta
@ -25,13 +25,14 @@ public final class VersionUtil {
*/
public static final String MAX_CLIENT_VERSION = "0.2-beta";
private static final Pattern versionPattern = Pattern.compile("(?<major>\\d).(?<minor>\\d)(?:-(?<suffix>\\w+))?");
private static final Pattern versionPattern =
Pattern.compile("(?<major>\\d).(?<minor>\\d)(?:-(?<suffix>\\w+))?");
private VersionUtil() {}
/**
* Parses an Envoy Client version string and checks whether that version is
* compatible with this server.
* Parses an Envoy Client version string and checks whether that version is compatible with this
* server.
*
* @param version the version string to parse
* @return {@code true} if the given version is compatible with this server
@ -40,12 +41,14 @@ public final class VersionUtil {
public static boolean verifyCompatibility(String version) {
final var currentMatcher = versionPattern.matcher(version);
if (!currentMatcher.matches()) return false;
if (!currentMatcher.matches())
return false;
final var minMatcher = versionPattern.matcher(MIN_CLIENT_VERSION);
final var maxMatcher = versionPattern.matcher(MAX_CLIENT_VERSION);
if (!minMatcher.matches() || !maxMatcher.matches()) throw new RuntimeException("Invalid min or max client version configured!");
if (!minMatcher.matches() || !maxMatcher.matches())
throw new RuntimeException("Invalid min or max client version configured!");
// Compare suffixes
{
@ -53,7 +56,8 @@ public final class VersionUtil {
final var minSuffix = convertSuffix(minMatcher.group("suffix"));
final var maxSuffix = convertSuffix(maxMatcher.group("suffix"));
if (currentSuffix < minSuffix || currentSuffix > maxSuffix) return false;
if (currentSuffix < minSuffix || currentSuffix > maxSuffix)
return false;
}
// Compare major
@ -62,7 +66,8 @@ public final class VersionUtil {
final var minMajor = Integer.parseInt(minMatcher.group("major"));
final var maxMajor = Integer.parseInt(maxMatcher.group("major"));
if (currentMajor < minMajor || currentMajor > maxMajor) return false;
if (currentMajor < minMajor || currentMajor > maxMajor)
return false;
}
// Compare minor
@ -71,7 +76,8 @@ public final class VersionUtil {
final var minMinor = Integer.parseInt(minMatcher.group("minor"));
final var maxMinor = Integer.parseInt(maxMatcher.group("minor"));
if (currentMinor < minMinor || currentMinor > maxMinor) return false;
if (currentMinor < minMinor || currentMinor > maxMinor)
return false;
}
return true;

View File

@ -1,6 +1,6 @@
/**
* This package contains utility classes used in Envoy Server.
*
*
* @author Kai S. K. Engelbart
* @since Envoy Server Standalone v0.1-beta
*/

View File

@ -1,6 +1,5 @@
/**
* This module contains all classes defining the server application of the Envoy
* project.
* This module contains all classes defining the server application of the Envoy project.
*
* @author Kai S. K. Engelbart
* @author Leon Hofmeister