diff --git a/.gitignore b/.gitignore index c96d30a..db08139 100644 --- a/.gitignore +++ b/.gitignore @@ -249,3 +249,5 @@ paket-files/ target/classes/* /target/ + +chatdb/ diff --git a/main/resources/META-INF/persistence.xml b/main/resources/META-INF/persistence.xml index 49b3b59..2a5549b 100644 --- a/main/resources/META-INF/persistence.xml +++ b/main/resources/META-INF/persistence.xml @@ -5,7 +5,7 @@ - + diff --git a/pom.xml b/pom.xml index 3a008df..1a95534 100644 --- a/pom.xml +++ b/pom.xml @@ -64,11 +64,8 @@ 2.6.2 - - org.json - json - 20160212 - + org.hibernate @@ -86,7 +83,6 @@ spring-tx ${spring-framework.version} - org.springframework @@ -98,6 +94,12 @@ spring-jdbc ${spring-framework.version} + + + com.google.code.gson + gson + 2.7 + 1.8 diff --git a/src/io/github/norbipeti/chat/server/IOHelper.java b/src/io/github/norbipeti/chat/server/IOHelper.java index 7a47da7..3a6a7b0 100644 --- a/src/io/github/norbipeti/chat/server/IOHelper.java +++ b/src/io/github/norbipeti/chat/server/IOHelper.java @@ -18,13 +18,14 @@ import java.util.function.Function; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; -import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.sun.net.httpserver.HttpExchange; -import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.User; import io.github.norbipeti.chat.server.page.Page; @@ -66,7 +67,6 @@ public class IOHelper { return content; } - @Deprecated public static HashMap GetPOST(HttpExchange exchange) throws IOException { if (exchange.getRequestBody().available() == 0) return new HashMap<>(); @@ -87,12 +87,12 @@ public class IOHelper { } } - public static JSONObject GetPOSTJSON(HttpExchange exchange) throws IOException { + public static JsonObject GetPOSTJSON(HttpExchange exchange) throws IOException { if (exchange.getRequestBody().available() == 0) return null; try { String content = IOUtils.toString(exchange.getRequestBody(), StandardCharsets.ISO_8859_1).trim(); - JSONObject obj = new JSONObject(content); + JsonObject obj = new JsonParser().parse(content).getAsJsonObject(); return obj; } catch (Exception e) { e.printStackTrace(); @@ -111,12 +111,17 @@ public class IOHelper { return true; } - public static void LoginUser(HttpExchange exchange, User user, DataProvider provider) { + /** + * Sends login headers and sets the session id on the user + * + * @param exchange + * @param user + */ + public static void LoginUser(HttpExchange exchange, User user) { LogManager.getLogger().log(Level.DEBUG, "Logging in user: " + user); // provider.SetValues(() -> // user.setSessionid(UUID.randomUUID().toString())); user.setSessionid(UUID.randomUUID().toString()); - user = provider.save(user); ZonedDateTime expiretime = ZonedDateTime.now(ZoneId.of("GMT")).plus(Period.of(2, 0, 0)); exchange.getResponseHeaders().add("Set-Cookie", "user_id=" + user.getId() + "; expires=" + expiretime.format(DateTimeFormatter.RFC_1123_DATE_TIME)); @@ -162,19 +167,17 @@ public class IOHelper { * * @param exchange * @return The logged in user or null if not logged in. + * @throws IOException */ - public static User GetLoggedInUser(HttpExchange exchange) { + public static User GetLoggedInUser(HttpExchange exchange) throws IOException { HashMap cookies = GetCookies(exchange); if (!cookies.containsKey("user_id") || !cookies.containsKey("session_id")) return null; - try (DataProvider provider = new DataProvider()) { - User user = provider.getUser(Long.parseLong(cookies.get("user_id"))); - if (user != null && cookies.get("session_id") != null - && cookies.get("session_id").equals(user.getSessionid())) - return user; - else - SendLogoutHeaders(exchange); - } + User user = DataManager.load(User.class, Long.parseLong(cookies.get("user_id"))); + if (user != null && cookies.get("session_id") != null && cookies.get("session_id").equals(user.getSessionid())) + return user; + else + SendLogoutHeaders(exchange); return null; } diff --git a/src/io/github/norbipeti/chat/server/Main.java b/src/io/github/norbipeti/chat/server/Main.java index 68ad7c2..9809467 100644 --- a/src/io/github/norbipeti/chat/server/Main.java +++ b/src/io/github/norbipeti/chat/server/Main.java @@ -4,23 +4,17 @@ import java.lang.reflect.Modifier; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Date; -import java.util.List; import java.util.Set; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.LoggerConfig; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; - import com.sun.net.httpserver.HttpServer; -import io.github.norbipeti.chat.server.db.*; + +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.*; import io.github.norbipeti.chat.server.page.*; @@ -30,52 +24,53 @@ public class Main { // https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/ // https://docs.oracle.com/javase/8/docs/api/ LogManager.getLogger().log(Level.INFO, "Loading database..."); - try (DataProvider provider = new DataProvider()) { - User user = new User(); - user.setName("asd"); - user.setEmail("test@test.com"); - User user2 = new User(); - user2.setName("Teszt"); - user2.setEmail("test2@test.com"); - // user = provider.save(user); - // user2 = provider.save(user2); - user.getContacts().add(user2); - user2.getContacts().add(user); - LogManager.getLogger().log(Level.DEBUG, "1st's contact: " + user.getContacts().get(0)); - LogManager.getLogger().log(Level.DEBUG, "2nd's contact: " + user2.getContacts().get(0)); - Conversation conversation = new Conversation(); - conversation = provider.save(conversation); - conversation.getUsers().add(user); - user.getConversations().add(conversation); - LogManager.getLogger().debug("User: " + user); - conversation.getUsers().add(user2); - LogManager.getLogger().debug("User2: " + user2); // TODO: Switch - // to JSON - // files? - user2.getConversations().add(conversation); // TODO: Fix - // duplicate - // key constraint - Message msg = new Message(); - msg.setSender(user); - msg.setTime(new Date()); - msg.setMessage("Teszt 1"); - conversation.getMesssages().add(msg); - Message msg2 = new Message(); - msg2.setSender(user2); - msg2.setTime(new Date()); - msg2.setMessage("Teszt 2"); - conversation.getMesssages().add(msg2); - // provider.save(user); - // provider.save(user2); - /* - * User loggedinuser = new User(); provider.save(loggedinuser); - * loggedinuser.setName("NorbiPeti"); loggedinuser.setSessionid( - * "093b1395-8c31-4f3b-ba67-828a755af92e"); - * loggedinuser.setEmail("sznp@asd.com"); - * conversation.getUsers().add(loggedinuser); - * loggedinuser.getConversations().add(conversation); - */ - } + User user = new User(); + user.setName("asd"); + user.setEmail("test@test.com"); + User user2 = new User(); + user2.setName("Teszt"); + user2.setEmail("test2@test.com"); + // user = provider.save(user); + // user2 = provider.save(user2); + user.getContacts().add(user2); + user2.getContacts().add(user); + LogManager.getLogger().log(Level.DEBUG, "1st's contact: " + user.getContacts().get(0)); + LogManager.getLogger().log(Level.DEBUG, "2nd's contact: " + user2.getContacts().get(0)); + Conversation conversation = new Conversation(); + conversation.getUsers().add(user); + user.getConversations().add(conversation); + LogManager.getLogger().debug("User: " + user); + // conversation.getUsers().add(user2); - TODO + LogManager.getLogger().debug("User2: " + user2); // TODO: Switch + // to JSON + // files? + // user2.getConversations().add(conversation); // TODO: Fix + // duplicate + // key constraint + Message msg = new Message(); + msg.setSender(user); + msg.setTime(new Date()); + msg.setMessage("Teszt 1"); + conversation.getMesssages().add(msg); + Message msg2 = new Message(); + msg2.setSender(user2); + msg2.setTime(new Date()); + msg2.setMessage("Teszt 2"); + conversation.getMesssages().add(msg2); + // provider.save(user); + // provider.save(user2);s + User loggedinuser = new User(); + loggedinuser.setName("NorbiPeti"); + loggedinuser.setSessionid("093b1395-8c31-4f3b-ba67-828a755af92e"); + loggedinuser.setEmail("sznp@asd.com"); + loggedinuser.getContacts().add(user2); + conversation.getUsers().add(loggedinuser); + loggedinuser.getConversations().add(conversation); + DataManager.save(user); + DataManager.save(user2); + DataManager.save(loggedinuser); + DataManager.save(conversation); + LogManager.getLogger().log(Level.INFO, "Starting webserver..."); HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 8080), 10); Reflections rf = new Reflections( @@ -100,7 +95,9 @@ public class Main { System.in.read(); LogManager.getLogger().log(Level.INFO, "Stopping..."); server.stop(1); - } catch (Exception e) { + } catch ( + + Exception e) { e.printStackTrace(); } LogManager.getLogger().log(Level.INFO, "Stopped"); diff --git a/src/io/github/norbipeti/chat/server/data/DataManager.java b/src/io/github/norbipeti/chat/server/data/DataManager.java new file mode 100644 index 0000000..d8bc395 --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/DataManager.java @@ -0,0 +1,61 @@ +package io.github.norbipeti.chat.server.data; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import com.google.common.io.Files; +import com.google.gson.Gson; +import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; + +public final class DataManager { + private DataManager() { + } + + public static void save(T object) throws IOException { + Gson gson = new Gson(); + Files.write(gson.toJson(object), new File(object.getClass().getName() + "-" + object.getId()), + StandardCharsets.UTF_8); + } + + public static T load(Class cl, long id) { + return loadFromFile(new File(cl.getName() + "-" + id), cl); + } + + public static LoaderCollection load(Class cl) { + String[] filenames = new File(".").list(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.startsWith(cl.getName() + "-"); + } + }); + LoaderCollection rets = new LoaderCollection(cl, filenames.length); + for (int i = 0; i < filenames.length; i++) { + rets.add(loadFromFile(new File(filenames[i]), cl)); + } + return rets; + } + + private static T loadFromFile(File file, Class cl) { + try { + if (!file.exists()) + return cl.newInstance(); + BufferedReader reader = Files.newReader(file, StandardCharsets.UTF_8); + String objstr = ""; + String line; + while ((line = reader.readLine()) != null) + objstr += line; + Gson gson = new Gson(); + return gson.fromJson(objstr, cl); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static boolean remove(T obj) { + return new File(obj.getClass().getName() + "-" + obj.getId()).delete(); + } +} diff --git a/src/io/github/norbipeti/chat/server/data/LoaderCollection.java b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java new file mode 100644 index 0000000..1b251fe --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/LoaderCollection.java @@ -0,0 +1,208 @@ +package io.github.norbipeti.chat.server.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.stream.Collectors; + +import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; + +public class LoaderCollection implements List, Serializable { + private static final long serialVersionUID = 5426152406394894301L; + private List contacts; + private Class cl; + + /** + * Only used for serialization + */ + @Deprecated + public LoaderCollection() { + } + + public LoaderCollection(Class cl) { + this.cl = cl; + contacts = new ArrayList<>(); + } + + public LoaderCollection(LoaderCollection parentofsub, int fromIndex, int toIndex) { + this.cl = parentofsub.cl; + contacts = parentofsub.contacts.subList(fromIndex, toIndex); + } + + public LoaderCollection(Class cl, int capacity) { + this.cl = cl; + contacts = new ArrayList<>(capacity); + } + + @Override + public Iterator iterator() { + return new LoaderIterator(contacts.iterator(), cl); + } + + @Override + public boolean add(T e) { + return contacts.add(e.getId()); + } + + @Override + public void add(int index, T element) { + contacts.add(index, element.getId()); + } + + @Override + public boolean addAll(Collection c) { + return contacts + .addAll(c.stream().map((data) -> ((ChatDatabaseEntity) data).getId()).collect(Collectors.toList())); + } + + @Override + public boolean addAll(int index, Collection c) { + return contacts.addAll(index, + c.stream().map((data) -> ((ChatDatabaseEntity) data).getId()).collect(Collectors.toList())); + } + + @Override + public void clear() { + contacts.clear(); + } + + @Override + public boolean contains(Object o) { + return contacts.contains(o); + } + + @Override + public boolean containsAll(Collection c) { + return contacts.containsAll(c); + } + + @Override + public T get(int index) { + return DataManager.load(cl, contacts.get(index)); + } + + @Override + public int indexOf(Object o) { + return contacts.indexOf(o); + } + + @Override + public boolean isEmpty() { + return contacts.isEmpty(); + } + + @Override + public int lastIndexOf(Object o) { + return contacts.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return new LoaderListIterator(contacts.listIterator(), cl); + } + + @Override + public ListIterator listIterator(int index) { + return new LoaderListIterator(contacts.listIterator(index), cl); + } + + /** + * Remove an object from this collection + * + * @param o + * Either the object of type T or the ID + */ + @Override + public boolean remove(Object o) { + if (ChatDatabaseEntity.class.isAssignableFrom(o.getClass())) + return contacts.remove(((ChatDatabaseEntity) o).getId()); + return contacts.remove(o); + } + + @Override + public T remove(int index) { + return DataManager.load(cl, contacts.remove(index)); + } + + @Override + public boolean removeAll(Collection c) { + boolean success = false; + for (Object item : c) { + if (ChatDatabaseEntity.class.isAssignableFrom(item.getClass())) { + if (contacts.remove(((ChatDatabaseEntity) item).getId())) { + success = true; + break; + } + } else { + if (contacts.remove(item)) { + success = true; + break; + } + } + } + return success; + } + + @Override + public boolean retainAll(Collection c) { + List list = new ArrayList(); + for (Object item : c) { + if (ChatDatabaseEntity.class.isAssignableFrom(item.getClass())) { + list.add(((ChatDatabaseEntity) item).getId()); + } else if (Long.class.isAssignableFrom(item.getClass())) { + list.add((Long) item); + } + } + return contacts.retainAll(list); + } + + @Override + public T set(int index, T element) { + return DataManager.load(cl, contacts.set(index, element.getId())); + } + + @Override + public int size() { + return contacts.size(); + } + + @Override + public List subList(int fromIndex, int toIndex) { + // TODO Auto-generated method stub + return new LoaderCollection(this, fromIndex, toIndex); + } + + @Override + public Object[] toArray() { + return contacts.stream().map((data) -> { + return DataManager.load(cl, data); + }).collect(Collectors.toList()).toArray(); + } + + @Override + public U[] toArray(U[] a) { + return contacts.stream().map((data) -> { + return DataManager.load(cl, data); + }).collect(Collectors.toList()).toArray(a); + } + + @Override + public String toString() { + return toString(false); + } + + public String toString(boolean loaditems) { + StringBuilder sb = new StringBuilder("["); + for (Long item : contacts) { + if (loaditems) + sb.append(DataManager.load(cl, item)); + else + sb.append(item); + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/src/io/github/norbipeti/chat/server/data/LoaderIterator.java b/src/io/github/norbipeti/chat/server/data/LoaderIterator.java new file mode 100644 index 0000000..bf73a2b --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/LoaderIterator.java @@ -0,0 +1,35 @@ +package io.github.norbipeti.chat.server.data; + +import java.util.Iterator; +import java.util.ListIterator; + +import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; + +public final class LoaderIterator implements Iterator { + private Iterator iterator; + private T lastitem; + private Class cl; + + LoaderIterator(Iterator listiterator, Class cl) { + this.iterator = listiterator; + this.cl = cl; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public T next() { + return lastitem = DataManager.load(cl, iterator.next()); + } + + @Override + public void remove() { + if (lastitem == null) + throw new IllegalStateException(); + DataManager.remove(lastitem); + lastitem = null; + } +} diff --git a/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java b/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java new file mode 100644 index 0000000..2d87537 --- /dev/null +++ b/src/io/github/norbipeti/chat/server/data/LoaderListIterator.java @@ -0,0 +1,64 @@ +package io.github.norbipeti.chat.server.data; + +import java.util.ListIterator; + +import io.github.norbipeti.chat.server.db.domain.ChatDatabaseEntity; + +public final class LoaderListIterator implements ListIterator { + private ListIterator listiterator; + private T lastitem; + private Class cl; + + LoaderListIterator(ListIterator listiterator, Class cl) { + this.listiterator = listiterator; + this.cl = cl; + } + + @Override + public boolean hasNext() { + return listiterator.hasNext(); + } + + @Override + public T next() { + return lastitem = DataManager.load(cl, listiterator.next()); + } + + @Override + public void remove() { + if (lastitem == null) + throw new IllegalStateException(); + DataManager.remove(lastitem); + lastitem = null; + } + + @Override + public void add(T e) { + listiterator.add(e.getId()); + } + + @Override + public boolean hasPrevious() { + return listiterator.hasPrevious(); + } + + @Override + public int nextIndex() { + return listiterator.nextIndex(); + } + + @Override + public T previous() { + return DataManager.load(cl, listiterator.previous()); + } + + @Override + public int previousIndex() { + return listiterator.previousIndex(); + } + + @Override + public void set(T e) { + listiterator.set(e.getId()); + } +} diff --git a/src/io/github/norbipeti/chat/server/db/DataProvider.java b/src/io/github/norbipeti/chat/server/db/DataProvider.java index de8ee85..74d7099 100644 --- a/src/io/github/norbipeti/chat/server/db/DataProvider.java +++ b/src/io/github/norbipeti/chat/server/db/DataProvider.java @@ -7,10 +7,9 @@ import javax.persistence.Persistence; import javax.persistence.TypedQuery; import org.hibernate.Hibernate; -import org.hibernate.Session; - import io.github.norbipeti.chat.server.db.domain.*; +@Deprecated public class DataProvider implements AutoCloseable { private EntityManagerFactory emf; private EntityManager em; diff --git a/src/io/github/norbipeti/chat/server/db/domain/ChatDatabaseEntity.java b/src/io/github/norbipeti/chat/server/db/domain/ChatDatabaseEntity.java index 21f0085..2125011 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/ChatDatabaseEntity.java +++ b/src/io/github/norbipeti/chat/server/db/domain/ChatDatabaseEntity.java @@ -4,5 +4,15 @@ import java.io.Serializable; @SuppressWarnings("serial") public abstract class ChatDatabaseEntity implements Serializable { + private static long nextID = 0; + private long id; + + public long getId() { + return id; + } + + protected ChatDatabaseEntity() { + id = nextID++; + } } diff --git a/src/io/github/norbipeti/chat/server/db/domain/Conversation.java b/src/io/github/norbipeti/chat/server/db/domain/Conversation.java index 1129ccc..6059f1c 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Conversation.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Conversation.java @@ -8,12 +8,13 @@ import java.util.Set; import javax.persistence.*; @Entity +@Table(name = "CONVERSATION") public class Conversation extends ChatDatabaseEntity { private static final long serialVersionUID = 5058682475353799722L; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", unique = true, nullable = false) - private Long id; + //@Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + //@Column(name = "ID", unique = true, nullable = false) + //private Long id; @ElementCollection(fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "conversation") private List messsages; @@ -27,7 +28,7 @@ public class Conversation extends ChatDatabaseEntity { // @JoinTable(name = "User_Conversation", joinColumns = @JoinColumn(name = // "conversation_id", referencedColumnName = "id"), inverseJoinColumns = // @JoinColumn(name = "user_id", referencedColumnName = "id")) - @JoinTable(name = "User_Conversation") + // @JoinTable(name = "User_Conversation") private Set users; public List getMesssages() { @@ -50,11 +51,11 @@ public class Conversation extends ChatDatabaseEntity { this.users = users; } - public Long getId() { + /*public Long getId() { return id; } public void setId(Long id) { this.id = id; - } + }*/ } diff --git a/src/io/github/norbipeti/chat/server/db/domain/Message.java b/src/io/github/norbipeti/chat/server/db/domain/Message.java index 9d23dde..3b0762b 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/Message.java +++ b/src/io/github/norbipeti/chat/server/db/domain/Message.java @@ -5,12 +5,13 @@ import java.util.Date; import javax.persistence.*; @Entity +@Table(name = "MESSAGE") public class Message extends ChatDatabaseEntity { private static final long serialVersionUID = 6345941601716826570L; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", unique = true, nullable = false) - private Long id; + //@Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + //@Column(name = "ID", unique = true, nullable = false) + //private Long id; @ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) // @JoinTable(name="user_message") private User sender; @@ -52,11 +53,11 @@ public class Message extends ChatDatabaseEntity { this.conversation = conversation; } - public Long getId() { + /*public Long getId() { return id; } public void setId(Long id) { this.id = id; - } + }*/ } diff --git a/src/io/github/norbipeti/chat/server/db/domain/User.java b/src/io/github/norbipeti/chat/server/db/domain/User.java index 292cc69..25a9f55 100644 --- a/src/io/github/norbipeti/chat/server/db/domain/User.java +++ b/src/io/github/norbipeti/chat/server/db/domain/User.java @@ -1,5 +1,6 @@ package io.github.norbipeti.chat.server.db.domain; +import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -7,27 +8,30 @@ import java.util.Set; import javax.persistence.*; +import io.github.norbipeti.chat.server.data.DataManager; +import io.github.norbipeti.chat.server.data.LoaderCollection; + @Entity -@Table(name = "\"User\"") +@Table(name = "\"USER\"") public class User extends ChatDatabaseEntity { private static final long serialVersionUID = 2862762084164225666L; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", unique = true, nullable = false) - private Long id; + // @Id + // @GeneratedValue(strategy = GenerationType.IDENTITY) + // @Column(name = "ID", unique = true, nullable = false) + // private Long id; private String name; private String email; private String password; @ElementCollection(fetch = FetchType.EAGER) - @ManyToMany(cascade = CascadeType.ALL) - private List contacts; + @OneToOne(cascade = CascadeType.ALL) + private LoaderCollection contacts; private String salt; // @Column(columnDefinition = "CHAR(16) FOR BIT DATA") @Column(columnDefinition = "VARCHAR(64)") private String sessionid; @ElementCollection(fetch = FetchType.EAGER) // @ManyToMany(fetch = FetchType.EAGER, mappedBy = "users") - @ManyToMany(mappedBy = "users", fetch = FetchType.EAGER, cascade = CascadeType.MERGE) + @ManyToMany(mappedBy = "USER", fetch = FetchType.EAGER, cascade = CascadeType.MERGE) // @ManyToMany(mappedBy = "users") // @JoinTable(name = "User_Conversation", joinColumns = // @JoinColumn(referencedColumnName = "id", unique = false), @@ -35,16 +39,18 @@ public class User extends ChatDatabaseEntity { // false)) private Set conversations; - public List getContacts() { + /** + * Loads all contact data + * + * @return + * @throws IOException + */ + public List getContacts() throws IOException { if (contacts == null) - contacts = new ArrayList<>(); + contacts = new LoaderCollection(User.class); return contacts; } - public void setContacts(List contacts) { - this.contacts = contacts; - } - public String getName() { return name; } @@ -59,14 +65,8 @@ public class User extends ChatDatabaseEntity { @Override public String toString() { - List c = null; - if (contacts != null) { - c = new ArrayList<>(); - for (User u : contacts) - c.add(u.name); - } - return "User [id=" + id + ", name=" + name + ", email=" + email + ", password=" + password + ", contacts=" + c - + ", sessionid=" + sessionid + "]"; + return "User [id=" + getId() + ", name=" + name + ", email=" + email + ", password=" + password + ", contacts=" + + contacts + ", sessionid=" + sessionid + "]"; } public void setEmail(String email) { @@ -81,14 +81,6 @@ public class User extends ChatDatabaseEntity { this.password = password; } - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - public String getSalt() { return salt; } @@ -116,6 +108,9 @@ public class User extends ChatDatabaseEntity { } public User() { + } + public static LoaderCollection getUsers() { + return DataManager.load(User.class); } } diff --git a/src/io/github/norbipeti/chat/server/page/IndexPage.java b/src/io/github/norbipeti/chat/server/page/IndexPage.java index 897d32c..8fa2118 100644 --- a/src/io/github/norbipeti/chat/server/page/IndexPage.java +++ b/src/io/github/norbipeti/chat/server/page/IndexPage.java @@ -8,7 +8,7 @@ import org.jsoup.nodes.Element; import com.sun.net.httpserver.HttpExchange; import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.Conversation; import io.github.norbipeti.chat.server.db.domain.Message; import io.github.norbipeti.chat.server.db.domain.User; @@ -35,18 +35,16 @@ public class IndexPage extends Page { Element userbox = doc.getElementById("userbox"); userbox.html(userbox.html().replace("", user.getName())); Element channelmessages = doc.getElementById("channelmessages"); - try (DataProvider provider = new DataProvider()) { - LogManager.getLogger().log(Level.INFO, "Conversations: " + provider.getConversations().size()); - LogManager.getLogger().log(Level.INFO, "User conversations: " + user.getConversations().size()); - Conversation convo = user.getConversations().iterator().next(); - LogManager.getLogger().log(Level.INFO, "Messages: " + convo.getMesssages().size()); - for (Message message : convo.getMesssages()) { - Element msgelement = channelmessages.appendElement("div"); - Element header = msgelement.appendElement("p"); - header.text(message.getSender().getName() + " - " + message.getTime()); - Element body = msgelement.appendElement("p"); - body.text(message.getMessage()); - } + LogManager.getLogger().log(Level.INFO, "Conversations: " + DataManager.load(Conversation.class).size()); + LogManager.getLogger().log(Level.INFO, "User conversations: " + user.getConversations().size()); + Conversation convo = user.getConversations().iterator().next(); + LogManager.getLogger().log(Level.INFO, "Messages: " + convo.getMesssages().size()); + for (Message message : convo.getMesssages()) { + Element msgelement = channelmessages.appendElement("div"); + Element header = msgelement.appendElement("p"); + header.text(message.getSender().getName() + " - " + message.getTime()); + Element body = msgelement.appendElement("p"); + body.text(message.getMessage()); } return doc; }, exchange); diff --git a/src/io/github/norbipeti/chat/server/page/LoginAjaxPage.java b/src/io/github/norbipeti/chat/server/page/LoginAjaxPage.java index c1ff975..1762761 100644 --- a/src/io/github/norbipeti/chat/server/page/LoginAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/LoginAjaxPage.java @@ -1,44 +1,40 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; -import org.json.JSONObject; import org.mindrot.jbcrypt.BCrypt; +import com.google.gson.JsonObject; import com.sun.net.httpserver.HttpExchange; import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.User; public class LoginAjaxPage extends Page { @Override public void handlePage(HttpExchange exchange) throws IOException { - JSONObject post = IOHelper.GetPOSTJSON(exchange); + JsonObject post = IOHelper.GetPOSTJSON(exchange); if (post == null || !post.has("email") || !post.has("pass")) { IOHelper.Redirect("/", exchange); return; } - try (DataProvider provider = new DataProvider()) { - User loginuser = null; - for (User user : provider.getUsers()) { - if (user.getEmail().equals(post.get("email"))) { - loginuser = user; - break; - } + User loginuser = null; + for (User user : DataManager.load(User.class)) { + if (user.getEmail().equals(post.get("email"))) { + loginuser = user; + break; } - if (loginuser == null || !BCrypt.checkpw(post.getString("pass"), loginuser.getPassword())) { - IOHelper.SendResponse(200, (doc) -> { - doc.appendElement("p").text("The username or password is invalid."); - return doc; - }, exchange); - return; - } - IOHelper.LoginUser(exchange, loginuser, provider); - IOHelper.SendResponse(200, "Success", exchange); - } catch (Exception e) { - throw e; } + if (loginuser == null || !BCrypt.checkpw(post.get("pass").getAsString(), loginuser.getPassword())) { + IOHelper.SendResponse(200, (doc) -> { + doc.appendElement("p").text("The username or password is invalid."); + return doc; + }, exchange); + return; + } + IOHelper.LoginUser(exchange, loginuser); + IOHelper.SendResponse(200, "Success", exchange); } @Override diff --git a/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java b/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java index 3aceee8..860a130 100644 --- a/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/MessageAjaxPage.java @@ -2,19 +2,15 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; import java.util.Date; -import java.util.HashMap; -import java.util.List; import java.util.Set; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.json.JSONObject; - +import com.google.gson.JsonObject; import com.sun.net.httpserver.HttpExchange; import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.Conversation; import io.github.norbipeti.chat.server.db.domain.Message; import io.github.norbipeti.chat.server.db.domain.User; @@ -33,7 +29,7 @@ public class MessageAjaxPage extends Page { IOHelper.SendResponse(403, "

Please log in to send messages

", exchange); return; // TODO: Fix sending messages } - JSONObject obj = IOHelper.GetPOSTJSON(exchange); + JsonObject obj = IOHelper.GetPOSTJSON(exchange); if (obj == null) { IOHelper.SendResponse(400, "

400 Bad request

Not a JSON string!

" + IOHelper.GetPOST(exchange) + "

", @@ -47,8 +43,8 @@ public class MessageAjaxPage extends Page { exchange); return; } - String message = obj.getString("message"); - int conversation = obj.getInt("conversation"); + String message = obj.get("message").getAsString(); + int conversation = obj.get("conversation").getAsInt(); if (message.trim().length() == 0) { IOHelper.SendResponse(400, "

400 Bad request

The message cannot be empty,

", exchange); return; @@ -68,20 +64,15 @@ public class MessageAjaxPage extends Page { + conversation + " is not found.

", exchange); return; } - try (DataProvider provider = new DataProvider()) { - Message msg = new Message(); - msg.setSender(user); - msg.setMessage(message); - msg.setTime(new Date()); - msg.setConversation(conv); - provider.save(msg); - conv.getMesssages().add(msg); - provider.save(conv); - LogManager.getLogger().log(Level.DEBUG, - "Added conversation's message count: " + conv.getMesssages().size()); - } catch (Exception e) { - throw e; - } + Message msg = new Message(); + msg.setSender(user); + msg.setMessage(message); + msg.setTime(new Date()); + msg.setConversation(conv); // TODO: Store relations at one side or both + DataManager.save(msg); + conv.getMesssages().add(msg); + DataManager.save(conv); + LogManager.getLogger().log(Level.DEBUG, "Added conversation's message count: " + conv.getMesssages().size()); IOHelper.SendResponse(200, "Success", exchange); } diff --git a/src/io/github/norbipeti/chat/server/page/RegisterAjaxPage.java b/src/io/github/norbipeti/chat/server/page/RegisterAjaxPage.java index 71452d0..3152e9f 100644 --- a/src/io/github/norbipeti/chat/server/page/RegisterAjaxPage.java +++ b/src/io/github/norbipeti/chat/server/page/RegisterAjaxPage.java @@ -1,19 +1,19 @@ package io.github.norbipeti.chat.server.page; import java.io.IOException; -import org.json.JSONObject; import org.mindrot.jbcrypt.BCrypt; +import com.google.gson.JsonObject; import com.sun.net.httpserver.HttpExchange; import io.github.norbipeti.chat.server.IOHelper; -import io.github.norbipeti.chat.server.db.DataProvider; +import io.github.norbipeti.chat.server.data.DataManager; import io.github.norbipeti.chat.server.db.domain.User; public class RegisterAjaxPage extends Page { @Override public void handlePage(HttpExchange exchange) throws IOException { - JSONObject post = IOHelper.GetPOSTJSON(exchange); + JsonObject post = IOHelper.GetPOSTJSON(exchange); if (post != null) { String errormsg = CheckValues(post, "name", "email", "pass", "pass2"); if (errormsg.length() > 0) { @@ -21,40 +21,36 @@ public class RegisterAjaxPage extends Page { IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); return; // TODO: Use JavaScript too, for error checks } - try (DataProvider provider = new DataProvider()) { - for (User user : provider.getUsers()) { - if (post.get("email").equals(user.getEmail())) { - errormsg += "

An user with this name already exists

"; - break; - } + for (User user : DataManager.load(User.class)) { // TODO: Optimize + if (post.get("email").equals(user.getEmail())) { + errormsg += "

An user with this name already exists

"; + break; } - if (!post.get("pass").equals(post.get("pass2"))) - errormsg += "

The passwords don't match

"; - if (errormsg.length() > 0) { - final String msg = errormsg; - IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); - return; - } - User user = new User(); - user.setName(post.getString("name")); - user.setEmail(post.getString("email")); - user.setSalt(BCrypt.gensalt()); // http://www.mindrot.org/projects/jBCrypt/ - user.setPassword(BCrypt.hashpw(post.getString("pass"), user.getSalt())); - user = provider.save(user); - IOHelper.LoginUser(exchange, user, provider); - IOHelper.SendResponse(200, "Success", exchange); - } catch (Exception e) { - throw e; } + if (!post.get("pass").equals(post.get("pass2"))) + errormsg += "

The passwords don't match

"; + if (errormsg.length() > 0) { + final String msg = errormsg; + IOHelper.SendResponse(200, (doc) -> doc.html(msg).ownerDocument(), exchange); + return; + } + User user = new User(); + user.setName(post.get("name").getAsString()); + user.setEmail(post.get("email").getAsString()); + user.setSalt(BCrypt.gensalt()); // http://www.mindrot.org/projects/jBCrypt/ + user.setPassword(BCrypt.hashpw(post.get("pass").getAsString(), user.getSalt())); + IOHelper.LoginUser(exchange, user); + DataManager.save(user); + IOHelper.SendResponse(200, "Success", exchange); return; } IOHelper.Redirect("/", exchange); } - private String CheckValues(JSONObject post, String... values) { + private String CheckValues(JsonObject post, String... values) { String errormsg = ""; for (String value : values) - if (!CheckValue(post.getString(value))) + if (!CheckValue(post.get(value).getAsString())) errormsg += "

" + value + " can't be empty

"; return errormsg; }