/**
* (c) Copyright 2007-2010 by emarsys eMarketing Systems AG
*
* This file is part of dyson.
*
* dyson is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* dyson is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.emarsys.dyson.storage;
import java.io.File;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import com.emarsys.dyson.Dyson;
import com.emarsys.dyson.DysonConfig;
import com.emarsys.dyson.DysonException;
import com.emarsys.dyson.MailStorageFileNamingScheme;
import com.emarsys.ecommon.builder.time.CalendarBuilder;
import com.emarsys.ecommon.builder.time.TimeBuilder;
import com.emarsys.ecommon.mail.MessageUtil;
import com.emarsys.ecommon.time.Dates;
/**
* A flexible {@link MailStorageFileNamingScheme} implementation
* that produces storage files according to the {@link Token}s
* specified in the setting
* {@link DysonConfig#STORAGE_PROCESSED_MAIL_NAMING_SCHEME_TOKENS}.
*
* @author <a href="mailto:kulovits@emarsys.com">Michael "kULO" Kulovits</a>
*/
public class FlexibleMailStorageNamingScheme
extends MailStorageFileNamingScheme
{
/**
* {@link Token}s that define the naming scheme.
*
* @author <a href="mailto:kulovits@emarsys.com">Michael "kULO" Kulovits</a>
*/
public enum Token
{
/**
*
*/
CURRENT_TIMESTAMP
{
@Override
public String toPath( MimeMessage mail )
{
return Dates.timestampToString(
CalendarBuilder.getInstance() );
}
},
/**
*
*/
CURRENT_TIME_MILLIS
{
@Override
public String toPath( MimeMessage mail )
{
return String.valueOf(
TimeBuilder.getInstance().currentTimeMillis() );
}
},
/**
*
*/
RECIPIENT_NAME
{
@Override
public String toPath( MimeMessage mail )
{
final String rcpt = this.getToRecipient( mail );
return rcpt == null ? "unknown" :
rcpt.substring( 0, rcpt.indexOf( '@' ) );
}
},
/**
*
*/
RECIPIENT_DOMAIN
{
@Override
public String toPath( MimeMessage mail )
{
try
{
final String rcpt = this.getToRecipient( mail );
return rcpt == null ? "unknown" :
MessageUtil.getMailDomain( rcpt );
}
catch (AddressException e)
{
throw new DysonException(
"cannot get recipeint mail domain from mail " +
MessageUtil.toString( mail ) + ": " + e, e );
}
}
};
/**
* Turns this token into a part of a storage file path.
*
* @param mail
*/
public abstract String toPath( MimeMessage mail );
/**
*
* @param mail
* @return
*/
protected String getToRecipient( MimeMessage mail )
{
try
{
String rcpt = null;
Address[] toRcpts = mail.getRecipients( RecipientType.TO );
if( toRcpts != null && toRcpts.length >= 1 )
{
rcpt = MessageUtil.getValidEmailAddress(
toRcpts[0].toString() );
}
return rcpt;
}
catch( MessagingException e )
{
throw new DysonException(
"error on getting to recipient for mail " +
MessageUtil.toString( mail ) + ": " + e, e );
}
}
}//enum Token
/**
*
* @author <a href="mailto:kulovits@emarsys.com">Michael "kULO" Kulovits</a>
*/
protected class TokenSequence
{
Iterable<Token> tokens;
InputStream data;
/**
*
*/
public TokenSequence( Iterable<Token> tokens, InputStream data )
{
this.tokens = tokens;
this.data = data;
}
/**
*
* @return
*/
public String getStoragePath()
{
try
{
StringBuilder path = new StringBuilder();
MimeMessage mail = new MimeMessage( session, this.data );
for( Token token : this.tokens )
{
path.append( '/' ).append( token.toPath(mail) );
}
return path.toString();
}
catch( MessagingException e )
{
throw new DysonException(
"error on getting filename for mail: " + e, e );
}
}
}//class TokenSequence
//cached fields
protected final Session session =
Session.getDefaultInstance( new Properties() );
protected List<Token> configuredTokens =
this.getConfiguredTokens();
/**
*
* @param dyson
*/
public FlexibleMailStorageNamingScheme( Dyson dyson )
{
super(dyson);
}
/**
* @see com.emarsys.dyson.MailStorageFileNamingScheme#getMailFile(File, java.io.InputStream)
*/
public File getMailFile( File parentDirectory, InputStream data ) throws DysonException
{
TokenSequence tokenSequence =
new TokenSequence( this.configuredTokens, data );
String relativeStoragePath =
tokenSequence.getStoragePath() + "." +
this.getDyson().getStorage().getMailFileSuffix();
return new File( parentDirectory, relativeStoragePath );
}
/**
*
* @return
* @throws IllegalArgumentException
*/
protected List<Token> getConfiguredTokens()
throws IllegalArgumentException
{
List<Token> tokens = new LinkedList<Token>();
List<String> tokenStrs =
this.getDyson().getConfiguration().get(
DysonConfig.STORAGE_PROCESSED_MAIL_NAMING_SCHEME_TOKENS
).getListValues();
for( String tokenStr : tokenStrs )
{
tokens.add( Token.valueOf( tokenStr ) );
}
if( tokens.isEmpty() )
{
throw new IllegalStateException(
"Cannot create naming scheme token list without " +
"configured tokens!" );
}
return tokens;
}
}//class DomainRecipientTimestampNamingScheme