View Javadoc
1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.services.implementations;
20  
21  import org.apache.commons.lang.StringUtils;
22  import org.apache.log4j.Logger;
23  import org.itracker.core.resources.ITrackerResources;
24  import org.itracker.model.*;
25  import org.itracker.model.Notification.Role;
26  import org.itracker.model.Notification.Type;
27  import org.itracker.model.util.IssueUtilities;
28  import org.itracker.model.util.ProjectUtilities;
29  import org.itracker.model.util.UserUtilities;
30  import org.itracker.persistence.dao.IssueActivityDAO;
31  import org.itracker.persistence.dao.IssueDAO;
32  import org.itracker.persistence.dao.NotificationDAO;
33  import org.itracker.services.EmailService;
34  import org.itracker.services.IssueService;
35  import org.itracker.services.NotificationService;
36  import org.itracker.services.ProjectService;
37  import org.itracker.util.HTMLUtilities;
38  import org.springframework.beans.BeansException;
39  import org.springframework.context.ApplicationContext;
40  import org.springframework.context.ApplicationContextAware;
41  
42  import javax.mail.internet.InternetAddress;
43  import java.net.MalformedURLException;
44  import java.util.*;
45  
46  public class NotificationServiceImpl implements NotificationService, ApplicationContextAware {
47      public static final Integer DEFAULT_ISSUE_AGE = 30;
48  
49  
50      private EmailService emailService;
51      private NotificationDAO notificationDao;
52      private ProjectService projectService;
53      private IssueActivityDAO issueActivityDao;
54      private IssueDAO issueDao;
55  
56  
57      private String issueServiceName;
58  
59      private static final Logger logger = Logger
60              .getLogger(NotificationServiceImpl.class);
61      private IssueService issueService;
62      private ApplicationContext applicationContext;
63  
64      public NotificationServiceImpl() {
65  
66          this.emailService = null;
67          this.projectService = null;
68          this.notificationDao = null;
69      }
70  
71      @Override
72      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
73          this.applicationContext = applicationContext;
74      }
75  
76      public NotificationServiceImpl(EmailService emailService,
77                                     ProjectService projectService, NotificationDAO notificationDao, IssueActivityDAO issueActivityDao, IssueDAO issueDao, IssueService issueService) {
78          this();
79          this.setEmailService(emailService);
80          this.setProjectService(projectService);
81          this.setNotificationDao(notificationDao);
82          this.setIssueActivityDao(issueActivityDao);
83          this.setIssueDao(issueDao);
84          this.setIssueService(issueService);
85      }
86  
87      public void sendNotification(Notification notification, Type type,
88                                   String url) {
89  
90          if (logger.isDebugEnabled()) {
91              logger.debug("sendNotification: called with notification: "
92                      + notification + ", type: " + url + ", url: " + url);
93          }
94          if (null == notification) {
95              throw new IllegalArgumentException("notification must not be null");
96          }
97          if (null == this.emailService || null == this.notificationDao) {
98              throw new IllegalStateException("service not initialized yet");
99          }
100         if (type == Type.SELF_REGISTER) {
101             this.handleSelfRegistrationNotification(notification.getUser()
102                     .getLogin(), notification.getUser().getEmailAddress(), notification.getUser().getPreferences().getUserLocale(), url);
103         } else {
104             handleIssueNotification(notification.getIssue(), type, url);
105 
106         }
107 
108     }
109 
110     public void sendNotification(Issue issue, Type type, String baseURL) {
111         if (logger.isDebugEnabled()) {
112             logger.debug("sendNotification: called with issue: " + issue
113                     + ", type: " + type + ", baseURL: " + baseURL);
114         }
115         handleIssueNotification(issue, type, baseURL);
116 
117     }
118 
119     public void setEmailService(EmailService emailService) {
120 
121         if (null == emailService)
122             throw new IllegalArgumentException("email service must not be null");
123 
124         if (null != this.emailService) {
125             throw new IllegalStateException("email service allready set");
126         }
127         this.emailService = emailService;
128 
129     }
130 
131 
132     private void handleSelfRegistrationNotification(String login,
133                                                     InternetAddress toAddress, String locale, String url) {
134         if (logger.isDebugEnabled()) {
135             logger
136                     .debug("handleSelfRegistrationNotification: called with login: "
137                             + login
138                             + ", toAddress"
139                             + toAddress
140                             + ", url: "
141                             + url);
142         }
143         try {
144 
145             if (toAddress != null && !"".equals(toAddress.getAddress())) {
146                 String subject = ITrackerResources
147                         .getString("itracker.email.selfreg.subject", locale);
148                 String msgText = ITrackerResources.getString(
149                         "itracker.email.selfreg.body", locale, new Object[]{login,
150                                 url + "/login.do"});
151                 emailService.sendEmail(toAddress, subject, msgText);
152             } else {
153                 throw new IllegalArgumentException(
154                         "To-address must be set for self registration notification.");
155             }
156         } catch (RuntimeException e) {
157             logger.error("failed to handle self registration notification for "
158                     + toAddress, e);
159             throw e;
160         }
161     }
162 
163     /**
164      * Method for internal sending of a notification of specific type.
165      */
166     private void handleIssueNotification(Issue issue, Type type, String url) {
167 
168         if (logger.isDebugEnabled()) {
169             logger.debug("handleIssueNotification: called with issue: " + issue
170                     + ", type: " + type + "url: " + url);
171         }
172         this.handleLocalizedIssueNotification(issue, type, url, null, null);
173     }
174 
175 
176     /**
177      * Method for internal sending of a notification of specific type.
178      */
179     private void handleLocalizedIssueNotification(final Issue issue, final Type type, final String url,
180                                                   final InternetAddress[] recipients, Integer lastModifiedDays) {
181         try {
182 
183             if (logger.isDebugEnabled()) {
184                 logger
185                         .debug("handleLocalizedIssueNotification: running as thread, called with issue: "
186                                 + issue
187                                 + ", type: "
188                                 + type
189                                 + "url: "
190                                 + url
191                                 + ", recipients: "
192                                 + (null == recipients ? "<null>" : String
193                                 .valueOf(Arrays.asList(recipients)))
194                                 + ", lastModifiedDays: " + lastModifiedDays);
195             }
196 
197             final Integer notModifiedSince;
198 
199             if (lastModifiedDays == null || lastModifiedDays < 0) {
200                 notModifiedSince = DEFAULT_ISSUE_AGE;
201             } else {
202                 notModifiedSince = lastModifiedDays;
203             }
204 
205             try {
206                 if (logger.isDebugEnabled()) {
207                     logger
208                             .debug("handleLocalizedIssueNotification.run: running as thread, called with issue: "
209                                     + issue
210                                     + ", type: "
211                                     + type
212                                     + "url: "
213                                     + url
214                                     + ", recipients: "
215                                     + (null == recipients ? "<null>" : String
216                                     .valueOf(Arrays.asList(recipients)))
217                                     + ", notModifiedSince: " + notModifiedSince);
218                 }
219                 final List<Notification> notifications;
220                 if (issue == null) {
221                     logger
222                             .warn("handleLocalizedIssueNotification: issue was null. Notification will not be handled");
223                     return;
224                 }
225                 Map<InternetAddress, Locale> localeMapping;
226 
227                 if (recipients == null) {
228                     notifications = this.getIssueNotifications(issue);
229 
230                     localeMapping = new Hashtable<>(notifications.size());
231                     Iterator<Notification> it = notifications.iterator();
232                     User currentUser;
233                     while (it.hasNext()) {
234                         currentUser = it.next().getUser();
235                         if (null != currentUser
236                                 && null != currentUser.getEmailAddress()
237                                 && null != currentUser.getEmail()
238                                 && (!localeMapping.keySet()
239                                 .contains(currentUser.getEmailAddress()))) {
240 
241                             try {
242                                 localeMapping.put(currentUser.getEmailAddress(), ITrackerResources.getLocale(currentUser.getPreferences().getUserLocale()));
243                             } catch (RuntimeException re) {
244                                 localeMapping.put(currentUser.getEmailAddress(), ITrackerResources.getLocale());
245                             }
246                         }
247                     }
248                 } else {
249                     localeMapping = new Hashtable<>(1);
250                     Locale locale = ITrackerResources.getLocale();
251                     for (InternetAddress internetAddress : Arrays.asList(recipients)) {
252                         localeMapping.put(internetAddress, locale);
253                     }
254                 }
255 
256                 this.handleNotification(issue, type, localeMapping, url, notModifiedSince);
257             } catch (Exception e) {
258                 logger.error("run: failed to process notification", e);
259             }
260 
261         } catch (Exception e) {
262             logger
263                     .error(
264                             "handleLocalizedIssueNotification: unexpected exception caught, throwing runtime exception",
265                             e);
266             throw new RuntimeException(e);
267         }
268     }
269 
270     @Override
271     public void sendReminder(Issue issue, User user, String baseURL, int issueAge) {
272         Map<InternetAddress, Locale> recipient = new HashMap<>(1);
273         recipient.put(user.getEmailAddress(), ITrackerResources.getLocale(user.getPreferences().getUserLocale()));
274         handleNotification(issue, Type.ISSUE_REMINDER, recipient, baseURL, issueAge);
275     }
276 
277     /**
278      * Send notifications to mapped addresses by locale.
279      */
280     private void handleNotification(Issue issue, Type type, Map<InternetAddress, Locale> recipientsLocales, final String url, Integer notModifiedSince) {
281         Set<InternetAddress> recipients;
282         Map<Locale, Set<InternetAddress>> localeRecipients = new Hashtable<>();
283 
284         List<Component> components = issue.getComponents();
285 
286         List<IssueActivity> activity = getIssueService().getIssueActivity(
287                 issue.getId(), false);
288 
289         IssueHistory history;
290         history = getIssueService().getLastIssueHistory(issue.getId());
291         StringBuilder recipientsString = new StringBuilder();
292 
293         if (logger.isDebugEnabled() && null != history) {
294             logger.debug("handleIssueNotification: got most recent history: "
295                     + history
296                     + " ("
297                     + history.getDescription()
298                     + ")");
299         }
300 
301         for (InternetAddress internetAddress : recipientsLocales.keySet()) {
302             recipientsString.append("\n  ");
303             recipientsString.append(internetAddress.getPersonal());
304 
305             if (localeRecipients.keySet().contains(recipientsLocales.get(internetAddress))) {
306                 localeRecipients.get(recipientsLocales.get(internetAddress)).add(internetAddress);
307             } else {
308                 Set<InternetAddress> addresses = new HashSet<>();
309                 addresses.add(internetAddress);
310                 localeRecipients.put(recipientsLocales.get(internetAddress), addresses);
311             }
312         }
313 
314         Iterator<Locale> localesIt = localeRecipients.keySet().iterator();
315         try {
316             while (localesIt.hasNext()) {
317                 Locale currentLocale = localesIt.next();
318                 recipients = localeRecipients.get(currentLocale);
319 
320 
321                 if (recipients.size() > 0) {
322                     String subject;
323                     if (type == Type.CREATED) {
324                         subject = ITrackerResources.getString(
325                                 "itracker.email.issue.subject.created",
326                                 currentLocale,
327                                 new Object[]{issue.getId(),
328                                         issue.getProject().getName()});
329                     } else if (type == Type.ASSIGNED) {
330                         subject = ITrackerResources.getString(
331                                 "itracker.email.issue.subject.assigned",
332                                 currentLocale,
333                                 new Object[]{issue.getId(),
334                                         issue.getProject().getName()});
335                     } else if (type == Type.CLOSED) {
336                         subject = ITrackerResources.getString(
337                                 "itracker.email.issue.subject.closed",
338                                 currentLocale,
339                                 new Object[]{issue.getId(),
340                                         issue.getProject().getName()});
341                     } else if (type == Type.ISSUE_REMINDER) {
342                         subject = ITrackerResources.getString(
343                                 "itracker.email.issue.subject.reminder",
344                                 currentLocale,
345                                 new Object[]{issue.getId(),
346                                         issue.getProject().getName(),
347                                         notModifiedSince});
348                     } else {
349                         subject = ITrackerResources.getString(
350                                 "itracker.email.issue.subject.updated",
351                                 currentLocale,
352                                 new Object[]{issue.getId(),
353                                         issue.getProject().getName()});
354                     }
355 
356                     String activityString;
357                     String componentString = "";
358                     StringBuilder sb = new StringBuilder();
359                     if (activity.size() == 0) {
360                         sb.append("-");
361                     } else {
362                         for (IssueActivity anActivity : activity) {
363                             sb.append("\n ").append(
364                                     IssueUtilities.getActivityName(anActivity
365                                             .getActivityType(), currentLocale)).append(": ").append(
366                                     anActivity.getDescription());
367 
368                         }
369                     }
370                     sb.append("\n");
371                     activityString = sb.toString();
372                     for (int i = 0; i < components.size(); i++) {
373                         componentString += (i != 0 ? ", " : "")
374                                 + components.get(i).getName();
375                     }
376 
377                     final String owner = IssueUtilities.getOwnerName(issue.getOwner(), currentLocale);
378                     final User hUser = null == history ? null : history.getUser();
379                     final String historyUser = (null != hUser) ? hUser.getFullName()
380                             : ITrackerResources.getString("itracker.web.generic.notapplicable", currentLocale);
381 
382                     final String historyText = (history == null ? "-"
383                             : HTMLUtilities
384                             .removeMarkup(history
385                                     .getDescription()));
386                     final String status =
387                             IssueUtilities.getStatusName(issue
388                                     .getStatus(), currentLocale);
389                     final String msgText;
390                     if (type == Type.ISSUE_REMINDER) {
391                         msgText = ITrackerResources
392                                 .getString(
393                                         "itracker.email.issue.body.reminder",
394                                         currentLocale,
395                                         new Object[]{
396                                                 IssueUtilities.getIssueURL(issue, url).toExternalForm(),
397                                                 issue.getProject().getName(),
398                                                 issue.getDescription(),
399                                                 IssueUtilities.getStatusName(issue
400                                                         .getStatus(), currentLocale),
401                                                 IssueUtilities
402                                                         .getSeverityName(issue
403                                                         .getSeverity(), currentLocale),
404                                                 owner,
405                                                 componentString,
406                                                 historyUser,
407                                                 historyText,
408                                                 notModifiedSince,
409                                                 activityString});
410                     } else {
411                         String resolution = (issue.getResolution() == null ? ""
412                                 : issue.getResolution());
413                         if (!resolution.equals("")
414                                 && ProjectUtilities
415                                 .hasOption(
416                                         ProjectUtilities.OPTION_PREDEFINED_RESOLUTIONS,
417                                         issue.getProject().getOptions())) {
418                             resolution = IssueUtilities.getResolutionName(
419                                     resolution, currentLocale);
420                         }
421                         msgText = ITrackerResources
422                                 .getString(
423                                         "itracker.email.issue.body."
424                                                 + (type == Type.CREATED ? "created" : "standard"),
425                                         currentLocale,
426                                         new Object[]{
427                                                 url + "/module-projects/view_issue.do?id=" + issue.getId(),
428                                                 issue.getProject().getName(),
429                                                 issue.getDescription(),
430                                                 status,
431                                                 resolution,
432                                                 IssueUtilities
433                                                         .getSeverityName(issue
434                                                         .getSeverity(), currentLocale),
435                                                 owner,
436                                                 componentString,
437                                                 historyUser,
438                                                 historyText,
439                                                 activityString,
440                                                 recipientsString});
441                     }
442 
443                     if (logger.isInfoEnabled()) {
444                         logger.info("handleNotification: sending notification for " + issue + " (" + type + ") to " + currentLocale + "-users (" + recipients + ")");
445 
446                     }
447                     for (InternetAddress iadr : recipients) {
448                         emailService.sendEmail(iadr, subject, msgText);
449                     }
450 
451                     if (logger.isDebugEnabled()) {
452                         logger.debug("handleNotification: sent notification for " + issue
453                                 + ": " + subject + "\n  " + msgText);
454                     }
455                 }
456 
457                 updateIssueActivityNotification(issue, true);
458                 if (logger.isDebugEnabled()) {
459                     logger.debug("handleNotification: sent notification for locales " + localeRecipients.keySet() + " recipients: " + localeRecipients.values());
460                 }
461             }
462         } catch (RuntimeException e) {
463             logger.error("handleNotification: failed to notify: " + issue + " (locales: " + localeRecipients.keySet() + ")", e);
464 
465         } catch (MalformedURLException e) {
466             logger.error("handleNotification: URL was not well-formed", e);
467         }
468 
469 
470     }
471 
472     private IssueService getIssueService() {
473         if (null == issueService) {
474             setIssueService((IssueService) applicationContext.getBean("issueService"));
475         }
476 
477         return issueService;
478     }
479 
480     public void setIssueService(IssueService issueService) {
481         this.issueService = issueService;
482     }
483 
484     public void updateIssueActivityNotification(Issue issue,
485                                                 Boolean notificationSent) {
486         if (logger.isDebugEnabled()) {
487             logger.debug("updateIssueActivityNotification: called with "
488                     + issue + ", notificationSent: " + notificationSent);
489         }
490 
491         Collection<IssueActivity> activities = getIssueActivityDao()
492                 .findByIssueId(issue.getId());
493         for (IssueActivity activity : activities) {
494             activity.setNotificationSent(notificationSent);
495         }
496     }
497 
498     /**
499      */
500     public boolean addIssueNotification(Notification notification) {
501         if (logger.isDebugEnabled()) {
502             logger.debug("addIssueNotification: called with notification: "
503                     + notification);
504         }
505         Issue issue = notification.getIssue();
506         if (!issue.getNotifications().contains(notification)) {
507             if (notification.getCreateDate() == null) {
508                 notification.setCreateDate(new Date());
509             }
510             if (notification.getLastModifiedDate() == null) {
511                 notification.setLastModifiedDate(new Date());
512             }
513 
514             getNotificationDao().save(notification);
515 
516             issue.getNotifications().add(notification);
517             getIssueDao().merge(issue);
518 
519             return true;
520         }
521         if (logger.isDebugEnabled()) {
522             logger.debug("addIssueNotification: attempted to add duplicate notification " + notification + " for issue: " + issue);
523         }
524         return false;
525     }
526 
527     /**
528      *
529      */
530     public List<Notification> getIssueNotifications(Issue issue,
531                                                     boolean primaryOnly, boolean activeOnly) {
532         if (logger.isDebugEnabled()) {
533             logger.debug("getIssueNotifications: called with issue: " + issue
534                     + ", primaryOnly: " + primaryOnly + ", activeOnly: "
535                     + activeOnly);
536         }
537         List<Notification> issueNotifications = new ArrayList<>();
538         if (issue == null) {
539             logger.warn("getIssueNotifications: no issue, throwing exception");
540             throw new IllegalArgumentException("issue must not be null");
541         }
542         if (!primaryOnly) {
543             List<Notification> notifications = getNotificationDao()
544                     .findByIssueId(issue.getId());
545 
546             for (Notification notification : notifications) {
547                 User notificationUser = notification.getUser();
548                 if (!activeOnly
549                         || notificationUser.getStatus() == UserUtilities.STATUS_ACTIVE) {
550                     issueNotifications.add(notification);
551                 }
552             }
553         }
554 
555         // Now add in other notifications like owner, creator, project owners,
556         // etc...
557 
558         boolean hasOwner = false;
559         if (issue.getOwner() != null) {
560             User ownerModel = issue.getOwner();
561 
562             if (ownerModel != null
563                     && (!activeOnly || ownerModel.getStatus() == UserUtilities.STATUS_ACTIVE)) {
564                 issueNotifications.add(new Notification(ownerModel, issue,
565                         Role.OWNER));
566                 hasOwner = true;
567             }
568         }
569 
570         if (!primaryOnly || !hasOwner) {
571             User creatorModel = issue.getCreator();
572 
573             if (creatorModel != null
574                     && (!activeOnly || creatorModel.getStatus() == UserUtilities.STATUS_ACTIVE)) {
575                 issueNotifications.add(new Notification(creatorModel,
576                         issue, Role.CREATOR));
577             }
578         }
579 
580         Project project = getProjectService().getProject(
581                 issue.getProject().getId());
582 
583         for (User projectOwner : project.getOwners()) {
584             if (projectOwner != null
585                     && (!activeOnly || projectOwner.getStatus() == UserUtilities.STATUS_ACTIVE)) {
586                 issueNotifications.add(new Notification(projectOwner,
587                         issue, Role.PO));
588             }
589         }
590 
591         if (logger.isDebugEnabled()) {
592             logger.debug("getIssueNotifications: returning "
593                     + issueNotifications);
594         }
595         return issueNotifications;
596     }
597 
598     public List<Notification> getIssueNotifications(Issue issue) {
599         if (logger.isDebugEnabled()) {
600             logger.debug("getIssueNotifications: called with: " + issue);
601         }
602         return this.getIssueNotifications(issue, false, true);
603     }
604 
605     public List<Notification> getPrimaryIssueNotifications(Issue issue) {
606         if (logger.isDebugEnabled()) {
607             logger.debug("getPrimaryIssueNotifications: called with: " + issue);
608         }
609         return this.getIssueNotifications(issue, true, false);
610     }
611 
612     public boolean hasIssueNotification(Issue issue, Integer userId) {
613         if (logger.isDebugEnabled()) {
614             logger.debug("hasIssueNotification: called with: " + issue
615                     + ", userId: " + userId);
616         }
617         return hasIssueNotification(issue, userId, Role.ANY);
618     }
619 
620     @Override
621     public boolean hasIssueNotification(Issue issue, String login) {
622 
623         return hasIssueNotification(issue, login, Role.ANY);
624     }
625 
626     @Override
627     public boolean hasIssueNotification(Issue issue, String login, Role role) {
628 
629         if (issue != null && StringUtils.isNotBlank(login)) {
630 
631             List<Notification> notifications = getIssueNotifications(issue,
632                     false, false);
633 
634             for (Notification notification : notifications) {
635 
636                 if (role == Role.ANY || notification.getRole() == role) {
637 
638                     if (StringUtils.equals(login, notification.getUser().getLogin())) {
639 
640                         return true;
641 
642                     }
643 
644                 }
645 
646             }
647 
648         }
649 
650         return false;
651     }
652 
653     public boolean hasIssueNotification(Issue issue, Integer userId, Role role) {
654 
655         if (issue != null && userId != null) {
656 
657             List<Notification> notifications = getIssueNotifications(issue,
658                     false, false);
659 
660             for (Notification notification : notifications) {
661 
662                 if (role == Role.ANY || notification.getRole() == role) {
663 
664                     if (notification.getUser().getId().equals(userId)) {
665 
666                         return true;
667 
668                     }
669 
670                 }
671 
672             }
673 
674         }
675 
676         return false;
677 
678     }
679 
680     public boolean removeIssueNotification(Integer notificationId) {
681         Notification notification = this.getNotificationDao().findById(
682                 notificationId);
683         getNotificationDao().delete(notification);
684         return true;
685     }
686 
687     public void sendNotification(Issue issue, Type type, String baseURL,
688                                  InternetAddress[] receipients, Integer lastModifiedDays) {
689         this.handleLocalizedIssueNotification(issue, type, baseURL, receipients,
690                 lastModifiedDays);
691 
692     }
693 
694 
695     /**
696      * @return the emailService
697      */
698     public EmailService getEmailService() {
699         return emailService;
700     }
701 
702     /**
703      * @return the notificationDao
704      */
705     private NotificationDAO getNotificationDao() {
706         return notificationDao;
707     }
708 
709     /**
710      * @return the projectService
711      */
712     public ProjectService getProjectService() {
713         return projectService;
714     }
715 
716     /**
717      * @param projectService the projectService to set
718      */
719     public void setProjectService(ProjectService projectService) {
720         this.projectService = projectService;
721     }
722 
723     /**
724      * @param notificationDao the notificationDao to set
725      */
726     public void setNotificationDao(NotificationDAO notificationDao) {
727         if (null == notificationDao) {
728             throw new IllegalArgumentException(
729                     "notification dao must not be null");
730         }
731         if (null != this.notificationDao) {
732             throw new IllegalStateException("notification dao allready set");
733         }
734         this.notificationDao = notificationDao;
735     }
736 
737 
738     /**
739      * @return the issueActivityDao
740      */
741     public IssueActivityDAO getIssueActivityDao() {
742         return issueActivityDao;
743     }
744 
745     /**
746      * @param issueActivityDao the issueActivityDao to set
747      */
748     public void setIssueActivityDao(IssueActivityDAO issueActivityDao) {
749         this.issueActivityDao = issueActivityDao;
750     }
751 
752     /**
753      * @return the issueDao
754      */
755     public IssueDAO getIssueDao() {
756         return issueDao;
757     }
758 
759     /**
760      * @param issueDao the issueDao to set
761      */
762     public void setIssueDao(IssueDAO issueDao) {
763         this.issueDao = issueDao;
764     }
765 
766     public String getIssueServiceName() {
767         return issueServiceName;
768     }
769 
770     public void setIssueServiceName(String issueServiceName) {
771         this.issueServiceName = issueServiceName;
772     }
773 
774 }