From 2729dedac3d61408e3b8ee3ced6249572458c4ed Mon Sep 17 00:00:00 2001 From: Roland Haeder Date: Sun, 13 Mar 2016 18:31:20 +0100 Subject: [PATCH] Continued with email delivery: - Added EJB for email change mail delivery - added needed jar(s) - updated project files --- lib/jmailer-ee.jar | Bin 0 -> 8085 bytes nbproject/build-impl.xml | 10 +- nbproject/genfiles.properties | 4 +- nbproject/project.properties | 3 + nbproject/project.xml | 1 + .../AddressbookEmailChangeSessionBean.java | 178 ++++++++++++++++-- 6 files changed, 177 insertions(+), 19 deletions(-) create mode 100644 lib/jmailer-ee.jar diff --git a/lib/jmailer-ee.jar b/lib/jmailer-ee.jar new file mode 100644 index 0000000000000000000000000000000000000000..ec343a7cc8b5b2bfa7d1581a51a80d6435b9a38e GIT binary patch literal 8085 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 + @@ -854,10 +855,11 @@ exists or setup the property manually. For example like this: + - + @@ -867,8 +869,9 @@ exists or setup the property manually. For example like this: - - + + + @@ -881,6 +884,7 @@ exists or setup the property manually. For example like this: + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index 4f6f540..566ff5d 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -3,6 +3,6 @@ build.xml.script.CRC32=7d41e0fd build.xml.stylesheet.CRC32=5910fda3@1.51.1 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=578b807a -nbproject/build-impl.xml.script.CRC32=34424534 +nbproject/build-impl.xml.data.CRC32=4a04b58e +nbproject/build-impl.xml.script.CRC32=5b2dfdcd nbproject/build-impl.xml.stylesheet.CRC32=6096d939@1.55.1 diff --git a/nbproject/project.properties b/nbproject/project.properties index 2fb4f97..de73a6c 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -27,6 +27,7 @@ file.reference.jcore-logger-lib.jar=lib/jcore-logger-lib.jar file.reference.jcore.jar=lib/jcore.jar file.reference.jcoreee.jar=lib/jcoreee.jar file.reference.jcountry-core.jar=lib/jcountry-core.jar +file.reference.jmailer-ee.jar=lib/jmailer-ee.jar file.reference.jphone-core.jar=lib/jphone-core.jar file.reference.juser-core.jar=lib/juser-core.jar file.reference.juser-lib.jar=lib/juser-lib.jar @@ -54,6 +55,7 @@ javac.classpath=\ ${file.reference.jcontacts-business-core.jar}:\ ${file.reference.juser-core.jar}:\ ${file.reference.juser-lib.jar}:\ + ${file.reference.jmailer-ee.jar}:\ ${reference.addressbook-lib.jar}:\ ${reference.juser-core.jar} javac.compilerargs=-Xlint:unchecked -Xlint:deprecation @@ -101,6 +103,7 @@ source.reference.jcore-logger-lib.jar=../jcore-logger-lib/src/ source.reference.jcore.jar=../jcore/src/ source.reference.jcoreee.jar=../jcoreee/src/ source.reference.jcountry-core.jar=../jcountry-core/src/ +source.reference.jmailer-ee.jar=../jmailer-ee/src/ source.reference.jphone-core.jar=../jphone-core/src/ source.reference.juser-core.jar=../juser-core/src/ source.reference.juser-lib.jar=../juser-lib/src/ diff --git a/nbproject/project.xml b/nbproject/project.xml index 8d34321..098497a 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -14,6 +14,7 @@ file.reference.jcontacts-business-core.jar file.reference.juser-core.jar file.reference.juser-lib.jar + file.reference.jmailer-ee.jar reference.addressbook-lib.jar reference.juser-core.jar diff --git a/src/java/org/mxchange/jusercore/model/email_address/AddressbookEmailChangeSessionBean.java b/src/java/org/mxchange/jusercore/model/email_address/AddressbookEmailChangeSessionBean.java index df02c0d..88d2c6e 100644 --- a/src/java/org/mxchange/jusercore/model/email_address/AddressbookEmailChangeSessionBean.java +++ b/src/java/org/mxchange/jusercore/model/email_address/AddressbookEmailChangeSessionBean.java @@ -17,14 +17,30 @@ package org.mxchange.jusercore.model.email_address; import java.text.MessageFormat; +import java.util.GregorianCalendar; import java.util.List; +import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.ejb.EJBException; import javax.ejb.Stateless; +import javax.faces.FacesException; +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnectionFactory; +import javax.jms.Session; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; import javax.persistence.NoResultException; import javax.persistence.Query; import org.mxchange.jcoreee.database.BaseDatabaseBean; +import org.mxchange.jmailee.model.delivery.DeliverableEmail; +import org.mxchange.jmailee.model.delivery.Mailer; import org.mxchange.jusercore.model.user.UserSessionBeanRemote; +import org.mxchange.jusercore.model.user.UserUtils; /** * A session bean for changing email addresses @@ -39,6 +55,31 @@ public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implemen */ private static final long serialVersionUID = 182_698_165_971_548L; + /** + * Connection + */ + private Connection connection; + + /** + * Object message + */ + private ObjectMessage message; + + /** + * Message producer + */ + private MessageProducer messageProducer; + + /** + * Mailer message queue + */ + private Queue queue; + + /** + * Session instance + */ + private Session session; + /** * User bean */ @@ -58,7 +99,7 @@ public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implemen this.getLoggerBeanLocal().logTrace("allQueuedAddressesAsList: CALLED!"); //NOI18N // Get named query - Query query = this.getEntityManager().createNamedQuery("AllEmailAddressChanges", List.class); + Query query = this.getEntityManager().createNamedQuery("AllEmailAddressChanges", List.class); //NOI18N // Get all entries List emailAddresses = query.getResultList(); @@ -71,23 +112,78 @@ public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implemen } @Override - public void enqueueEmailAddressForChange (final ChangeableEmailAddress emailAddress) { + public void enqueueEmailAddressForChange (final ChangeableEmailAddress emailChange) { // Trace message - this.getLoggerBeanLocal().logTrace(MessageFormat.format("enqueueEmailAddressForChange: emailAddress={0} - CALLED!", emailAddress)); + this.getLoggerBeanLocal().logTrace(MessageFormat.format("enqueueEmailAddressForChange: emailChange={0} - CALLED!", emailChange)); //NOI18N - // user should not be null - if (null == emailAddress) { + // Email address change should be valid + if (null == emailChange) { // Abort here - throw new NullPointerException("emailAddress is null"); //NOI18N - } else if (!this.userBean.ifUserExists(emailAddress.getEmailChangeUser())) { + throw new NullPointerException("emailChange is null"); //NOI18N + } else if (emailChange.getEmailChangeUser() == null) { + // Throw NPE again + throw new NullPointerException("emailChange.emailChangeUser is null"); //NOI18N + } else if (emailChange.getEmailChangeUser().getUserId() == null) { + // Throw NPE again + throw new NullPointerException("emailChange.emailChangeUser.userId is null"); //NOI18N + } else if (emailChange.getEmailChangeUser().getUserId() < 1) { + // Not valid id + throw new IllegalArgumentException(MessageFormat.format("emailChange.emailChangeUser.userId={0} is invalid.", emailChange.getEmailChangeUser().getUserId())); //NOI18N + } else if (!this.userBean.ifUserExists(emailChange.getEmailChangeUser())) { // User does not exist - throw new EJBException(MessageFormat.format("Email change with id {0} does not exist.", emailAddress.getEmailChangeId())); //NOI18N - } else if (this.isEmailAddressEnqueued(emailAddress.getEmailAddress())) { + throw new EJBException(MessageFormat.format("Email change with id {0} does not exist.", emailChange.getEmailChangeId())); //NOI18N + } else if (emailChange.getEmailAddress().trim().isEmpty()) { + // Email address is empty + throw new IllegalArgumentException("emailChange.emaiLAddress is empty."); //NOI18N + } else if (this.isEmailAddressEnqueued(emailChange.getEmailAddress())) { // Email address is already enqueued - throw new EJBException(MessageFormat.format("Email address {0} is already enqueued.", emailAddress.getEmailAddress())); + throw new EJBException(MessageFormat.format("Email address {0} is already enqueued.", emailChange.getEmailAddress())); //NOI18N } - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + // The email change is not (yet) there, add secure hash and "created" timestamp + emailChange.setEmailChangeCreated(new GregorianCalendar()); + this.generateSecureHash(emailChange); + + // Persist it + //this.getEntityManager().persist(emailChange); + + // Get mailer instance + DeliverableEmail mailer = new Mailer(); + + // Send out email change + mailer.sendEmailChangeMail(this.messageProducer, this.message, emailChange); + } + + /** + * Initialization of this bean + */ + @PostConstruct + public void init () { + try { + // Get initial context + Context context = new InitialContext(); + + // Get factory from JMS resource + QueueConnectionFactory connectionFactory = (QueueConnectionFactory) context.lookup("jms/addressbook-queue-factory"); //NOI18N + + // Lookup queue + this.queue = (Queue) context.lookup("jms/addressbook-email-queue"); //NOI18N + + // Create connection + this.connection = connectionFactory.createConnection(); + + // Init session instance + this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // And message producer + this.messageProducer = this.session.createProducer(this.queue); + + // Finally the message instance itself + this.message = this.session.createObjectMessage(); + } catch (final NamingException | JMSException e) { + // Continued to throw + throw new FacesException(e); + } } @Override @@ -126,9 +222,9 @@ public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implemen @Override public void updateEmailAddress (final ChangeableEmailAddress emailAddress) { // Trace message - this.getLoggerBeanLocal().logTrace(MessageFormat.format("updateEmailAddress: emailAddress={0} - CALLED!", emailAddress)); + this.getLoggerBeanLocal().logTrace(MessageFormat.format("updateEmailAddress: emailAddress={0} - CALLED!", emailAddress)); //NOI18N - // user should not be null + // Email address change should be valid if (null == emailAddress) { // Abort here throw new NullPointerException("emailAddress is null"); //NOI18N @@ -138,15 +234,69 @@ public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implemen } else if (emailAddress.getEmailChangeId() < 1) { // Not valid throw new IllegalArgumentException(MessageFormat.format("emailAddress.emailChangeId={0} is not valid.", emailAddress.getEmailChangeId())); //NOI18N + } else if (emailAddress.getEmailAddress().trim().isEmpty()) { + // Email address is empty + throw new IllegalArgumentException("emailAddress.emaiLAddress is empty."); //NOI18N } else if (!this.userBean.ifUserExists(emailAddress.getEmailChangeUser())) { // User does not exist throw new EJBException(MessageFormat.format("Email change with id {0} does not exist.", emailAddress.getEmailChangeId())); //NOI18N } else if (!this.isEmailAddressEnqueued(emailAddress.getEmailAddress())) { // Email address is not enqueued - throw new EJBException(MessageFormat.format("Email address {0} is not enqueued.", emailAddress.getEmailAddress())); + throw new EJBException(MessageFormat.format("Email address {0} is not enqueued.", emailAddress.getEmailAddress())); //NOI18N } throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } + /** + * Generates a secure, unique hash for given email address change. This + * requires to check if the hash is really not there. + *

