diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index db24ee7..8ded9c8 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,13 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve @@ -6,10 +15,101 @@ org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=info org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.source=1.8 diff --git a/pom.xml b/pom.xml index db5b8da..22bcff3 100644 --- a/pom.xml +++ b/pom.xml @@ -28,12 +28,12 @@ com.github.informatik-ag-ngl envoy-common - develop-SNAPSHOT + v0.2-alpha com.github.informatik-ag-ngl java-nio-server - master-SNAPSHOT + v0.1-alpha org.hibernate @@ -54,5 +54,30 @@ src/main/resources + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4.1 + + + package + + single + + + + + envoy.server.Startup + + + + jar-with-dependencies + + + + + + \ No newline at end of file diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index e23bf69..13cd852 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -8,6 +8,7 @@ import com.jenkov.nioserver.Server; import envoy.server.data.ConfigItem; import envoy.server.database.PersistenceManager; +import envoy.server.net.ConnectionManager; import envoy.server.net.ObjectMessageProcessor; import envoy.server.net.ObjectMessageReader; import envoy.server.processors.*; @@ -53,7 +54,7 @@ public class Startup { } private static void initializeCurrentMessageId() { - PersistenceManager persMan = PersistenceManager.getPersistenceManager(); + PersistenceManager persMan = PersistenceManager.getInstance(); if (persMan.getConfigItemById("currentMessageId") == null) persMan.addConfigItem(new ConfigItem("currentMessageId", "0")); } } \ No newline at end of file diff --git a/src/main/java/envoy/server/data/Message.java b/src/main/java/envoy/server/data/Message.java index e5d1fce..6eceb52 100644 --- a/src/main/java/envoy/server/data/Message.java +++ b/src/main/java/envoy/server/data/Message.java @@ -66,7 +66,7 @@ public class Message { * @since Envoy Server Standalone v0.1-alpha */ public Message(envoy.data.Message message) { - PersistenceManager persMan = PersistenceManager.getPersistenceManager(); + PersistenceManager persMan = PersistenceManager.getInstance(); id = message.getId(); status = message.getStatus(); text = message.getText(); diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index 8943f52..12ac446 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -1,14 +1,17 @@ package envoy.server.database; +import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; +import envoy.data.User.UserStatus; import envoy.server.data.ConfigItem; import envoy.server.data.Message; import envoy.server.data.User; +import envoy.server.net.ConnectionManager; /** * Project: envoy-server-standalone
@@ -32,14 +35,21 @@ public class PersistenceManager { */ private PersistenceManager() { transaction.begin(); - Runtime.getRuntime().addShutdownHook(new Thread(() -> transaction.commit())); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + ConnectionManager.getInstance() + .getOnlineUsers() + .stream() + .map(this::getUserById) + .forEach(user -> { user.setStatus(UserStatus.OFFLINE); user.setLastSeen(new Date()); updateUser(user); }); + transaction.commit(); + })); } /** * @return the {@link PersistenceManager} singleton * @since Envoy Server Standalone v0.1-alpha */ - public static PersistenceManager getPersistenceManager() { return persistenceManager; } + public static PersistenceManager getInstance() { return persistenceManager; } /** * Adds a {@link User} to the database. diff --git a/src/main/java/envoy/server/ConnectionManager.java b/src/main/java/envoy/server/net/ConnectionManager.java similarity index 84% rename from src/main/java/envoy/server/ConnectionManager.java rename to src/main/java/envoy/server/net/ConnectionManager.java index 9dfd56b..9419ed3 100644 --- a/src/main/java/envoy/server/ConnectionManager.java +++ b/src/main/java/envoy/server/net/ConnectionManager.java @@ -1,10 +1,6 @@ -package envoy.server; +package envoy.server.net; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import com.jenkov.nioserver.ISocketIdListener; @@ -50,14 +46,14 @@ public class ConnectionManager implements ISocketIdListener { @Override public void socketCancelled(long socketId) { if (!pendingSockets.remove(socketId)) { - // notifying contacts of this users offline-going - envoy.server.data.User user = PersistenceManager.getPersistenceManager().getUserById(getUserIdBySocketId(socketId)); + // Notify contacts of this users offline-going + envoy.server.data.User user = PersistenceManager.getInstance().getUserById(getUserIdBySocketId(socketId)); user.setStatus(UserStatus.OFFLINE); user.setLastSeen(new Date()); UserStatusChangeProcessor.updateUserStatus(user); - // removing the socket - sockets.entrySet().stream().filter(e -> e.getValue() == socketId).forEach(e -> sockets.remove(e.getValue())); + // Remove the socket + sockets.entrySet().removeIf(e -> e.getValue() == socketId); } } @@ -98,4 +94,10 @@ public class ConnectionManager implements ISocketIdListener { * @since Envoy Server Standalone v0.1-alpha */ public boolean isOnline(long userId) { return sockets.containsKey(userId); } + + /** + * @return the userId of all users who are currently online + * @since Envoy Server Standalone v0.1-alpha + */ + public Set getOnlineUsers() { return sockets.keySet(); } } diff --git a/src/main/java/envoy/server/processors/ContactOperationProcessor.java b/src/main/java/envoy/server/processors/ContactOperationProcessor.java index 48ec6d9..0a79197 100644 --- a/src/main/java/envoy/server/processors/ContactOperationProcessor.java +++ b/src/main/java/envoy/server/processors/ContactOperationProcessor.java @@ -5,9 +5,9 @@ import java.util.Arrays; import envoy.data.Contacts; import envoy.event.ContactOperationEvent; -import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; +import envoy.server.net.ConnectionManager; import envoy.server.net.ObjectWriteProxy; /** @@ -30,11 +30,11 @@ public class ContactOperationProcessor implements ObjectProcessor { - private static final long ID_RANGE = 2; + private static final long ID_RANGE = 200; @Override public Class getInputClass() { return IdGeneratorRequest.class; } @@ -28,10 +28,10 @@ public class IdGeneratorRequestProcessor implements ObjectProcessor { - private PersistenceManager persistenceManager = PersistenceManager.getPersistenceManager(); - - @Override - public Class getInputClass() { return LoginCredentials.class; } + private final PersistenceManager persistenceManager = PersistenceManager.getInstance(); + private final ConnectionManager connectionManager = ConnectionManager.getInstance(); @Override public void process(LoginCredentials input, long socketId, ObjectWriteProxy writeProxy) throws IOException { UserStatusChangeProcessor.setWriteProxy(writeProxy); System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId)); - envoy.server.data.User user = getUser(input); + envoy.server.data.User user = getUser(input, socketId, writeProxy); // Not logged in successfully - if (user == null) return; - ConnectionManager.getInstance().registerUser(user.getId(), socketId); + if (user == null) { + System.out.println("Rejecting handshake on socket " + socketId); + return; + } + connectionManager.registerUser(user.getId(), socketId); - // notifies contacts of this users online-going and updates his status in the + // Notifies contacts of this users online-going and updates his status in the // database user.setStatus(UserStatus.ONLINE); UserStatusChangeProcessor.updateUserStatus(user); @@ -59,33 +63,86 @@ public class LoginCredentialProcessor implements ObjectProcessor pendingMessages = PersistenceManager.getPersistenceManager().getUnreadMessages(user); + List pendingMessages = PersistenceManager.getInstance().getUnreadMessages(user); for (Message msg : pendingMessages) { - System.out.println("Sending message " + msg.toCommonMessage().toString()); + System.out.println("Sending message " + msg.toCommonMessage()); writeProxy.write(socketId, msg.toCommonMessage()); msg.setReceivedDate(new Date()); msg.setStatus(MessageStatus.RECEIVED); - PersistenceManager.getPersistenceManager().updateMessage(msg); + PersistenceManager.getInstance().updateMessage(msg); } } - private envoy.server.data.User getUser(LoginCredentials credentials) { - envoy.server.data.User user; + @Override + public Class getInputClass() { return LoginCredentials.class; } - if (credentials.isRegistration()) { + private envoy.server.data.User getUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { + return credentials.isRegistration() ? newUser(credentials, socketId, writeProxy) : checkForExistingUser(credentials, socketId, writeProxy); + } + + /** + * @param credentials the input to evaluate + * @param socketId the socket ID at which the client performing the handshake + * is connected + * @param writeProxy the {@link ObjectWriteProxy} to use if login was not + * successful + * @return the database user matching the login credentials + * @throws IOException if sending the failed login back to the client failed + * @since Envoy Server Standalone v0.1-alpha + */ + private envoy.server.data.User checkForExistingUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { + try { + envoy.server.data.User user = persistenceManager.getUserByName(credentials.getIdentifier()); + + // Checking if user is already online + if (connectionManager.isOnline(user.getId())) { + writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.ALREADY_ONLINE)); + return null; + } + // Evaluating the correctness of the password hash + if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) { + writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD)); + return null; + } + return user; + } catch (NoResultException e) { + // Checking if user exists + writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_DOES_NOT_EXIST)); + } catch (InputMismatchException e) { + // Checking if the given password hash is correct + writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD)); + } + return null; + } + + /** + * @param credentials the credentials upon which to create the new {@link User} + * @param socketId the socketID at which the client performing the handshake + * is connected + * @param writeProxy the write proxy used to notify the client about handshake + * rejection + * @return the newly created {@link User} + * @throws IOException if sending the failed login back to the client failed + * @since Envoy Server Standalone v0.1-alpha + */ + private envoy.server.data.User newUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { + try { + // Checking that no user already has this identifier + PersistenceManager.getInstance().getUserByName(credentials.getIdentifier()); + // this code only gets executed if this user already exists + writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_EXISTS_ALREADY)); + return null; + } catch (NoResultException e) { + // Creation of a new user + envoy.server.data.User user; user = new envoy.server.data.User(); - user.setName(credentials.getName()); + user.setName(credentials.getIdentifier()); user.setLastSeen(new Date()); user.setStatus(User.UserStatus.ONLINE); user.setPasswordHash(credentials.getPasswordHash()); - persistenceManager.addUser(user); user.setContacts(new ArrayList<>()); - } else { - user = persistenceManager.getUserByName(credentials.getName()); - // TODO: Implement error when user does not exist - if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) // TODO: Wrong Password Response - return null; + persistenceManager.addUser(user); + return user; } - return user; } } diff --git a/src/main/java/envoy/server/processors/MessageProcessor.java b/src/main/java/envoy/server/processors/MessageProcessor.java index 0d9a7e6..a1e4f7c 100644 --- a/src/main/java/envoy/server/processors/MessageProcessor.java +++ b/src/main/java/envoy/server/processors/MessageProcessor.java @@ -5,9 +5,9 @@ import java.util.Date; import envoy.data.Message; import envoy.event.MessageStatusChangeEvent; -import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; +import envoy.server.net.ConnectionManager; import envoy.server.net.ObjectWriteProxy; /** @@ -37,11 +37,11 @@ public class MessageProcessor implements ObjectProcessor { // Update the message status to RECEIVED message.setReceivedDate(new Date()); message.nextStatus(); - writeProxy.write(connectionManager.getSocketId(message.getSenderId()), new MessageStatusChangeEvent(message)); + writeProxy.write(socketId, new MessageStatusChangeEvent(message)); } catch (IOException e) { System.err.println("Recipient online. Failed to send message" + message.getId()); e.printStackTrace(); } - PersistenceManager.getPersistenceManager().addMessage(new envoy.server.data.Message(message)); + PersistenceManager.getInstance().addMessage(new envoy.server.data.Message(message)); } } diff --git a/src/main/java/envoy/server/processors/MessageStatusChangeProcessor.java b/src/main/java/envoy/server/processors/MessageStatusChangeProcessor.java index 216e028..9949e43 100644 --- a/src/main/java/envoy/server/processors/MessageStatusChangeProcessor.java +++ b/src/main/java/envoy/server/processors/MessageStatusChangeProcessor.java @@ -5,9 +5,9 @@ import java.io.IOException; import envoy.data.Message.MessageStatus; import envoy.event.MessageStatusChangeEvent; import envoy.exception.EnvoyException; -import envoy.server.ConnectionManager; import envoy.server.ObjectProcessor; import envoy.server.database.PersistenceManager; +import envoy.server.net.ConnectionManager; import envoy.server.net.ObjectWriteProxy; /** @@ -32,7 +32,7 @@ public class MessageStatusChangeProcessor implements ObjectProcessor { private static ObjectWriteProxy writeProxy; - private static PersistenceManager persistenceManager = PersistenceManager.getPersistenceManager(); + private static PersistenceManager persistenceManager = PersistenceManager.getInstance(); @Override public Class getInputClass() { return UserStatusChangeEvent.class; } diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 4d937c9..10effe7 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -20,8 +20,6 @@ value="org.hibernate.dialect.PostgreSQL95Dialect" /> - -