1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.portlets.registration;
18
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Date;
24 import java.util.HashMap;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29 import java.util.MissingResourceException;
30 import java.util.ResourceBundle;
31
32 import javax.portlet.ActionRequest;
33 import javax.portlet.ActionResponse;
34 import javax.portlet.PortletConfig;
35 import javax.portlet.PortletException;
36 import javax.portlet.PortletMode;
37 import javax.portlet.PortletPreferences;
38 import javax.portlet.PortletRequest;
39 import javax.portlet.PortletResponse;
40 import javax.portlet.RenderRequest;
41 import javax.portlet.RenderResponse;
42 import javax.portlet.WindowState;
43
44 import org.apache.jetspeed.CommonPortletServices;
45 import org.apache.jetspeed.JetspeedActions;
46 import org.apache.jetspeed.PortalReservedParameters;
47 import org.apache.jetspeed.administration.AdministrationEmailException;
48 import org.apache.jetspeed.administration.PortalAdministration;
49 import org.apache.jetspeed.locator.JetspeedTemplateLocator;
50 import org.apache.jetspeed.locator.LocatorDescriptor;
51 import org.apache.jetspeed.locator.TemplateDescriptor;
52 import org.apache.jetspeed.locator.TemplateLocatorException;
53 import org.apache.jetspeed.request.RequestContext;
54 import org.apache.jetspeed.security.SecurityException;
55 import org.apache.jetspeed.security.User;
56 import org.apache.jetspeed.security.UserManager;
57 import org.apache.portals.bridges.util.PreferencesHelper;
58 import org.apache.portals.bridges.velocity.AbstractVelocityMessagingPortlet;
59 import org.apache.portals.gems.util.ValidationHelper;
60 import org.apache.velocity.context.Context;
61
62 /***
63 * This portlet allows a logged on user to change its password.
64 *
65 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
66 * @author <a href="mailto:chris@bluesunrise.com">Chris Schaefer</a>
67 * @version $Id: $
68 */
69 public class UserRegistrationPortlet extends AbstractVelocityMessagingPortlet
70 {
71
72 private PortalAdministration admin;
73
74 private UserManager userManager;
75
76
77
78 private static final String USER_ATTRIBUTE_EMAIL = "user.business-info.online.email";
79
80
81 private static final String MSG_MESSAGE = "MSG";
82
83 private static final String MSG_USERINFO = "user";
84
85 private static final String MSG_REGED_USER_MSG = "registeredUserMsg";
86
87
88 private static final String IP_ROLES = "roles";
89
90 private static final String IP_GROUPS = "groups";
91
92 private static final String IP_TEMPLATE_LOCATION = "emailTemplateLocation";
93
94 private static final String IP_TEMPLATE_NAME = "emailTemplateName";
95
96 private static final String IP_RULES_NAMES = "rulesNames";
97
98 private static final String IP_RULES_VALUES = "rulesValues";
99
100 private static final String IP_REDIRECT_PATH = "redirectPath";
101
102 private static final String IP_RETURN_URL = "returnURL";
103
104 private static final String IP_OPTION_EMAILS_SYSTEM_UNIQUE = "Option_Emails_System_Unique";
105
106 private static final String IP_OPTION_GENERATE_PASSWORDS = "Option_Generate_Passwords";
107
108 private static final String IP_OPTION_USE_EMAIL_AS_USERNAME = "Option_Use_Email_As_Username";
109
110
111 private static final String CTX_RETURN_URL = "returnURL";
112
113 private static final String CTX_MESSAGE = "MSG";
114
115 private static final String CTX_USERINFO = "user";
116
117 private static final String CTX_FIELDS = "fieldsInOrder";
118
119 private static final String CTX_OPTIONALS = "optionalMap";
120
121 private static final String CTX_REGED_USER_MSG = "registeredUserMsg";
122
123 private static final String CTX_OPTION_GENERATE_PASSWORDS = "CTX_Option_Generate_Passwords";
124
125 private static final String CTX_OPTION_USE_EMAIL_AS_USERNAME = "CTX_Option_Use_Email_As_Username";
126
127
128 private static final String RB_EMAIL_SUBJECT = "email.subject.registration";
129
130 private static final String PATH_SEPARATOR = "/";
131
132 /*** email template to use for merging */
133 private String templateLocation;
134
135 private String templateName;
136
137 private JetspeedTemplateLocator templateLocator;
138
139 /*** localized emailSubject */
140 private String emailSubject = null;
141
142 /*** path where to redirect to after pressing submit on the form */
143 private String redirectPath;
144
145 /*** servlet path of the return url to be printed and href'd in email template */
146 private String returnUrlPath;
147
148 /*** roles */
149 private List roles;
150
151 /*** groups */
152 private List groups;
153
154 /*** profile rules */
155 private Map rules;
156
157 /*** will force the passwords to be generated instead of picked by the user */
158 private boolean optionForceGeneratedPasswords = false;
159
160 /***
161 * will use cause the portlet to use a user request username instead
162 * otherwise forces emailaddress
163 */
164 private boolean optionForceEmailAsUsername = true;
165
166 /*** will check to make sure the email address is unique to the system */
167 private boolean optionForceEmailsToBeSystemUnique = true;
168
169 public void init(PortletConfig config) throws PortletException
170 {
171 super.init(config);
172 admin = (PortalAdministration) getPortletContext().getAttribute(
173 CommonPortletServices.CPS_PORTAL_ADMINISTRATION);
174 if (null == admin) { throw new PortletException(
175 "Failed to find the Portal Administration on portlet initialization"); }
176 userManager = (UserManager) getPortletContext().getAttribute(
177 CommonPortletServices.CPS_USER_MANAGER_COMPONENT);
178 if (null == userManager) { throw new PortletException(
179 "Failed to find the User Manager on portlet initialization"); }
180
181
182 this.roles = getInitParameterList(config, IP_ROLES);
183
184
185 this.groups = getInitParameterList(config, IP_GROUPS);
186
187
188 List names = getInitParameterList(config, IP_RULES_NAMES);
189 List values = getInitParameterList(config, IP_RULES_VALUES);
190 rules = new HashMap();
191 for (int ix = 0; ix < ((names.size() < values.size()) ? names.size()
192 : values.size()); ix++)
193 {
194 rules.put(names.get(ix), values.get(ix));
195 }
196
197 this.templateLocation = config.getInitParameter(IP_TEMPLATE_LOCATION);
198 if (templateLocation == null)
199 {
200 templateLocation = "/WEB-INF/view/userreg/";
201 }
202 templateLocation = getPortletContext().getRealPath(templateLocation);
203 this.templateName = config.getInitParameter(IP_TEMPLATE_NAME);
204 if (templateName == null)
205 {
206 templateName = "userRegistrationEmail.vm";
207 }
208
209 ArrayList roots = new ArrayList(1);
210 roots.add(templateLocation);
211
212 try
213 {
214 templateLocator = new JetspeedTemplateLocator(roots, "email", getPortletContext().getRealPath("/"));
215 templateLocator.start();
216 }
217 catch (FileNotFoundException e)
218 {
219 throw new PortletException("Could not start the template locator.", e);
220 }
221
222
223
224 this.optionForceEmailsToBeSystemUnique = Boolean.valueOf(
225 config.getInitParameter(IP_OPTION_EMAILS_SYSTEM_UNIQUE))
226 .booleanValue();
227 this.optionForceGeneratedPasswords = Boolean.valueOf(
228 config.getInitParameter(IP_OPTION_GENERATE_PASSWORDS))
229 .booleanValue();
230 this.optionForceEmailAsUsername = Boolean.valueOf(
231 config.getInitParameter(IP_OPTION_USE_EMAIL_AS_USERNAME))
232 .booleanValue();
233 if (this.optionForceEmailAsUsername)
234 {
235
236 this.optionForceEmailsToBeSystemUnique = true;
237 }
238 this.returnUrlPath = config.getInitParameter(IP_RETURN_URL);
239 this.redirectPath = config.getInitParameter(IP_REDIRECT_PATH);
240 }
241
242 public void doEdit(RenderRequest request, RenderResponse response)
243 throws PortletException, IOException
244 {
245 response.setContentType("text/html");
246 doPreferencesEdit(request, response);
247 }
248
249 protected void doDispatch(RenderRequest request, RenderResponse response) throws PortletException, IOException
250 {
251 if ( !request.getWindowState().equals(WindowState.MINIMIZED))
252 {
253 PortletMode curMode = request.getPortletMode();
254 if (JetspeedActions.EDIT_DEFAULTS_MODE.equals(curMode))
255 {
256
257 doEdit(request, response);
258 }
259 else
260 {
261 super.doDispatch(request, response);
262 }
263 }
264
265 }
266
267 public void doView(RenderRequest request, RenderResponse response)
268 throws PortletException, IOException
269 {
270 response.setContentType("text/html");
271 Context context = getContext(request);
272
273 Object userinfoObject = this
274 .receiveRenderMessage(request, MSG_USERINFO);
275 context.put(CTX_USERINFO, userinfoObject);
276 context.put(CTX_FIELDS, getListOfNonSpecialFormKeys());
277 context.put(CTX_OPTIONALS, getOptionalMap());
278 context.put(CTX_MESSAGE, consumeRenderMessage(request, MSG_MESSAGE));
279 String guid = request.getParameter("newUserGUID");
280 if (guid != null)
281 {
282
283
284
285
286
287 ResourceBundle resource = getPortletConfig().getResourceBundle(
288 request.getLocale());
289 context.put(CTX_REGED_USER_MSG, resource
290 .getString("success.login_above"));
291 } else
292 {
293
294
295
296 context.put(CTX_REGED_USER_MSG, consumeRenderMessage(request,
297 MSG_REGED_USER_MSG));
298 }
299
300 if (this.optionForceEmailAsUsername)
301 {
302 context.put(CTX_OPTION_USE_EMAIL_AS_USERNAME, "TRUE");
303 }
304 if (this.optionForceGeneratedPasswords)
305 {
306 context.put(CTX_OPTION_GENERATE_PASSWORDS, "TRUE");
307 }
308
309 super.doView(request, response);
310 }
311
312 private static final Boolean required = new Boolean(true);
313
314 private static final Boolean optional = new Boolean(false);
315
316 private static final Integer IS_STRING = new Integer(1);
317
318 private static final Integer IS_EMAIL = new Integer(2);
319
320 private static final Integer IS_PHONE = new Integer(3);
321
322 private static final Integer IS_URL = new Integer(4);
323
324 private static final Integer IS_BDATE = new Integer(5);
325
326 protected List getListOfNonSpecialFormKeys()
327 {
328 List l = new ArrayList();
329 for (int i = 0; i < formKeys.length; i++)
330 {
331 String key = (String) formKeys[i][0];
332 if (key.equals("user.name"))
333 {
334
335 } else if (key.equals("user.business-info.online.email"))
336 {
337
338 } else if (key.equals("password"))
339 {
340
341 } else if (key.equals("verifyPassword"))
342 {
343
344 } else
345 {
346
347 l.add(key);
348 }
349 }
350 return l;
351 }
352
353 protected Map getOptionalMap()
354 {
355 Map m = new HashMap();
356 for (int i = 0; i < formKeys.length; i++)
357 {
358 boolean isRequired = ((Boolean) formKeys[i][1]).booleanValue();
359 if (!isRequired)
360 {
361 m.put(formKeys[i][0], "");
362 }
363 }
364 return m;
365 }
366
367
368 protected static Object[][] formKeys =
369 {
370
371
372
373 {"user.business-info.online.email", required , new Integer(80), IS_EMAIL},
374
375
376
377 {"user.name", required , new Integer(80), IS_STRING},
378
379
380
381 {"password", required, new Integer(80), IS_STRING},
382 {"verifyPassword", required, new Integer(80), IS_STRING},
383
384
385
386
387
388
389
390
391
392
393
394 {"user.department", optional , new Integer(80), IS_STRING},
395
396
397
398
399 {"user.name.given", optional , new Integer(30), IS_STRING},
400 {"user.name.family", optional , new Integer(30), IS_STRING},
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435 {"user.business-info.postal.name", optional , new Integer(80), IS_STRING},
436 {"user.business-info.postal.street", optional , new Integer(80), IS_STRING},
437 {"user.business-info.postal.city", optional , new Integer(80), IS_STRING},
438 {"user.business-info.postal.stateprov", optional , new Integer(80), IS_STRING},
439 {"user.business-info.postal.postalcode", optional , new Integer(80), IS_STRING},
440 {"user.business-info.postal.country", optional , new Integer(80), IS_STRING},
441 {"user.business-info.postal.organization", optional , new Integer(80), IS_STRING},
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 };
467
468 protected boolean validateFormValue(String value, Integer length,
469 Integer validationType)
470 {
471
472 if (validationType.equals(IS_STRING))
473 {
474 if (!ValidationHelper.isAny(value, true, length.intValue())) { return false; }
475 } else if (validationType.equals(IS_EMAIL))
476 {
477 if (!ValidationHelper
478 .isEmailAddress(value, true, length.intValue())) { return false; }
479 } else if (validationType.equals(IS_PHONE))
480 {
481 if (!ValidationHelper.isPhoneNumber(value, true, length.intValue())) { return false; }
482 } else if (validationType.equals(IS_URL))
483 {
484 if (!ValidationHelper.isURL(value, true, length.intValue())) { return false; }
485 } else if (validationType.equals(IS_BDATE))
486 {
487 if (!ValidationHelper.isValidDatetime(value)) { return false; }
488 } else
489 {
490
491 if (!ValidationHelper.isAny(value, true, length.intValue())) { return false; }
492 }
493 return true;
494
495 }
496
497 protected String convertIfNeed(String key, String value)
498 {
499 if ("user.bdate".equals(key))
500 {
501
502 Date d = ValidationHelper.parseDate(value);
503 long timeInmS = d.getTime();
504 return "" + timeInmS;
505 }
506 return value;
507 }
508
509 public void processAction(ActionRequest actionRequest,
510 ActionResponse actionResponse) throws PortletException, IOException
511 {
512 List errors = new LinkedList();
513
514 Map userAttributes = new HashMap();
515
516 Map userInfo = new HashMap();
517 ResourceBundle resource = getPortletConfig().getResourceBundle(
518 actionRequest.getLocale());
519
520 PortletMode curMode = actionRequest.getPortletMode();
521
522 if (curMode == PortletMode.EDIT ||
523 curMode.equals(JetspeedActions.EDIT_DEFAULTS_MODE))
524 {
525 PortletPreferences prefs = actionRequest.getPreferences();
526 PreferencesHelper.requestParamsToPreferences(actionRequest);
527 prefs.store();
528 actionResponse.setPortletMode(PortletMode.VIEW);
529 return;
530 }
531
532 try
533 {
534
535 for (int i = 0; i < formKeys.length; i++)
536 {
537 try
538 {
539 String key = (String) formKeys[i][0];
540 Boolean isRequired = (Boolean) formKeys[i][1];
541 String value = actionRequest.getParameter(key);
542 if ((value != null) && (value.length() > 0))
543 {
544
545 userInfo.put(key, value);
546
547
548 if (!validateFormValue(value, (Integer) formKeys[i][2],
549 (Integer) formKeys[i][3]))
550 {
551 errors.add(resource
552 .getString("error.invalid-format." + key));
553 }
554
555 if (key.startsWith("user."))
556 {
557 value = convertIfNeed(key, value);
558
559 userAttributes.put(key, value);
560 }
561 } else
562 {
563
564
565 if (isRequired.booleanValue())
566 {
567 errors.add(resource.getString("error.lacking."
568 + key));
569 }
570
571
572 userInfo.put(key, "");
573 }
574 } catch (MissingResourceException mre)
575 {
576 errors.add(resource.getString("error.failed_to_add")
577 + mre.toString());
578 }
579
580 }
581
582 publishRenderMessage(actionRequest, MSG_USERINFO, userInfo);
583
584
585
586
587 if (this.optionForceEmailAsUsername)
588 {
589
590 if (!ValidationHelper.isEmailAddress((String) userInfo
591 .get(USER_ATTRIBUTE_EMAIL), true, 80))
592 {
593 errors.add(resource.getString("error.invalid-format."
594 + USER_ATTRIBUTE_EMAIL));
595 }
596 } else
597 {
598 if (!ValidationHelper.isAny((String) userInfo.get("user.name"),
599 true, 80))
600 {
601 errors.add(resource.getString("error.lacking.user.name"));
602 }
603 }
604
605
606 if (!this.optionForceGeneratedPasswords)
607 {
608 if (!ValidationHelper.isAny((String) userInfo.get("password"),
609 true, 25))
610 {
611 errors.add(resource.getString("error.lacking.password"));
612 }
613 }
614
615 if (optionForceEmailAsUsername)
616 {
617
618 userInfo.put("user.name", userInfo.get(USER_ATTRIBUTE_EMAIL));
619 }
620
621 boolean userIdExistsFlag = true;
622 try
623 {
624 userManager.getUser((String) userInfo.get("user.name"));
625 } catch (SecurityException e)
626 {
627 userIdExistsFlag = false;
628 }
629
630 if (userIdExistsFlag)
631 {
632 errors.add(resource.getString("error.userid_already_exists"));
633 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
634 return;
635 }
636 if (optionForceEmailsToBeSystemUnique)
637 {
638 boolean emailExistsFlag = true;
639 User user = null;
640 try
641 {
642 user = admin.lookupUserFromEmail((String) userInfo
643 .get(USER_ATTRIBUTE_EMAIL));
644 } catch (AdministrationEmailException e1)
645 {
646 emailExistsFlag = false;
647 }
648 if ((emailExistsFlag) || (user != null))
649 {
650 errors
651 .add(resource
652 .getString("error.email_already_exists"));
653 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
654 return;
655 }
656
657 }
658
659 try
660 {
661 if (optionForceGeneratedPasswords)
662 {
663 String password = admin.generatePassword();
664 userInfo.put("password", password);
665 } else
666 {
667 if (userInfo.get("password").equals(
668 userInfo.get("verifyPassword")))
669 {
670
671 } else
672 {
673 errors.add(resource
674 .getString("error.two_passwords_do_not_match"));
675 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
676 return;
677 }
678 }
679 } catch (Exception e)
680 {
681 errors.add(resource.getString("error.failed_to_add")
682 + e.toString());
683 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
684 }
685
686 if (errors.size() > 0)
687 {
688 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
689 return;
690 }
691
692
693 try
694 {
695 PortletPreferences prefs = actionRequest.getPreferences();
696 String template = prefs.getValue("newUserTemplateDirectory", "");
697 if (template.trim().length() == 0)
698 template = null;
699 String subsiteRootFolder = prefs.getValue("subsiteRootFolder", "");
700 if (subsiteRootFolder.trim().length() == 0)
701 subsiteRootFolder = null;
702 List prefRoles = getPreferencesList(prefs, IP_ROLES);
703 if (prefRoles.isEmpty())
704 prefRoles = this.roles;
705 List prefGroups = getPreferencesList(prefs, IP_GROUPS);
706 if (prefGroups.isEmpty())
707 prefGroups = this.groups;
708
709 List names = getPreferencesList(prefs, IP_RULES_NAMES);
710 List values = getPreferencesList(prefs, IP_RULES_VALUES);
711 Map profileRules = new HashMap();
712 for (int ix = 0; ix < ((names.size() < values.size()) ? names.size()
713 : values.size()); ix++)
714 {
715 profileRules.put(names.get(ix), values.get(ix));
716 }
717 if (profileRules.isEmpty())
718 profileRules = this.rules;
719
720 admin.registerUser((String) userInfo.get("user.name"),
721 (String) userInfo.get("password"), prefRoles,
722 prefGroups, userAttributes,
723
724 profileRules, template, subsiteRootFolder);
725
726 String urlGUID = ForgottenPasswordPortlet.makeGUID(
727 (String) userInfo.get("user.name"), (String) userInfo
728 .get("password"));
729
730 userInfo.put(CTX_RETURN_URL, generateReturnURL(actionRequest,
731 actionResponse, urlGUID));
732
733 String templ = getTemplatePath(actionRequest, actionResponse);
734
735 if (templ == null) { throw new Exception(
736 "email template not available"); }
737
738 boolean sendEmail = prefs.getValue("SendEmail", "true").equals("true");
739 if (sendEmail)
740 {
741 admin.sendEmail(getPortletConfig(), (String) userInfo
742 .get(USER_ATTRIBUTE_EMAIL),
743 getEmailSubject(actionRequest), templ, userInfo);
744 }
745
746 if ((this.optionForceEmailAsUsername)
747 || (this.optionForceGeneratedPasswords))
748 {
749 publishRenderMessage(actionRequest, MSG_REGED_USER_MSG,
750 resource.getString("success.check_your_email"));
751 } else
752 {
753 publishRenderMessage(actionRequest, MSG_REGED_USER_MSG,
754 resource.getString("success.login_above"));
755 }
756
757
758 publishRenderMessage(actionRequest, MSG_USERINFO, new HashMap());
759
760 actionResponse.sendRedirect(this.generateRedirectURL(
761 actionRequest, actionResponse));
762
763 } catch (Exception e)
764 {
765 errors.add(resource.getString("error.failed_to_add")
766 + e.toString());
767 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
768 }
769 } catch (MissingResourceException mre)
770 {
771 errors.add(resource.getString("error.failed_to_add")
772 + mre.toString());
773 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
774 } catch (Exception e)
775 {
776 errors
777 .add(resource.getString("error.failed_to_add")
778 + e.toString());
779 publishRenderMessage(actionRequest, MSG_MESSAGE, errors);
780 }
781
782 }
783
784 protected String getEmailSubject(PortletRequest request)
785 {
786 ResourceBundle resource = getPortletConfig().getResourceBundle(
787 request.getLocale());
788 try
789 {
790 this.emailSubject = resource.getString(RB_EMAIL_SUBJECT);
791 } catch (java.util.MissingResourceException mre)
792 {
793 this.emailSubject = null;
794 }
795 if (this.emailSubject == null)
796 this.emailSubject = "Registration Confirmation";
797 return this.emailSubject;
798 }
799
800 protected List getInitParameterList(PortletConfig config, String ipName)
801 {
802 String temp = config.getInitParameter(ipName);
803 if (temp == null) return new ArrayList();
804
805 String[] temps = temp.split("//,");
806 for (int ix = 0; ix < temps.length; ix++)
807 temps[ix] = temps[ix].trim();
808
809 return Arrays.asList(temps);
810 }
811
812 protected List getPreferencesList(PortletPreferences prefs, String prefName)
813 {
814 String temp = prefs.getValue(prefName, "");
815 if (temp == null || temp.trim().length() == 0) return new ArrayList();
816
817 String[] temps = temp.split("//,");
818 for (int ix = 0; ix < temps.length; ix++)
819 temps[ix] = temps[ix].trim();
820
821 return Arrays.asList(temps);
822 }
823
824 protected String generateReturnURL(PortletRequest request,
825 PortletResponse response, String urlGUID)
826 {
827 String fullPath = this.returnUrlPath + "?newUserGUID=" + urlGUID;
828
829 String url = admin.getPortalURL(request, response, fullPath);
830 return url;
831 }
832
833 protected String generateRedirectURL(PortletRequest request,
834 PortletResponse response)
835 {
836 return admin.getPortalURL(request, response, this.redirectPath);
837 }
838
839
840 protected String getTemplatePath(ActionRequest request, ActionResponse response)
841 {
842 if (templateLocator == null)
843 {
844 return templateLocation + PATH_SEPARATOR + templateName;
845 }
846
847 RequestContext requestContext = (RequestContext) request
848 .getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
849 Locale locale = request.getLocale();
850
851 try
852 {
853 LocatorDescriptor locator = templateLocator.createLocatorDescriptor("email");
854 locator.setName(templateName);
855 locator.setMediaType(requestContext.getMediaType());
856 locator.setLanguage(locale.getLanguage());
857 locator.setCountry(locale.getCountry());
858 TemplateDescriptor template = templateLocator.locateTemplate(locator);
859
860 return template.getAppRelativePath();
861 }
862 catch (TemplateLocatorException e)
863 {
864 return templateLocation + PATH_SEPARATOR + templateName;
865 }
866 }
867 }