Source Code Cross Referenced for Email.java in  » Issue-Tracking » scarab-0.21 » org » tigris » scarab » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Issue Tracking » scarab 0.21 » org.tigris.scarab.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.tigris.scarab.util;
002:
003:        /* ================================================================
004:         * Copyright (c) 2000 CollabNet.  All rights reserved.
005:         * 
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions are
008:         * met:
009:         * 
010:         * 1. Redistributions of source code must retain the above copyright
011:         * notice, this list of conditions and the following disclaimer.
012:         * 
013:         * 2. Redistributions in binary form must reproduce the above copyright
014:         * notice, this list of conditions and the following disclaimer in the
015:         * documentation and/or other materials provided with the distribution.
016:         * 
017:         * 3. The end-user documentation included with the redistribution, if
018:         * any, must include the following acknowlegement: "This product includes
019:         * software developed by CollabNet (http://www.collab.net/)."
020:         * Alternately, this acknowlegement may appear in the software itself, if
021:         * and wherever such third-party acknowlegements normally appear.
022:         * 
023:         * 4. The hosted project names must not be used to endorse or promote
024:         * products derived from this software without prior written
025:         * permission. For written permission, please contact info@collab.net.
026:         * 
027:         * 5. Products derived from this software may not use the "Tigris" name
028:         * nor may "Tigris" appear in their names without prior written
029:         * permission of CollabNet.
030:         * 
031:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033:         * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034:         * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041:         * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042:         *
043:         * ====================================================================
044:         * 
045:         * This software consists of voluntary contributions made by many
046:         * individuals on behalf of CollabNet.
047:         */
048:
049:        import java.util.ArrayList;
050:        import java.util.Collection;
051:        import java.util.HashMap;
052:        import java.util.HashSet;
053:        import java.util.Iterator;
054:        import java.util.List;
055:        import java.util.Locale;
056:        import java.util.Map;
057:        import java.util.Set;
058:        import java.util.StringTokenizer;
059:
060:        import javax.mail.SendFailedException;
061:        import javax.mail.internet.InternetAddress;
062:
063:        import org.apache.fulcrum.ServiceException;
064:        import org.apache.fulcrum.template.TemplateContext;
065:        import org.apache.fulcrum.template.TemplateEmail;
066:        import org.apache.fulcrum.velocity.ContextAdapter;
067:        import org.apache.log4j.Logger;
068:        import org.apache.torque.TorqueException;
069:        import org.apache.turbine.Turbine;
070:        import org.tigris.scarab.om.GlobalParameter;
071:        import org.tigris.scarab.om.GlobalParameterManager;
072:        import org.tigris.scarab.om.Module;
073:        import org.tigris.scarab.om.ScarabUserManager;
074:        import org.tigris.scarab.om.ScarabUser;
075:        import org.tigris.scarab.services.email.VelocityEmail;
076:        import org.tigris.scarab.tools.ScarabLocalizationTool;
077:        import org.tigris.scarab.tools.localization.L10NKeySet;
078:
079:        /**
080:         * Sends a notification email.
081:         *
082:         * @author <a href="mailto:jon@collab.net">Jon Scott Stevens</a>
083:         * @author <a href="mailto:elicia@collab.net">Elicia David</a>
084:         * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
085:         * @version $Id: Email.java 10366 2006-11-29 18:38:43Z ronvoe122 $
086:         */
087:        public class Email extends TemplateEmail {
088:            private static final int TO = 0;
089:            private static final int CC = 1;
090:            private static final Integer ARCHIVE_USER_ID = new Integer(-1234);
091:            private static ScarabUser archiveUser;
092:
093:            public static Logger log = Log.get(Email.class.getName());
094:
095:            /**
096:             * Sends email to a single recipient. Throws an Excetion,
097:             * if it fails to send the email for any reason.
098:             */
099:            public static void sendEmail(EmailContext context, Module module,
100:                    Object fromUser, Object replyToUser, ScarabUser toUser,
101:                    String template) throws Exception {
102:                Collection toUsers = new ArrayList(2);
103:                toUsers.add(toUser);
104:                sendEmail(context, module, fromUser, replyToUser, toUsers,
105:                        null, template);
106:            }
107:
108:            /** 
109:             * Sends email to multiple recipients. Throws an Exception,
110:             * if it fails to send the email for any reason.
111:             */
112:            public static void sendEmail(EmailContext context, Module module,
113:                    Object fromUser, Object replyToUser, Collection toUsers,
114:                    Collection ccUsers, String template) throws Exception {
115:                if (!GlobalParameterManager.getBoolean(
116:                        GlobalParameter.EMAIL_ENABLED, module)) {
117:                    return;
118:                }
119:
120:                //
121:                // To avoid any NullPointerExceptions, create
122:                // empty lists of to: and cc: users if the
123:                // collections are null.
124:                //
125:                if (toUsers == null) {
126:                    toUsers = new ArrayList();
127:                }
128:
129:                if (ccUsers == null) {
130:                    ccUsers = new ArrayList();
131:                }
132:
133:                //
134:                // Remove duplicate addresses from the cc: list
135:                //
136:                ccUsers.removeAll(toUsers);
137:
138:                Map userLocaleMap = groupAddressesByLocale(module, toUsers,
139:                        ccUsers);
140:
141:                for (Iterator i = userLocaleMap.keySet().iterator(); i
142:                        .hasNext();) {
143:                    Locale locale = (Locale) i.next();
144:                    List[] toAndCC = (List[]) userLocaleMap.get(locale);
145:                    List to = toAndCC[TO];
146:                    List cc = toAndCC[CC];
147:
148:                    sendEmailInLocale(context, module, fromUser, replyToUser,
149:                            to, cc, template, locale);
150:                }
151:
152:            }
153:
154:            /** Sends email in a specific locale. */
155:            private static void sendEmailInLocale(EmailContext context,
156:                    Module module, Object fromUser, Object replyToUser,
157:                    List toAddresses, List ccAddresses, String template,
158:                    Locale locale) throws Exception {
159:                log.debug("Sending email for locale=" + locale);
160:
161:                // get reference to l10n tool, so we can alter the locale per email
162:                ScarabLocalizationTool l10n = new ScarabLocalizationTool();
163:                context.setLocalizationTool(l10n);
164:                l10n.init(locale);
165:
166:                Email te = getEmail(context, module, fromUser, replyToUser,
167:                        template);
168:                te.setCharset(getCharset(locale));
169:
170:                boolean atLeastOneTo = false;
171:                for (Iterator iTo = toAddresses.iterator(); iTo.hasNext();) {
172:                    InternetAddress a = (InternetAddress) iTo.next();
173:                    log.debug("Adding To: email[" + a.getAddress() + "], name["
174:                            + a.getPersonal() + "]");
175:                    te.addTo(a.getAddress(), a.getPersonal());
176:                    atLeastOneTo = true;
177:                }
178:                for (Iterator iCC = ccAddresses.iterator(); iCC.hasNext();) {
179:                    InternetAddress a = (InternetAddress) iCC.next();
180:                    String email = a.getAddress();
181:                    String name = a.getPersonal();
182:
183:                    // template email requires a To: user, it does seem possible
184:                    // to send emails with only a CC: user, so not sure if this
185:                    // is a bug to be fixed in TemplateEmail.  Might not be good
186:                    // form anyway.  So if there are no To: users, upgrade CC's.
187:                    if (atLeastOneTo) {
188:                        log.debug("Adding CC: email[" + email + "], name["
189:                                + name + "]");
190:                        te.addCc(email, name);
191:                    } else {
192:                        log.debug("Adding to: email[" + email + "], name["
193:                                + name + "]");
194:                        te.addTo(email, name);
195:                        // We've added one To: user and TemplateEmail should be
196:                        // happy. No need to move all CC: into TO:
197:                        atLeastOneTo = true;
198:                    }
199:                }
200:
201:                try {
202:                    log.debug("Sending email ...");
203:                    te.sendMultiple();
204:                } catch (SendFailedException sfe) {
205:                    log.warn("Could not send Email. Cause [" + sfe.getMessage()
206:                            + "]");
207:                    if (sfe.getCause() != null) {
208:                        log.warn("Cause: [" + sfe.getCause().getMessage());
209:                    }
210:                    Throwable t = sfe.getNextException();
211:                    throw new ScarabException(L10NKeySet.ExceptionEmailFailure,
212:                            t);
213:                }
214:            }
215:
216:            /**
217:             * Creates a map of Locale objects -> List[2], where the first
218:             * element of the list array is a list of "To:" addresses, and
219:             * the second is a list of "Cc:" addresses. For example, if
220:             * user "Pierre" is in <code>toUsers</code> and requires emails
221:             * in french, his email address will be in
222:             * <code>userLocaleMap[Locale.FRANCE][TO]</code>. The same applies
223:             * to "Cc:" addresses, while the archive email address is associated
224:             * with the default module locale.
225:             */
226:            private static Map groupAddressesByLocale(Module module,
227:                    Collection toUsers, Collection ccUsers) throws Exception {
228:                Map result = new HashMap();
229:                for (Iterator iter = toUsers.iterator(); iter.hasNext();) {
230:                    fileUser(result, (ScarabUser) iter.next(), module, TO);
231:                }
232:
233:                for (Iterator iter = ccUsers.iterator(); iter.hasNext();) {
234:                    fileUser(result, (ScarabUser) iter.next(), module, CC);
235:                }
236:                return result;
237:            }
238:
239:            private static void fileAddress(Map userLocaleMap,
240:                    InternetAddress address, Locale locale, int toOrCC) {
241:                List[] toAndCC = (List[]) userLocaleMap.get(locale);
242:                if (toAndCC == null) {
243:                    toAndCC = new List[2];
244:                    toAndCC[0] = new ArrayList();
245:                    toAndCC[1] = new ArrayList();
246:                    userLocaleMap.put(locale, toAndCC);
247:                }
248:                toAndCC[toOrCC].add(address);
249:            }
250:
251:            /** 
252:             * Checks if a user is the dummy user which indicates
253:             * that an Email should be sent to the archive Email addresses
254:             */
255:            public static boolean isArchiveUser(ScarabUser user) {
256:                return user.getUserId() == ARCHIVE_USER_ID;
257:            }
258:
259:            /** 
260:             * returns the dummy user which indicates
261:             * that an Email should be sent to the archive Email addresses
262:             */
263:            public static ScarabUser getArchiveUser() throws TorqueException {
264:                if (archiveUser == null) {
265:                    archiveUser = ScarabUserManager.getInstance();
266:                    archiveUser.setUserId(ARCHIVE_USER_ID);
267:                }
268:                return archiveUser;
269:            }
270:
271:            /** 
272:             * returns the archive Email addresses of a module
273:             */
274:            private static Set getArchiveAddresses(Module module) {
275:                Set expandedArchiveAddresses = new HashSet();
276:
277:                String archiveAddresses = module.getArchiveEmail();
278:                if (archiveAddresses != null) {
279:                    StringTokenizer st = new StringTokenizer(archiveAddresses,
280:                            ",;");
281:                    while (st.hasMoreTokens())
282:                        expandedArchiveAddresses.add(st.nextToken().trim());
283:                }
284:                return expandedArchiveAddresses;
285:            }
286:
287:            private static void fileUser(Map userLocaleMap, ScarabUser user,
288:                    Module module, int toOrCC) throws Exception {
289:                if (!isArchiveUser(user)) {
290:                    fileAddress(userLocaleMap, new InternetAddress(user
291:                            .getEmail(), user.getName()), chooseLocale(user,
292:                            module), toOrCC);
293:                } else {
294:                    for (Iterator addresses = getArchiveAddresses(module)
295:                            .iterator(); addresses.hasNext();) {
296:                        fileAddress(userLocaleMap, new InternetAddress(
297:                                (String) addresses.next(), user.getName()),
298:                                chooseLocale(user, module), toOrCC);
299:
300:                    }
301:                }
302:            }
303:
304:            /**
305:             * Override the super.handleRequest() and process the template
306:             * our own way.
307:             * This could have been handled in a more simple way, which was
308:             * to create a new service and associate the emails with a different
309:             * file extension which would have prevented the need to override
310:             * this method, however, that was discovered after the fact and it
311:             * also seemed to be a bit more work to change the file extension. 
312:             */
313:            protected String handleRequest() throws ServiceException {
314:                String result = null;
315:                try {
316:                    result = VelocityEmail.handleRequest(new ContextAdapter(
317:                            getContext()), getTemplate());
318:                } catch (Exception e) {
319:                    throw new ServiceException(e); //EXCEPTION
320:                }
321:                return result;
322:            }
323:
324:            /**
325:             * @param context The context in which to send mail, or
326:             * <code>null</code> to create a new context.
327:             * @param fromUser Can be any of the following: ScarabUser, two
328:             * element String[] composed of name and address, base portion of
329:             * the key used for a name and address property lookup.
330:             * @param replyToUser Can be any of the following: ScarabUser, two
331:             * element String[] composed of name and address, base portion of
332:             * the key used for a name and address property lookup.
333:             */
334:            private static Email getEmail(EmailContext context, Module module,
335:                    Object fromUser, Object replyToUser, String template)
336:                    throws Exception {
337:                Email te = new Email();
338:                if (context == null) {
339:                    context = new EmailContext();
340:                }
341:                te.setContext(context);
342:
343:                EmailLink el = EmailLinkFactory.getInstance(module);
344:                context.setLinkTool(el);
345:
346:                String[] nameAndAddr = getNameAndAddress(fromUser);
347:                te.setFrom(nameAndAddr[0], nameAndAddr[1]);
348:
349:                nameAndAddr = getNameAndAddress(replyToUser);
350:                log.debug("Add from name[" + nameAndAddr[0] + "], address["
351:                        + nameAndAddr[1] + "]");
352:                te.addReplyTo(nameAndAddr[0], nameAndAddr[1]);
353:
354:                if (template == null) {
355:                    template = Turbine.getConfiguration().getString(
356:                            "scarab.email.default.template", "Default.vm");
357:                }
358:                log.debug("Add template [" + template + "]");
359:                te.setTemplate(prependDir(template));
360:
361:                String subjectTemplate = context.getSubjectTemplate();
362:                if (subjectTemplate == null) {
363:                    int templateLength = template.length();
364:                    // The magic number 7 represents "Subject"
365:                    StringBuffer templateSB = new StringBuffer(
366:                            templateLength + 7);
367:                    // The magic number 3 represents ".vm"
368:                    templateSB
369:                            .append(template.substring(0, templateLength - 3));
370:                    subjectTemplate = templateSB.append("Subject.vm")
371:                            .toString();
372:                }
373:
374:                String subjectText = getSubject(context, subjectTemplate);
375:                log.debug("Add subject [" + subjectText + "]");
376:                te.setSubject(subjectText);
377:                return te;
378:            }
379:
380:            /**
381:             * Leverages the <code>fromName</code> and
382:             * <code>fromAddress</code> properties when <code>input</code> is
383:             * neither a <code>ScarabUser</code> nor <code>String[]</code>.
384:             */
385:            private static String[] getNameAndAddress(Object input) {
386:                String[] nameAndAddr;
387:                if (input instanceof  ScarabUser) {
388:                    ScarabUser u = (ScarabUser) input;
389:                    nameAndAddr = new String[] { u.getName(), u.getEmail() };
390:                } else if (input instanceof  String[]) {
391:                    nameAndAddr = (String[]) input;
392:                } else {
393:                    // Assume we want a property lookup, and the base portion
394:                    // of the key to use for that lookup was passed in.
395:                    String keyBase = (String) input;
396:                    if (keyBase == null) {
397:                        keyBase = "scarab.email.default";
398:                    }
399:
400:                    // TODO: Discover a better sending host/domain than
401:                    // "localhost"
402:
403:                    nameAndAddr = new String[2];
404:                    nameAndAddr[0] = Turbine.getConfiguration().getString(
405:                            keyBase + ".fromName", "Scarab System");
406:                    nameAndAddr[1] = Turbine.getConfiguration().getString(
407:                            keyBase + ".fromAddress", "help@localhost");
408:                }
409:                return nameAndAddr;
410:            }
411:
412:            private static String getSubject(TemplateContext context,
413:                    String template) {
414:                template = prependDir(template);
415:                String result = null;
416:                try {
417:                    // render the template
418:                    result = VelocityEmail.handleRequest(new ContextAdapter(
419:                            context), template);
420:                    if (result != null) {
421:                        result = result.trim();
422:                    }
423:                    // in some of the more complicated templates, we set a context
424:                    // variable so that there is not a whole bunch of whitespace
425:                    // that can make it into the subject...
426:                    String subject = (String) context.get("emailSubject");
427:                    if (subject != null) {
428:                        result = subject.trim();
429:                    }
430:                } catch (Exception e) {
431:                    log.error("Error rendering subject for " + template + ". ",
432:                            e);
433:                    result = "Scarab System Notification";
434:                }
435:                return result;
436:            }
437:
438:            private static String prependDir(String template) {
439:                boolean b = false;
440:                try {
441:                    b = GlobalParameterManager
442:                            .getBoolean(GlobalParameter.EMAIL_INCLUDE_ISSUE_DETAILS);
443:                } catch (Exception e) {
444:                    log.debug("", e);
445:                    // use the basic email
446:                }
447:                return b ? "email/" + template : "basic_email/" + template;
448:            }
449:
450:            /**
451:             * Returns a charset for the given locale that is generally
452:             * preferred by email clients.  If not specified by the property
453:             * named by {@link
454:             * org.tigris.scarab.util.ScarabConstants#DEFAULT_EMAIL_ENCODING_KEY},
455:             * ask the <code>MimeTypeService</code> for a good value (except
456:             * for Japanese, which always uses the encoding
457:             * <code>ISO-2022-JP</code>).
458:             *
459:             * @param locale a <code>Locale</code> value
460:             * @return a <code>String</code> value
461:             */
462:            public static String getCharset(Locale locale) {
463:                String charset = Turbine.getConfiguration().getString(
464:                        ScarabConstants.DEFAULT_EMAIL_ENCODING_KEY, "").trim();
465:                if (charset.length() == 0 || "native".equalsIgnoreCase(charset)) {
466:                    if ("ja".equals(locale.getLanguage())) {
467:                        charset = "ISO-2022-JP";
468:                    } else {
469:                        charset = ComponentLocator.getMimeTypeService()
470:                                .getCharSet(locale);
471:                    }
472:                }
473:
474:                return charset;
475:            }
476:
477:            private static Locale chooseLocale(ScarabUser user, Module module) {
478:                Locale locale = null;
479:                if (user != null) {
480:                    try {
481:                        locale = user.getPreferredLocale();
482:                    } catch (Exception e) {
483:                        log.error("Couldn't determine locale for user "
484:                                + user.getUserName(), e);
485:                    }
486:                }
487:                if (locale == null) {
488:                    if (module != null && module.getLocale() != null) {
489:                        locale = module.getLocale();
490:                    } else {
491:                        locale = ScarabConstants.DEFAULT_LOCALE;
492:                    }
493:                }
494:                return locale;
495:            }
496:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.