+ * @param emailAddress Email address change + */ + private void generateSecureHash (final ChangeableEmailAddress emailAddress) { + // Email address change should be valid + if (null == emailAddress) { + // Abort here + throw new NullPointerException("emailAddress is null"); //NOI18N + } else if (emailAddress.getEmailAddress().trim().isEmpty()) { + // Email address is empty + throw new IllegalArgumentException("emailAddress.emaiLAddress is empty."); //NOI18N + } + + // Initialize loop with null + String hash = null; + + // Default is not used + boolean isUsed = true; + + // Search for free hash + while (isUsed) { + // Generate hash, there is already in UserUtils a nice method that can be used for this purpose. + hash = UserUtils.encryptPassword(String.format("%s:%s", emailAddress.getEmailAddress(), emailAddress.toString())); //NOI18N + + // The hash *may* be unique, better test it + Query query = this.getEntityManager().createNamedQuery("SearchEmailChangeByHash", EmailAddressChange.class); //NOI18N + + // Set hash as parameter + query.setParameter("hash", hash); //NOI18N + + // Try to get single result + try { + // Get single result + ChangeableEmailAddress dummy = (ChangeableEmailAddress) query.getSingleResult(); + } catch (final NoResultException ex) { + // Not found + isUsed = false; + } + } + + // hash should not be null and set + assert (hash != null) : "hash is null"; //NOI18N + assert (!hash.isEmpty()) : "hash is empty"; //NOI18N + + // Set it in email change + emailAddress.setEmailChangeHash(hash); + } + } -- 2.39.5