]> git.mxchange.org Git - addressbook-mailer-ejb.git/blob - src/java/org/mxchange/jusercore/model/email_address/AddressbookEmailChangeSessionBean.java
Continued:
[addressbook-mailer-ejb.git] / src / java / org / mxchange / jusercore / model / email_address / AddressbookEmailChangeSessionBean.java
1 /*
2  * Copyright (C) 2016 Roland Haeder
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Affero General Public License as
6  * published by the Free Software Foundation, either version 3 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Affero General Public License for more details.
13  *
14  * You should have received a copy of the GNU Affero General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 package org.mxchange.jusercore.model.email_address;
18
19 import java.text.MessageFormat;
20 import java.util.GregorianCalendar;
21 import java.util.List;
22 import java.util.Locale;
23 import java.util.Properties;
24 import javax.annotation.PostConstruct;
25 import javax.ejb.EJB;
26 import javax.ejb.EJBException;
27 import javax.ejb.Stateless;
28 import javax.faces.FacesException;
29 import javax.jms.Connection;
30 import javax.jms.JMSException;
31 import javax.jms.MessageProducer;
32 import javax.jms.ObjectMessage;
33 import javax.jms.Queue;
34 import javax.jms.QueueConnectionFactory;
35 import javax.jms.Session;
36 import javax.mail.Address;
37 import javax.mail.internet.AddressException;
38 import javax.mail.internet.InternetAddress;
39 import javax.naming.Context;
40 import javax.naming.InitialContext;
41 import javax.naming.NamingException;
42 import javax.persistence.NoResultException;
43 import javax.persistence.Query;
44 import org.mxchange.jcoreee.database.BaseDatabaseBean;
45 import org.mxchange.jusercore.model.user.UserSessionBeanRemote;
46 import org.mxchange.jusercore.model.user.UserUtils;
47
48 /**
49  * A session bean for changing email addresses
50  * <p>
51  * @author Roland Haeder<roland@mxchange.org>
52  */
53 @Stateless (name = "emailchange", description = "A bean handling email changes")
54 public class AddressbookEmailChangeSessionBean extends BaseDatabaseBean implements EmailChangeSessionBeanRemote {
55
56         /**
57          * Serial number
58          */
59         private static final long serialVersionUID = 182_698_165_971_548L;
60
61         /**
62          * Connection
63          */
64         private Connection connection;
65
66         /**
67          * Object message
68          */
69         private ObjectMessage message;
70
71         /**
72          * Message producer
73          */
74         private MessageProducer messageProducer;
75
76         /**
77          * Mailer message queue
78          */
79         private Queue queue;
80
81         /**
82          * Session instance
83          */
84         private Session session;
85
86         /**
87          * User bean
88          */
89         @EJB
90         private UserSessionBeanRemote userBean;
91
92         /**
93          * Default constructor
94          */
95         public AddressbookEmailChangeSessionBean () {
96         }
97
98         @Override
99         @SuppressWarnings ("unchecked")
100         public List<String> allQueuedAddressesAsList () {
101                 // Trace message
102                 this.getLoggerBeanLocal().logTrace("allQueuedAddressesAsList: CALLED!"); //NOI18N
103
104                 // Get named query
105                 Query query = this.getEntityManager().createNamedQuery("AllEmailAddressChanges", List.class); //NOI18N
106
107                 // Get all entries
108                 List<String> emailAddresses = query.getResultList();
109
110                 // Trace message
111                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("allQueuedAddressesAsList: emailAddresses.size()={0} - EXIT!", emailAddresses.size())); //NOI18N
112
113                 // Return it
114                 return emailAddresses;
115         }
116
117         @Override
118         public void enqueueEmailAddressForChange (final ChangeableEmailAddress emailChange) {
119                 // Trace message
120                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("enqueueEmailAddressForChange: emailChange={0} - CALLED!", emailChange)); //NOI18N
121
122                 // Email address change should be valid
123                 if (null == emailChange) {
124                         // Abort here
125                         throw new NullPointerException("emailChange is null"); //NOI18N
126                 } else if (emailChange.getEmailChangeUser() == null) {
127                         // Throw NPE again
128                         throw new NullPointerException("emailChange.emailChangeUser is null"); //NOI18N
129                 } else if (emailChange.getEmailChangeUser().getUserId() == null) {
130                         // Throw NPE again
131                         throw new NullPointerException("emailChange.emailChangeUser.userId is null"); //NOI18N
132                 } else if (emailChange.getEmailChangeUser().getUserId() < 1) {
133                         // Not valid id
134                         throw new IllegalArgumentException(MessageFormat.format("emailChange.emailChangeUser.userId={0} is invalid.", emailChange.getEmailChangeUser().getUserId())); //NOI18N
135                 } else if (!this.userBean.ifUserExists(emailChange.getEmailChangeUser())) {
136                         // User does not exist
137                         throw new EJBException(MessageFormat.format("Email change with id {0} does not exist.", emailChange.getEmailChangeId())); //NOI18N
138                 } else if (emailChange.getEmailAddress().trim().isEmpty()) {
139                         // Email address is empty
140                         throw new IllegalArgumentException("emailChange.emaiLAddress is empty."); //NOI18N
141                 } else if (this.isEmailAddressEnqueued(emailChange.getEmailAddress())) {
142                         // Email address is already enqueued
143                         throw new EJBException(MessageFormat.format("Email address {0} is already enqueued.", emailChange.getEmailAddress())); //NOI18N
144                 }
145
146                 // The email change is not (yet) there, add secure hash and "created" timestamp
147                 emailChange.setEmailChangeCreated(new GregorianCalendar());
148                 this.generateSecureHash(emailChange);
149
150                 // Persist it
151                 //this.getEntityManager().persist(emailChange);
152
153                 // Prepare mail wrapper
154                 WrapableEmailDelivery emailWrapper = new EmailDeliveryWrapper();
155
156                 try {
157                         // Create email address and set
158                         Address emailAddress = new InternetAddress(emailChange.getEmailAddress());
159                         emailWrapper.setRecipient(emailAddress);
160                 } catch (final AddressException ex) {
161                         // Throw again
162                         throw new EJBException(ex);
163                 }
164
165                 // Set all values
166                 Properties variables = UserUtils.getAllUserFields(emailChange.getEmailChangeUser());
167
168                 // Set all
169                 // @TODO Get locale from user + language from message bundle
170                 emailWrapper.setLocale(Locale.GERMAN);
171                 emailWrapper.setSubjectLine("Email change");
172                 emailWrapper.setTemplateName("email_change"); //NOI18N
173                 emailWrapper.setTemplateVariables(variables);
174
175                 try {
176                         // Send out email change
177                         this.message.setObject(emailWrapper);
178
179                         // Send message
180                         this.sendMessage(this.message);
181                 } catch (final JMSException ex) {
182                         // Throw again
183                         throw new EJBException(ex);
184                 }
185
186                 // Trace message
187                 this.getLoggerBeanLocal().logTrace("enqueueEmailAddressForChange - EXIT!"); //NOI18N
188         }
189
190         /**
191          * Initialization of this bean
192          */
193         @PostConstruct
194         public void init () {
195                 // Trace message
196                 this.getLoggerBeanLocal().logTrace("init: CALLED!"); //NOI18N
197
198                 try {
199                         // Get initial context
200                         Context context = new InitialContext();
201
202                         // Get factory from JMS resource
203                         QueueConnectionFactory connectionFactory = (QueueConnectionFactory) context.lookup("jms/jlandingpage-queue-factory"); //NOI18N
204
205                         // Lookup queue
206                         this.queue = (Queue) context.lookup("jms/jlandingpage-email-queue"); //NOI18N
207
208                         // Create connection
209                         this.connection = connectionFactory.createConnection();
210
211                         // Init session instance
212                         this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
213
214                         // And message producer
215                         this.messageProducer = this.session.createProducer(this.queue);
216
217                         // Finally the message instance itself
218                         this.message = this.session.createObjectMessage();
219                 } catch (final NamingException | JMSException e) {
220                         // Continued to throw
221                         throw new FacesException(e);
222                 }
223         }
224
225         @Override
226         public boolean isEmailAddressEnqueued (final String emailAddress) {
227                 // Trace message
228                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("isEmailAddressEnqueued: emailAddress={0} - CALLED!", emailAddress)); //NOI18N
229
230                 // Create query instance
231                 Query query = this.getEntityManager().createNamedQuery("SearchEmailChangeByEmail"); //NOI18N
232
233                 // Add email address as parameter
234                 query.setParameter("email", emailAddress); //NOI18N
235
236                 // Initialize variable
237                 boolean isFound = false;
238
239                 // Try it
240                 try {
241                         // Try to get single result
242                         ChangeableEmailAddress dummy = (ChangeableEmailAddress) query.getSingleResult();
243
244                         // Found it
245                         isFound = true;
246                 } catch (final NoResultException ex) {
247                         // Log it
248                         this.getLoggerBeanLocal().logException(ex);
249                 }
250
251                 // Trace message
252                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("isEmailAddressEnqueued: isFound={0} - EXIT!", isFound)); //NOI18N
253
254                 // Return it
255                 return isFound;
256         }
257
258         @Override
259         public void updateEmailAddress (final ChangeableEmailAddress emailAddress) {
260                 // Trace message
261                 this.getLoggerBeanLocal().logTrace(MessageFormat.format("updateEmailAddress: emailAddress={0} - CALLED!", emailAddress)); //NOI18N
262
263                 // Email address change should be valid
264                 if (null == emailAddress) {
265                         // Abort here
266                         throw new NullPointerException("emailAddress is null"); //NOI18N
267                 } else if (emailAddress.getEmailChangeId() == null) {
268                         // Throw NPE again
269                         throw new NullPointerException("emailAddress.emailChangeId is null"); //NOI18N
270                 } else if (emailAddress.getEmailChangeId() < 1) {
271                         // Not valid
272                         throw new IllegalArgumentException(MessageFormat.format("emailAddress.emailChangeId={0} is not valid.", emailAddress.getEmailChangeId())); //NOI18N
273                 } else if (emailAddress.getEmailAddress().trim().isEmpty()) {
274                         // Email address is empty
275                         throw new IllegalArgumentException("emailAddress.emaiLAddress is empty."); //NOI18N
276                 } else if (!this.userBean.ifUserExists(emailAddress.getEmailChangeUser())) {
277                         // User does not exist
278                         throw new EJBException(MessageFormat.format("Email change with id {0} does not exist.", emailAddress.getEmailChangeId())); //NOI18N
279                 } else if (!this.isEmailAddressEnqueued(emailAddress.getEmailAddress())) {
280                         // Email address is not enqueued
281                         throw new EJBException(MessageFormat.format("Email address {0} is not enqueued.", emailAddress.getEmailAddress())); //NOI18N
282                 }
283
284                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
285         }
286
287         /**
288          * Generates a secure, unique hash for given email address change. This
289          * requires to check if the hash is really not there.
290          * <p>
291          * @param emailAddress Email address change
292          */
293         private void generateSecureHash (final ChangeableEmailAddress emailAddress) {
294                 // Email address change should be valid
295                 if (null == emailAddress) {
296                         // Abort here
297                         throw new NullPointerException("emailAddress is null"); //NOI18N
298                 } else if (emailAddress.getEmailAddress().trim().isEmpty()) {
299                         // Email address is empty
300                         throw new IllegalArgumentException("emailAddress.emaiLAddress is empty."); //NOI18N
301                 }
302
303                 // Initialize loop with null
304                 String hash = null;
305
306                 // Default is not used
307                 boolean isUsed = true;
308
309                 // Search for free hash
310                 while (isUsed) {
311                         // Generate hash, there is already in UserUtils a nice method that can be used for this purpose.
312                         hash = UserUtils.encryptPassword(String.format("%s:%s", emailAddress.getEmailAddress(), emailAddress.toString())); //NOI18N
313
314                         // The hash *may* be unique, better test it
315                         Query query = this.getEntityManager().createNamedQuery("SearchEmailChangeByHash", EmailAddressChange.class); //NOI18N
316
317                         // Set hash as parameter
318                         query.setParameter("hash", hash); //NOI18N
319
320                         // Try to get single result
321                         try {
322                                 // Get single result
323                                 ChangeableEmailAddress dummy = (ChangeableEmailAddress) query.getSingleResult();
324                         } catch (final NoResultException ex) {
325                                 // Not found
326                                 isUsed = false;
327                         }
328                 }
329
330                 // hash should not be null and set
331                 assert (hash != null) : "hash is null"; //NOI18N
332                 assert (!hash.isEmpty()) : "hash is empty"; //NOI18N
333
334                 // Set it in email change
335                 emailAddress.setEmailChangeHash(hash);
336         }
337
338         /**
339          * Sends given message to configured queue
340          * <p>
341          * @param message Message to send
342          * <p>
343          * @throws JMSException if something went wrong
344          */
345         private void sendMessage (final ObjectMessage message) throws JMSException {
346                 // The parameter should be valid
347                 if (null == message) {
348                         // Throw NPE
349                         throw new NullPointerException("message is null"); //NOI18N
350                 }
351
352                 // Send it
353                 this.messageProducer.send(message);
354         }
355
356 }