001package org.apache.archiva.redback.integration.mail; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import freemarker.template.Configuration; 023import org.apache.archiva.redback.configuration.UserConfiguration; 024import org.apache.archiva.redback.configuration.UserConfigurationKeys; 025import org.apache.archiva.redback.keys.AuthenticationKey; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028import org.springframework.stereotype.Service; 029import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; 030 031import javax.inject.Inject; 032import javax.inject.Named; 033import java.text.SimpleDateFormat; 034import java.util.HashMap; 035import java.util.Locale; 036import java.util.Map; 037 038/** 039 * Mail generator that uses freemarker templates. 040 * 041 * This implementation sets the following model values that can be used in templates: 042 * <ul> 043 * <li>applicationUrl</li> 044 * <li>urlPath</li> 045 * <li>authKey</li> 046 * <li>accountId</li> 047 * <li>requestedOn</li> 048 * <li>expiresOn</li> 049 * </ul> 050 * 051 * The additional template data is added for interpolation, if not <code>null</code>. 052 * 053 * This implementation is location enabled. That means, it will try to find templates in the following order: 054 * <ul> 055 * <li><i>templateName</i>_<i>language</i>_<i>country</i>.ftl</li> 056 * <li><i>templateName</i>_<i>language</i>.ftl</li> 057 * <li><i>templateName</i>.ftl</li> 058 * </ul> 059 * 060 * The default encoding used for reading the template is UTF-8 061 * 062 * @author Martin Stockhammer <martin_s@apache.org> 063 */ 064@Service( "mailGenerator#freemarker" ) 065public class FreemarkerMailGenerator implements MailGenerator 066{ 067 private Logger log = LoggerFactory.getLogger( FreemarkerMailGenerator.class ); 068 069 public static final String DEFAULT_ENCODING = "UTF-8"; 070 071 @Inject 072 @Named( value = "userConfiguration#default" ) 073 private UserConfiguration config; 074 075 @Inject 076 Configuration freemarkerConfiguration; 077 078 private String encoding; 079 080 private String getEncoding( ) 081 { 082 if ( this.encoding == null ) 083 { 084 this.encoding = config.getString( UserConfigurationKeys.MAIL_TEMPLATE_ENCODING, DEFAULT_ENCODING ); 085 } 086 return this.encoding; 087 } 088 089 private Locale getMailLocale() { 090 String localeString = config.getString( UserConfigurationKeys.MAIL_DEFAULT_LOCALE ); 091 if (localeString == null || "".equals(localeString)) { 092 return Locale.getDefault( ); 093 } else { 094 return Locale.forLanguageTag( localeString ); 095 } 096 } 097 098 /** 099 * 100 * @param templateName the template name without extension 101 * @param locale the locale used to find the template file 102 * @param authkey the authentication key 103 * @param baseUrl the base url 104 * @param templateData additional template data, may be <code>null</code> 105 * @return the string generated from the template 106 */ 107 @Override 108 public String generateMail( String templateName, Locale locale, AuthenticationKey authkey, String baseUrl, 109 Map<String, Object> templateData ) 110 { 111 Map<String, Object> context = createModel( authkey, baseUrl, templateData ); 112 StringBuffer content = new StringBuffer( ); 113 try 114 { 115 content.append( FreeMarkerTemplateUtils.processTemplateIntoString( 116 freemarkerConfiguration.getTemplate( templateName + ".ftl", locale, getEncoding( ) ), context ) ); 117 return content.toString( ); 118 } 119 catch ( Exception e ) 120 { 121 log.error( "Could not parse the mail template {}: {}", templateName, e.getMessage( ), e ); 122 } 123 return ""; 124 } 125 126 @Override 127 public String generateMail( String templateName, AuthenticationKey authenticationKey, String baseUrl ) 128 { 129 return generateMail( templateName, getMailLocale(), authenticationKey, baseUrl ); 130 } 131 132 @Override 133 public String generateMail( String templateName, Locale locale, AuthenticationKey authenticationKey, String baseUrl ) 134 { 135 return generateMail( templateName, locale, authenticationKey, baseUrl, null ); 136 } 137 138 private Map<String, Object> createModel( AuthenticationKey authkey, String appUrl, Map<String, Object> templateData ) 139 { 140 Map<String, Object> context = new HashMap<>( ); 141 context.put( "applicationUrl", config.getString( UserConfigurationKeys.APPLICATION_URL, appUrl ) ); 142 143 String feedback = config.getString( UserConfigurationKeys.EMAIL_FEEDBACK_PATH ); 144 145 if ( feedback != null ) 146 { 147 if ( feedback.startsWith( "/" ) ) 148 { 149 feedback = appUrl + feedback; 150 } 151 152 context.put( "feedback", feedback ); 153 } 154 155 context.put( "urlPath", 156 config.getString( UserConfigurationKeys.EMAIL_URL_PATH, "security/login!login.action" ) ); 157 158 context.put( "authkey", authkey.getKey( ) ); 159 160 context.put( "accountId", authkey.getForPrincipal( ) ); 161 162 SimpleDateFormat dateformatter = 163 new SimpleDateFormat( config.getString( UserConfigurationKeys.APPLICATION_TIMESTAMP ), Locale.US ); 164 165 context.put( "requestedOn", dateformatter.format( authkey.getDateCreated( ) ) ); 166 167 if ( authkey.getDateExpires( ) != null ) 168 { 169 context.put( "expiresOn", dateformatter.format( authkey.getDateExpires( ) ) ); 170 } 171 else 172 { 173 context.put( "expiresOn", "(does not expire)" ); 174 } 175 176 if (templateData!=null) 177 { 178 for ( Map.Entry<String, Object> entry : templateData.entrySet( ) ) 179 { 180 context.put( entry.getKey( ), entry.getValue( ) ); 181 } 182 } 183 184 return context; 185 } 186 187 public Configuration getFreemarkerConfiguration( ) 188 { 189 return freemarkerConfiguration; 190 } 191 192 public void setFreemarkerConfiguration( Configuration freemarkerConfiguration ) 193 { 194 this.freemarkerConfiguration = freemarkerConfiguration; 195 } 196 197 public UserConfiguration getConfig( ) 198 { 199 return config; 200 } 201 202 public void setConfig( UserConfiguration config ) 203 { 204 this.config = config; 205 } 206}