first commit

This commit is contained in:
jomu
2013-02-06 22:06:43 +00:00
parent 1a6d3e4c41
commit aef92c311d
84 changed files with 5334 additions and 0 deletions

View File

@ -0,0 +1,7 @@
#Thu Jul 05 02:27:50 CEST 2012
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -0,0 +1,5 @@
#Thu Jul 05 02:27:48 CEST 2012
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<netbeans.compile.on.save>all</netbeans.compile.on.save>
</properties>
</project-shared-configuration>

78
network/pom.xml Normal file
View File

@ -0,0 +1,78 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.muehlencord.shared</groupId>
<artifactId>shared-network</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>shared-network</name>
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<url>http://maven.apache.org</url>
<ciManagement>
<system>hudson</system>
<url>http://sunrise.muehlencord.intra:8088/jenkins/job/shared-util/</url>
</ciManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.enterprisedt</groupId>
<artifactId>edtFTPj</artifactId>
<version>1.5.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.muehlencord.shared</groupId>
<artifactId>shared-util</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.5</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,241 @@
package de.muehlencord.shared.network.ftp;
import com.enterprisedt.net.ftp.FTPClient;
import com.enterprisedt.net.ftp.FTPConnectMode;
import com.enterprisedt.net.ftp.FTPException;
import com.enterprisedt.net.ftp.FTPFile;
import de.muehlencord.shared.util.StringUtil;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.apache.log4j.Logger;
/**
*
* @author joern@muehlencord.de
*/
public class FTPConnection {
/** the default timeout in ms */
public static final int DEFAULTTIMEOUT = 30000;
/** the logger object */
private final Logger logger = Logger.getLogger(FTPConnection.class);
/** the username to connect with */
private String userName;
/** the password to connect with */
private String password;
/** the ftp client to use */
private FTPClient client;
/** the remote host to connect to */
private String remoteHost;
/** the locale of the client to use */
private Locale clientLocale;
/**
* creates a new ftp connection
*
* @param remoteHost the host to connect to
* @param userName the user to connect with
* @param password the password to connect with
*/
public FTPConnection(String remoteHost, String userName, String password) {
this(remoteHost, userName, password, Locale.getDefault());
}
/**
* creates a new ftp connection
*
* @param remoteHost the host to connect to
* @param userName the user to connect with
* @param password the password to connect with
* @param clientLocale the locale to use for the client
*/
public FTPConnection(String remoteHost, String userName, String password, Locale clientLocale) {
this.remoteHost = remoteHost;
this.userName = userName;
this.password = password;
this.clientLocale = clientLocale;
}
/**
* connects the ftp client to the remote host
*
* @throws FTPConnectionException if the command cannot be executed
*/
public void connect() throws FTPConnectionException {
try {
client = new FTPClient();
client.setConnectMode(FTPConnectMode.PASV);
client.setParserLocale(clientLocale);
client.setRemoteHost(remoteHost);
client.setTimeout(DEFAULTTIMEOUT);
client.connect();
client.login(userName, password);
} catch (Exception ex) {
throw new FTPConnectionException("Error while connecting to ftp client. Reason: " + ex.getMessage(), ex);
}
}
/** disconnects the ftp client from the remote host */
public void disconnect() {
try {
client.quit();
} catch (IOException ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
} catch (FTPException ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
}
}
/**
* returns a list of files (as string) found in the given directory
*
* @param dir the directory to return the list for
* @return a list of files (as string) found in the given directory
*
* @throws FTPConnectionException if the command cannot be executed
*/
public List<String> list(String dir) throws FTPConnectionException {
List<String> returnValue = new LinkedList<String>();
try {
FTPFile[] files = client.dirDetails(dir);
for (int i = 0; i < files.length; i++) {
returnValue.add(files[i].getName());
}
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
}
return returnValue;
}
/**
* returns a list of directories contained in given directory
*
* @param dir the directory to return the subfolders for
* @return a list of subfolders of the given directory
*
* @throws FTPConnectionException if the command cannot be executed
*/
public List<String> listDirsOnly(String dir) throws FTPConnectionException {
List<String> returnValue = new LinkedList<String>();
try {
FTPFile[] files = client.dirDetails(dir);
for (int i = 0; i < files.length; i++) {
if (files[i].isDir()) {
returnValue.add(files[i].getName());
}
}
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
}
return returnValue;
}
/**
* returns a list of files contained in the given folder
*
* @param dir the directory to list
* @return a list of files contained in the given folder
*
* @throws FTPConnectionException if the command cannot be executed
*/
public List<String> listFilesOnly(String dir) throws FTPConnectionException {
List<String> returnValue = new LinkedList<String>();
try {
FTPFile[] files = client.dirDetails(dir);
for (int i = 0; i < files.length; i++) {
if (!files[i].isDir()) {
returnValue.add(files[i].getName());
}
}
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
}
return returnValue;
}
/**
* returns a list of links contained in the given folder
*
* @param dir the directory to list
* @return a list of links contained in the given folder
*
* @throws FTPConnectionException if the command cannot be executed
*/
public List<String> listLinksOnly(String dir) throws FTPConnectionException {
List<String> returnValue = new LinkedList<String>();
try {
FTPFile[] files = client.dirDetails(dir);
for (int i = 0; i < files.length; i++) {
if (files[i].isLink()) {
returnValue.add(files[i].getName());
}
}
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while getting diretoy listing. Reason: " + ex.getMessage(), ex);
}
return returnValue;
}
/**
* uploads the given file and stores it under the given remote filename - including path
*
* @param localFilename the path and filename of the source file
* @param remoteFileName the path and filename of the destination file
* @throws FTPConnectionException if the command cannot be executed
*/
public void uploadFile(String localFilename, String remoteFileName) throws FTPConnectionException {
try {
client.setDetectTransferMode(true);
if ((remoteFileName != null) && !remoteFileName.equals("")) {
client.put(localFilename, remoteFileName, false);
} else {
File f = new File(localFilename);
String remoteName = f.getName();
client.put(localFilename, remoteName, false);
}
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while uploading file. Reason: " + ex.getMessage(), ex);
}
}
/**
* renames a file on the remote host
*
* @param remoteOldName the current file name
* @param remoteNewName the new file name
* @throws FTPConnectionException if the command cannot be executed
*/
public void rename(String remoteOldName, String remoteNewName) throws FTPConnectionException {
try {
client.rename(remoteOldName, remoteNewName);
} catch (Exception ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
throw new FTPConnectionException("Error while renaming file. Reason: " + ex.getMessage(), ex);
}
}
}

View File

@ -0,0 +1,45 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.ftp;
/**
*
* @author jomu
*/
public class FTPConnectionException extends Exception {
/**
*
*/
private static final long serialVersionUID = 4393979078434188521L;
/**
* Creates a new instance of
* <code>FTPConnectionException</code> without detail message.
*/
public FTPConnectionException() {
}
/**
* Constructs an instance of
* <code>FTPConnectionException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public FTPConnectionException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>FTPConnectionException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public FTPConnectionException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,263 @@
package de.muehlencord.shared.network.http;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
/**
* Communication endpoint for posting a messages
*
* @author joern@muehlencord.de
*/
public class HttpLayer {
private static final Logger logger = Logger.getLogger(HttpLayer.class);
/** the url to post to */
private String destinationUrlString;
/** the encoding to use */
private String encoding;
/**
* creates a new http layer which can communicate with the given url
*
* @param urlString
* the url to communicate with
*/
public HttpLayer(String urlString) {
this.destinationUrlString = urlString;
this.encoding = "UTF-8";
}
/**
* posts the value of message into the varialbe parameter
*
* @param parameter
* the parameter to write the message to
* @param message
* the message to post
* @throws MessageNotSendException
* if the message cannot be sent
*/
public void post(String parameter, String message)
throws MessageNotSendException {
Map<String, String[]> parameterMap = new HashMap<String, String[]>();
String[] valueArray = { message };
parameterMap.put(parameter, valueArray);
post(parameterMap);
}
public void post(List<Map<String, String[]>> parameterMap)
throws MessageNotSendException {
// construct string to post
String content = getDataString(parameterMap);
post(content);
}
/**
* posts the parameters and values specified by the parameter map to the
* configured url
*
* @param parameterMap
* the parameter map to post
* @throws MessageNotSendException
* if the http / post request cannot be executed
*
* TODO add https support
*/
public void post(Map<String, String[]> parameterMap) throws MessageNotSendException {
List<Map<String,String[]>> parameterList = new LinkedList<Map<String,String[]>>();
parameterList.add(parameterMap);
String content = getDataString(parameterList);
post (content);
}
private void post(String messageString) throws MessageNotSendException {
// check URL string and return URL object if valid; otherwise
// MessageNotSendException is thrown
URLConnection urlConn = getUrlConnection();
// post data
IOException exceptionDuringPost = null;
OutputStream outputStream = null;
DataOutputStream printout = null;
try {
outputStream = urlConn.getOutputStream();
printout = new DataOutputStream(outputStream);
printout.writeBytes(messageString);
printout.flush();
logger.info("Message sent successfully");
} catch (IOException ioex) {
// store received exception but first get output and
if (logger.isDebugEnabled()) {
logger.debug(ioex);
}
exceptionDuringPost = ioex;
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug(ex);
}
}
}
if (printout != null) {
try {
printout.close();
} catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug(ex);
}
}
}
}
// Get response message
StringBuilder sb = new StringBuilder();
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
inputStreamReader = new InputStreamReader(urlConn.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
while (bufferedReader.ready()) {
sb.append(bufferedReader.readLine());
}
if (logger.isDebugEnabled()) {
logger.debug("Response from server");
logger.debug(sb.toString());
}
} catch (IOException ioex) {
logger.error(ioex);
exceptionDuringPost = ioex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
logger.error(ex.getMessage());
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (IOException ex) {
logger.error(ex.getMessage());
}
}
}
if (exceptionDuringPost != null) {
String hint = "Error while sending message. Reason: "
+ exceptionDuringPost.getMessage();
logger.error(hint);
throw new MessageNotSendException(hint, exceptionDuringPost);
}
}
/**
*
* @param urlString
* the url to check
* @return a URl object created from the given urlString
* @throws MessageNotSendException
* if the url is invalid
*/
private URLConnection getUrlConnection() throws MessageNotSendException {
URLConnection urlConn;
URL url;
try {
url = new URL(destinationUrlString);
} catch (MalformedURLException ex) {
String hint = "Cannot send message to url - invalid url "
+ destinationUrlString;
logger.error(hint);
throw new MessageNotSendException(hint, ex);
}
String protocol = url.getProtocol().toLowerCase();
if (!protocol.equals("http")) {
String hint = "protocol " + protocol + " not supported";
logger.error(hint);
throw new MessageNotSendException(hint);
}
// setup url connection
try {
// URL connection channel.
urlConn = url.openConnection();
// Let the run-time system (RTS) know that we want input.
urlConn.setDoInput(true);
// Let the RTS know that we want to do output.
urlConn.setDoOutput(true);
// No caching, we want the real thing.
urlConn.setUseCaches(false);
// Specify the content type.
urlConn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
} catch (IOException ioex) {
String hint = "Error while setting up connection. Reason: "
+ ioex.getMessage();
logger.error(hint);
throw new MessageNotSendException(hint, ioex);
}
return urlConn;
}
/**
* returns the data string to post based on the given parameter map
*
* @param parameterMap
* the parameter map to construct the data string from
* @return the data string to post
* @throws MessageNotSendException
* if the datastring cannot be constructed
*/
private String getDataString(List<Map<String, String[]>> parameterList)
throws MessageNotSendException {
// perpare data
String data = "";
for (Map<String,String[]> parameterMap : parameterList) {
try {
Iterator<String> keyIterator = parameterMap.keySet().iterator();
while (keyIterator.hasNext()) {
String key = keyIterator.next();
String[] valueArray = parameterMap.get(key);
for (String currentValue : valueArray) {
if (!data.equals("")) {
data += "&";
}
data += key.toLowerCase() + "="
+ URLEncoder.encode(currentValue, encoding);
}
}
} catch (UnsupportedEncodingException ex) {
String hint = "Error while preparing data for message. Unknown encoding "
+ encoding;
logger.error(hint);
throw new MessageNotSendException(hint, ex);
}
}
return data;
}
}

View File

@ -0,0 +1,41 @@
package de.muehlencord.shared.network.http;
/**
* This message is thrown if a message cannot be sent
* @author joern@muehlencord.de
*/
public class MessageNotSendException extends Exception {
/**
*
*/
private static final long serialVersionUID = -8959773341187046577L;
/**
* Creates a new instance of
* <code>MessageNotSendException</code> without detail message.
*/
public MessageNotSendException() {
}
/**
* Constructs an instance of
* <code>MessageNotSendException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public MessageNotSendException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>MessageNotSendException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public MessageNotSendException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,485 @@
package de.muehlencord.shared.network.mail;
import de.muehlencord.shared.util.StringUtil;
import java.io.ByteArrayOutputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeMessage;
import javax.mail.search.MessageIDTerm;
import javax.mail.search.SearchTerm;
import javax.mail.util.SharedByteArrayInputStream;
import org.apache.log4j.Logger;
/**
* MailReader to connect and work with IMAP mailboxes. Also works with exchange servers.
*
* @author joern@muehlencord.de
*/
public abstract class DefaultMailReader implements MailReader {
/** the logging object */
private final static Logger logger = Logger.getLogger(DefaultMailReader.class);
/** the store to connect with */
private Store store = null;
/** the smtp host to work with */
private final MailReaderConfiguration configuration;
/**
* creates a new instance of the DefaultMailReader and updates needed values and settings
*
* @param config the configuration for the reader
*/
public DefaultMailReader(MailReaderConfiguration config) {
this.configuration = config;
}
/**
* onnects to the mailbox
*
* @throws MailReaderConnectionException if the connection cannot be established
*/
@Override
public abstract void connect() throws MailReaderConnectionException;
/** disconnects from mailbox */
@Override
public void disconnect() {
if (getStore() != null) {
try {
getStore().close();
} catch (MessagingException ex) {
logger.error("Cannot disconnect from mailbox");
logger.debug(StringUtil.getStackTraceString(ex));
} finally {
logger.info("Connection closed");
setStore(null);
}
}
}
/** returns the default folder
*
* @return the default folder
*
* @throws MailReaderException if the default folder cannot be found
*/
@Override
public String getDefaultFolder() throws MailReaderException {
try {
return getStore().getDefaultFolder().getFullName();
} catch (Exception ex) {
logger.debug(StringUtil.getStackTraceString(ex));
throw new MailReaderException("Error while retrieving default folder. Reason: " + ex.getMessage(), ex);
}
}
/**
* returns the list of subfolders of the specified source folder
*
* @param sourceFolder the folder to return the folder list for
* @return the list of subfolders of the specified source folder
*
* @throws MailReaderException if the folder list cannot be retrieved
*/
public List<String> getSubFolder(Folder sourceFolder) throws MailReaderException {
List<String> returnValue = new LinkedList<String>();
try {
Folder[] folders = sourceFolder.list();
for (Folder folder : folders) {
returnValue.add(folder.getFullName());
}
} catch (Exception ex) {
logger.debug(StringUtil.getStackTraceString(ex));
throw new MailReaderException("Cannot retrieve folder list. Reason: " + ex.getMessage(), ex);
}
return returnValue;
}
/**
* returns the session object to use
*
* @return the session object to use
*/
protected Session getDefaultSession() {
Properties props = (Properties) System.getProperties().clone();
props.put("mail.smtp.host", configuration.getSmtpHost());
// TODO - add needed properties - only valid for session, do not overwrite properites
// TODO - add chained properties
return Session.getInstance(props, null);
}
/**
* @return the store
*/
protected Store getStore() {
return store;
}
/**
* @param store the store to set
*/
protected void setStore(Store store) {
this.store = store;
}
/**
* returns the configuration object
*
* @return returns the configuration
*/
protected MailReaderConfiguration getConfiguration() {
return configuration;
}
/**
* returns the folder, if folder path is a valid path to an existing folder
*
* @param folderPath the folder to return
* @return the folder, if folder path is a valid path to an existing folder
*
* @throws MailReaderException if the folder cannot be found
*/
private List<Folder> getFolderPath(String folderPath) throws MailReaderException {
List<Folder> returnValue = new LinkedList<Folder>();
try {
String[] folderPathParts = folderPath.split("/");
Folder currentFolder = store.getDefaultFolder();
boolean stillExists = true;
for (int i = 0; ((i < folderPathParts.length) && (stillExists)); i++) {
currentFolder = currentFolder.getFolder(folderPathParts[i]);
stillExists = currentFolder.exists();
returnValue.add(currentFolder);
}
if (stillExists) {
return returnValue;
} else {
throw new MailReaderException("Folder " + folderPath + " not found");
}
} catch (Exception ex) {
throw new MailReaderException("Error while getting older " + folderPath + ". Reason: " + ex.getMessage(), ex);
}
}
/**
* returns the folder object defined by the folder path
*
* @param sourceFolder the full name of the folder (including path)
* @return the folder object if existent
*
* @throws MailReaderException if the folder does not exist
*/
private Folder getFolderObject(String sourceFolder) throws MailReaderException {
List<Folder> folderList = getFolderPath(sourceFolder);
return folderList.get(folderList.size() - 1);
}
/**
* returns the folder, if folder path is a valid path to an existing folder
*
* @param folderPath the folder to return
* @return the folder, if folder path is a valid path to an existing folder
*
* @throws MailReaderException if the folder cannot be found
*/
@Override
public String getFolder(String folderPath) throws MailReaderException {
String returnValue = "";
List<Folder> folderList = getFolderPath(folderPath);
for (Folder folder : folderList) {
returnValue += folder.getName() + "/";
}
if (returnValue.endsWith("/")) {
returnValue = returnValue.substring(0, returnValue.length() - 1);
}
return returnValue;
}
/**
* returns the list of subfolders of the specified source folder
*
* @param sourceFolder the folder to return the folder list for
* @return the list of subfolders of the specified source folder
*
* @throws MailReaderException if the folder list cannot be retrieved
*/
@Override
public List<String> getSubFolder(String sourceFolder) throws MailReaderException {
List<String> returnValue = new LinkedList<String>();
Folder folder = getFolderObject(sourceFolder);
try {
folder.open(Folder.READ_ONLY);
Folder[] subFolders = folder.list();
for (Folder subFolder : subFolders) {
returnValue.add(subFolder.getFullName());
}
} catch (Exception ex) {
throw new MailReaderException("Error while getting subfolders. Reason: " + ex.getMessage(), ex);
} finally {
if ((folder != null) && folder.isOpen()) {
try {
folder.close(false);
} catch (MessagingException ex) {
logger.debug(StringUtil.getStackTraceString(ex));
}
}
}
return returnValue;
}
/**
* returns the message count for the given folder
*
* @param sourceFolder the folder to return the message count for
* @return the message count for the given folder
*
* @throws MailReaderException if the amount of messages cannot be determined
*/
@Override
public int getMessageCount(String sourceFolder) throws MailReaderException {
Folder folder = getFolderObject(sourceFolder);
int messageCount;
try {
folder.open(Folder.READ_ONLY);
messageCount = folder.getMessageCount();
} catch (Exception ex) {
throw new MailReaderException("Error while getting messageCount. Reason:" + ex.getMessage(), ex);
} finally {
if ((folder != null) && folder.isOpen()) {
try {
folder.close(false);
} catch (MessagingException ex) {
logger.debug(StringUtil.getStackTraceString(ex));
}
}
}
return messageCount;
}
/**
* retrieves the list of messages stored in the given folder
*
* @param sourceFolder the folder to search return the emails for
* @return list of messages stored in the given folder
*
* @throws MailReaderException if the message list cannot be retrieved
*
*/
@Override
public List<MailMessage> getMessages(String sourceFolder) throws MailReaderException {
List<MailMessage> returnValue = new LinkedList<MailMessage>();
Folder folder = getFolderObject(sourceFolder);
try {
folder.open(Folder.READ_ONLY);
Message[] messages = folder.getMessages();
for (Message msg : messages) {
returnValue.add(MailMessageUtils.getInstance(getValidMessage(msg)));
}
} catch (Exception ex) {
throw new MailReaderException("Cannot fetch email from folder " + folder.getFullName() + ". Reason: " + ex.getMessage(), ex);
} finally {
if ((folder != null) && (folder.isOpen())) {
try {
folder.close(false);
} catch (MessagingException ex) {
logger.debug(StringUtil.getStackTraceString(ex));
}
}
}
return returnValue;
}
/**
* copies the given message from the source folder to the destination folder
*
* @param mm the message to copy
* @param sourceFolder the folder the message currently resists in
* @param destFolder the folder the message should be copied to
* @throws MailReaderException if the operation fails
*/
@Override
public void copyMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
copyMessages(mm, sourceFolder, destFolder, false);
}
/**
* moves the given message from the source folder to the destination folder
*
* @param mm the message to move
* @param sourceFolder the folder the message currently resists in
* @param destFolder the folder the message should be moved to
* @throws MailReaderException if the operation fails
*/
@Override
public void moveMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
copyMessages(mm, sourceFolder, destFolder, true);
}
/**
* marks the messages as seen
*
* @param folderName the folder to search for the email
* @param mm the message to mark as seen
* @param flagValue if set to true, the seen flag is set; otherwise it is removed (unset)
* @throws MailReaderException if the flag cannot be set
*/
@Override
public void setSeenFlag(String folderName, MailMessage mm, boolean flagValue) throws MailReaderException {
Folder folder = getFolderObject(folderName);
try {
folder.open(Folder.READ_WRITE);
Message[] msgs = getMessage(folder, mm.getMessageId());
for (Message message : msgs) {
message.setFlag(Flags.Flag.SEEN, true);
}
} catch (Exception ex) {
throw new MailReaderException("Cannot set seen flag. Reason: " + ex.getMessage(), ex);
} finally {
if ((folder != null) && (folder.isOpen())) {
try {
folder.close(false);
} catch (MessagingException ex) {
logger.debug("Error while closing folder", ex);
}
}
}
}
/**
* returns an array with one element of javax.mail.Message with the given messageid
*
* @param folder the folder to search for the message
* @param messageId messageid of the message
* @return the javax.mail.Message object for the mail with the givne messageid
*
* @throws MailReaderException if the message cannot be found or if more than one message with the same messageid exists
*/
private Message[] getMessage(Folder folder, String messageId) throws MailReaderException {
try {
SearchTerm st = new MessageIDTerm(messageId);
Message[] messages = folder.search(st);
if (messages.length != 1) {
throw new MailReaderException("Cannot find message with messageID = " + messageId);
}
return messages;
} catch (Exception ex) {
throw new MailReaderException("Cannot find message with messageID = " + messageId + ". Reason: " + ex.getMessage(), ex);
}
}
/**
* moves the given message from the source folder to the destination folder
*
* @param mm the message to move
* @param sourceFolder the folder the message currently resists in
* @param destFolder the folder the message should be moved to
* @param deleteMessage if set to true, the messages are deleted from source folder after deletion
* @throws MailReaderException if the operation fails
*/
private void copyMessages(MailMessage mm, String sourceFolder, String destFolder, boolean deleteMessage) throws MailReaderException {
Folder sf = getFolderObject(sourceFolder);
Folder df = getFolderObject(destFolder);
try {
sf.open(Folder.READ_WRITE);
df.open(Folder.READ_WRITE);
Message[] messages = getMessage(sf, mm.getMessageId());
sf.copyMessages(messages, df);
if (deleteMessage) {
for (Message message : messages) {
message.setFlag(Flags.Flag.DELETED, true);
}
}
} catch (Exception ex) {
} finally {
if ((df != null) && (df.isOpen())) {
try {
df.close(false);
} catch (MessagingException ex) {
logger.debug("Error while closing destination folder", ex);
}
}
if ((sf != null) && (sf.isOpen())) {
try {
sf.close(true);
} catch (MessagingException ex) {
logger.debug("Error while closing source folder", ex);
}
}
}
}
/**
* asures the message can be read even if the underlaying IMAP server does not handle the message correctly. see
* http://www.oracle.com/technetwork/java/faq-135477.html for details
*
* @param msg the message to read
* @return the message in a readable format
*
* @throws MessagingException if the message cannot be processed
*/
private Message getValidMessage(Message msg) throws MessagingException {
// assert message can be read
// see
MessagingException initialException;
try {
msg.getContentType();
return msg;
} catch (MessagingException ex) {
initialException = ex;
logger.debug("Direct access failed - trying workaround copy constructor");
}
try {
MimeMessage copyMsg = (MimeMessage) msg;
// Use the MimeMessage copy constructor to make a copy
// of the entire message, which will fetch the entire
// message from the server and parse it on the client:
MimeMessage cmsg = new MimeMessage(copyMsg);
cmsg.getContentType();
return cmsg;
} catch (MessagingException ex) {
logger.debug("Access via copy constructor failed, trying byte array constructor");
}
try {
Session session = getDefaultSession();
// Copy the message by writing into an byte array and
// creating a new MimeMessage object based on the contents
// of the byte array:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
msg.writeTo(bos);
bos.close();
SharedByteArrayInputStream bis =
new SharedByteArrayInputStream(bos.toByteArray());
MimeMessage cmsg = new MimeMessage(session, bis);
bis.close();
return cmsg;
} catch (Exception ex) {
logger.debug("Also fallback solution did not work");
throw initialException;
}
}
}

View File

@ -0,0 +1,315 @@
/**
* package containing containing acess to mail messages, covering javax.mail api
*/
package de.muehlencord.shared.network.mail;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
/**
* A mail message
*
* @author joern@muehlencord.de
*/
public class MailMessage {
/** the subect of the email */
private String subject;
/** the content of the message */
private List<String> content;
/** the html content of the message if avaialble, null else */
private List<String> htmlContent;
/** true, if content is html message body */
private boolean isHtmlMessage;
/** the message id if available, null otherwise */
private String messageId;
/** the size of the message in bytes */
private int size;
/** the date the message was sent */
private Date sentDate;
/** the sender of the email */
private String sender;
/** the list of receivers */
private List<String> receiver;
/** the list of CC receivers */
private List<String> ccReceiver;
/** the list of BCCC receivers */
private List<String> bccReceiver;
// TODO add replyTo, add attachmentSupport
/**
* creates a new instance of a MailMessage
*
* @param subj the subject of the message
* @param contentString the content of the message
*/
public MailMessage(String subj, String contentString) {
this.subject = subj;
this.content = new LinkedList<String>();
if (contentString != null) {
content.add(contentString);
}
this.htmlContent = new LinkedList<String>();
this.isHtmlMessage = false;
this.messageId = null;
this.sender = null;
this.receiver = new LinkedList<String>();
this.ccReceiver = new LinkedList<String>();
this.bccReceiver = new LinkedList<String>();
}
/** creates a new instance of MaiLmessage
*
* @param subj the subject of the message
* @param contentString the content of the message
* @param id the message id the message was sent with
*/
public MailMessage(String subj, String contentString, String id) {
this(subj, contentString);
this.messageId = id;
}
/* *** getter / setter *** */
/**
* @return the subject
*/
public String getSubject() {
return subject;
}
/**
* @return the content
*/
public String getContent() {
return getContent(content);
}
private String getContent(List<String> contentList) {
String returnValue = "";
String contentSeparator = "--------";
for (String currentContent : contentList) {
returnValue += currentContent;
returnValue += contentSeparator; // FIXME make configurable
}
if (returnValue.endsWith(contentSeparator)) {
returnValue = returnValue.substring(0, returnValue.length() - contentSeparator.length());
}
return returnValue;
}
/**
* sets the content string of the message
*
* @param c the content to set
* @param isHtmlContent if set to true, given content is treated as html content
*/
public void setContent(String c, boolean isHtmlContent) {
if (c != null) {
content.add(c);
this.isHtmlMessage = isHtmlContent;
if (isHtmlContent) {
this.htmlContent.add(c);
}
}
}
/**
* sets the html content of the message
*
* @param c the content to set (html string)
*/
public void setHtmlContent(String c) {
this.htmlContent.add(c);
}
/**
* returns the html content string
*
* @return the html content string
*/
public String getHtmlContent() {
return getContent(htmlContent);
}
/**
* @return the isHtmlMessage
*/
public boolean isHtmlMessage() {
return isHtmlMessage;
}
/**
* @return the messageId
*/
public String getMessageId() {
return messageId;
}
/**
* sets the size of the message in bytes
*
* @param messageSize the size of the message in bytes
*/
public void setSize(int messageSize) {
this.size = messageSize;
}
/**
* @return the message size in bytes
*/
public int getSize() {
return size;
}
/**
* @return the sentDate
*/
public Date getSentDate() {
return new Date(sentDate.getTime());
}
/**
* @param date the sentDate to set
*/
public void setSentDate(Date date) {
this.sentDate = new Date(date.getTime());
}
/**
* @return the sender
*/
public String getSender() {
return sender;
}
/**
* sets the sender address
*
* @param sender the sender to set
*
*/
public void setSender(String sender) {
this.sender = sender;
}
/**
* sets the sender address
*
* @param sender the sender to set
*/
public void setSender(Address[] sender) {
if (sender.length > 0) {
this.sender = getEmailAddress(sender[0]);
}
}
/**
* @return the receiver
*/
public List<String> getReceiver() {
return receiver;
}
/**
* @param rcv the receiver to set
*/
public void addReceiver(String rcv) {
this.receiver.add(rcv);
}
/**
* adds the given receiver to the list of receivers
*
* @param rcvList the receiver to add
*/
public void addReceiver(List<String> rcvList) {
this.receiver.addAll(rcvList);
}
/**
* adds the give list of addresses to the receiver list
*
* @param addresses the addresses to add
*/
public void addReceiver(Address[] addresses) {
if (addresses != null) {
for (Address currentAddress : addresses) {
addReceiver(getEmailAddress(currentAddress));
}
}
}
/**
* @return the ccReceiver
*/
public List<String> getCcReceiver() {
return ccReceiver;
}
/**
* @param rcv the ccReceiver to set
*/
public void addCcReceiver(String rcv) {
this.ccReceiver.add(rcv);
}
/**
* adds the give list of addresses to the cc receiver list
*
* @param addresses the addresses to add
*/
public void addCcReceiver(Address[] addresses) {
if (addresses != null) {
for (Address currentAddress : addresses) {
addCcReceiver(getEmailAddress(currentAddress));
}
}
}
/**
* @return the bccReceiver
*/
public List<String> getBccReceiver() {
return bccReceiver;
}
/**
* @param rcv the bccReceiver to set
*/
public void addBccReceiver(String rcv) {
this.bccReceiver.add(rcv);
}
/**
* adds the give list of addresses to the bcc receiver list
*
* @param addresses the addresses to add
*/
public void addBccReceiver(Address[] addresses) {
if (addresses != null) {
for (Address currentAddress : addresses) {
addBccReceiver(getEmailAddress(currentAddress));
}
}
}
/**
* returns the email adddress of the givne address
*
* @param currentAddress the address to get
* @return the email adddress of the givne address as string
*/
private String getEmailAddress(Address currentAddress) {
if (currentAddress instanceof InternetAddress) {
InternetAddress address = (InternetAddress) currentAddress;
return address.getAddress();
} else {
return currentAddress.toString();
}
}
}

View File

@ -0,0 +1,41 @@
package de.muehlencord.shared.network.mail;
/**
* Exception used during mail handling
* @author joern@muehlencord.de
*/
public class MailMessageException extends Exception {
/**
*
*/
private static final long serialVersionUID = 6699249884047524285L;
/**
* Creates a new instance of
* <code>MailMessageException</code> without detail message.
*/
public MailMessageException() {
}
/**
* Constructs an instance of
* <code>MailMessageException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public MailMessageException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>MailMessageException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing Throwable
*/
public MailMessageException(String msg, Throwable th) {
super(msg,th);
}
}

View File

@ -0,0 +1,326 @@
/**
* wrapper classes around javax.mail package
* written by Joern Muehlencord
*
*/
package de.muehlencord.shared.network.mail;
import de.muehlencord.shared.util.StringUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.log4j.Logger;
/**
* Util class to convert between javax.mail.Message and MailMessage objects
* @author joern@muehlencord.de
*/
public abstract class MailMessageUtils {
/** the logging object */
private static final Logger logger = Logger.getLogger(MailMessageUtils.class.getName());
/** content type of mutipart messages - e.g. multipart_alternative or _mixed */
private static final String CONTENTTYPE_MULTIPART = "multipart/";
/** content type of text messages - like text/plain or text/html */
private static final String CONTENTTYPE_TEXT = "text/";
/** content type of text/plain messages */
private static final String CONTENTTYPE_TEXT_PLAIN = "text/plain";
/** content type of text/html messages */
private static final String CONTENTTYPE_TEXT_HTML = "text/html";
/** content type of application based messages - e.g. application/pdf */
private static final String CONTENTTYPE_APPLICATION = "application/";
/** content type of application pgp-signature */
private static final String CONTENTTYPE_APPLICATION_PGPSIGNATURE = "application/pgp-signature";
/** content type of embedded message */
private static final String CONTENTTYPE_MESSAGE = "message/";
/** content type of attached images */
private static final String CONTENTTYPE_IMAGE = "image/";
/** content type of attached videos */
private static final String CONTENTTYPE_VIDEO = "video/";
/** content type of attached audios */
private static final String CONTENTTYPE_AUDIO = "audio/";
/**
* creates a new instance of MailMessage based on the given javax.mail.Message object
*
* @param message the message object to create the message from
* @return the MailMessage object created from the given javax.mail.Message
*
* @throws MailMessageException if the message cannot be created
*/
public static MailMessage getInstance(Message message) throws MailMessageException {
MailMessage returnMessage = null;
if (message instanceof MimeMessage) {
MimeMessage mm = (MimeMessage) message;
String contentType;
String subject;
String messageId;
try {
contentType = getContentType(mm.getContentType());
subject = mm.getSubject();
logger.debug("message subject = " + subject);
messageId = getMessageId(message);
logger.debug("messageid = " + messageId);
logger.debug(mm.getSentDate());
} catch (MessagingException ex) {
throw new MailMessageException("Error while converting mime message. Reason: " + ex.getMessage(), ex);
}
logger.debug("messageContentType = " + contentType);
// handling multipart messages
if (contentType.contains(CONTENTTYPE_MULTIPART)) {
returnMessage = new MailMessage(subject, null, messageId);
try {
Multipart mp = (Multipart) mm.getContent();
int partsFound = mp.getCount();
logger.debug(partsFound + " parts found");
for (int i = 0; i < partsFound; i++) {
logger.debug("Working on multiPart " + (i + 1));
BodyPart bp = mp.getBodyPart(i);
String bodyContentType = getContentType(bp.getContentType());
logger.debug("contentType = " + bodyContentType);
if (bodyContentType.contains(CONTENTTYPE_MULTIPART)) {
MimeMultipart bodyMultiPart = (MimeMultipart) bp.getContent();
int bodyPartCount = bodyMultiPart.getCount();
logger.debug(bodyPartCount + " bodyMultiParts found");
for (int currentBodyPart = 0; currentBodyPart < bodyPartCount; currentBodyPart++) {
logger.debug("Working on bodypart " + (currentBodyPart + 1));
BodyPart bodyPart = bodyMultiPart.getBodyPart(currentBodyPart);
String bodyPartContentType = getContentType(bodyPart.getContentType());
logger.debug("bodyPart contentType = " + bodyPartContentType);
if (bodyPartContentType.contains(CONTENTTYPE_TEXT_PLAIN)) {
returnMessage.setContent(getContent(bodyPart), false);
} else if (bodyPartContentType.contains(CONTENTTYPE_TEXT_HTML)) {
returnMessage.setHtmlContent(getContent(bodyPart));
}
}
} else if (bodyContentType.equals(CONTENTTYPE_TEXT_PLAIN)) {
if (bp.getFileName() == null) {
returnMessage.setContent(getContent(bp), false);
} else {
logger.debug("Found base64 coded attachment - not yet supported, skipping");
}
} else if (bodyContentType.equals(CONTENTTYPE_TEXT_HTML)) {
returnMessage.setHtmlContent(getContent(bp));
} else if (bodyContentType.equals(CONTENTTYPE_APPLICATION_PGPSIGNATURE)) {
logger.debug("Found pgp signature - not yet supported, skipping");
// TODO add pgp/signature support
} else if ((bodyContentType.contains(CONTENTTYPE_APPLICATION) || (bodyContentType.contains(CONTENTTYPE_MESSAGE))
|| (bodyContentType.contains(CONTENTTYPE_TEXT)) || (bodyContentType.contains(CONTENTTYPE_IMAGE))
|| (bodyContentType.contains(CONTENTTYPE_VIDEO)) || (bodyContentType.contains(CONTENTTYPE_AUDIO)))) {
logger.debug("Found attachment - not yet supported, skipping");
// TODO add attachment support
} else {
throw new MailMessageException("Reading bodyContentType " + bodyContentType + " not yet implemented");
}
} // for all parts
// asure content is set even if message contains html part only
if ((returnMessage.getContent() == null) && (returnMessage.getHtmlContent() != null)) {
returnMessage.setContent(returnMessage.getHtmlContent(), true);
}
if ((returnMessage.getContent() == null) && (returnMessage.getHtmlContent() == null)) {
throw new MailMessageException("Neither plain/text nor text/html content found. Unsupported message format");
}
} catch (Exception ex) {
throw new MailMessageException("Error while converting multipart mime message. Reason: " + ex.getMessage(), ex);
}
} else if (contentType.equals(CONTENTTYPE_TEXT_PLAIN)) {
// plain/text mimmessage
try {
returnMessage = new MailMessage(subject, mm.getContent().toString(), messageId);
} catch (Exception ex) {
throw new MailMessageException("Error while converting plain/text mime message. Reason: " + ex.getMessage(), ex);
}
} else if (contentType.equals(CONTENTTYPE_TEXT_HTML)) {
// plain/text mimmessage
try {
String contentString = mm.getContent().toString();
returnMessage = new MailMessage(subject, null, messageId);
returnMessage.setContent(contentString, true);
// returnMessage.setContent(mm.getContent().toString(), false);
} catch (Exception ex) {
throw new MailMessageException("Error while converting plain/text mime message. Reason: " + ex.getMessage(), ex);
}
} else if (contentType.contains(CONTENTTYPE_MESSAGE)) {
try {
Message nestedMessage = (Message) mm.getContent();
returnMessage = getInstance(nestedMessage);
} catch (Exception ex) {
throw new MailMessageException("Error while converting nested message. Reason: " + ex.getMessage(), ex);
}
} else if (contentType.contains(CONTENTTYPE_APPLICATION)) {
// message with only attachment
returnMessage = new MailMessage(subject, "", messageId);
logger.debug("Found attachment - not yet supported, skipping"); // TODO add attachment
} else if (contentType.contains(CONTENTTYPE_TEXT)) {
returnMessage = new MailMessage(subject, "", messageId);
logger.debug("Found attachment - not yet supported, skipping"); // TODO add attachment
} else {
String hint = "Unkonwn message format Converting MimeMessage of contentType " + contentType + " not yet implemented.";
try {
logger.debug(mm.getContent().getClass());
logger.debug(mm.getContent());
logger.error(hint);
} catch (Exception ex) {
logger.error(hint);
}
throw new MailMessageException(hint);
}
} else if (message instanceof Message) {
try {
String content = message.getContent().toString();
String subject = message.getSubject();
returnMessage = new MailMessage(subject, content);
} catch (Exception ex) {
throw new MailMessageException("Error whilec converting email. Reason: " + ex.getMessage(), ex);
}
} else {
throw new MailMessageException("Unsupported messagetype " + message.getClass().toString() + ". Cannot create message");
}
// TODO add missing parameters
// messageid
try {
returnMessage.addReceiver(message.getRecipients(Message.RecipientType.TO));
returnMessage.addCcReceiver(message.getRecipients(Message.RecipientType.CC));
returnMessage.addBccReceiver(message.getRecipients(Message.RecipientType.BCC));
returnMessage.setSender(message.getFrom());
returnMessage.setSentDate(message.getSentDate());
returnMessage.setSize(message.getSize());
} catch (Exception ex) {
throw new MailMessageException("Cannot read email. Reason: " + ex.getMessage(), ex);
}
return returnMessage;
}
/**
* returns the content type based on the content-type header. The messad asures the contentype
* is selected correctly from the string, including trim and tolower case
* @param contentType the contenttype string read from email header
* @return the content type of the email (small letters)
*/
private static String getContentType(String contentType) {
if (contentType.contains(";")) {
contentType = contentType.substring(0, contentType.indexOf(';'));
}
contentType = contentType.toLowerCase();
contentType = contentType.trim();
return contentType;
}
/**
* returns the content of the given bodypart which needs to be a text based bodypart
* The method tries to read the messages as it is. In case of an unsupported encoding it reads the message with
* the default encoding (accepting "ugly" characters)
* @param bp the body part to read the content from
* @return the content of the body part
* @throws IOException if the content cannot be read
* @throws MessagingException if the message cannot be processed
*/
private static String getContent(BodyPart bp) throws IOException, MessagingException {
String returnValue = null;
try {
returnValue = bp.getContent().toString();
} catch (java.io.UnsupportedEncodingException ex) {
logger.debug(ex.getMessage());
} catch (java.io.IOException ioex) {
throw new IOException("Cannot read content from bodypart.", ioex);
} catch (MessagingException mex) {
throw new MessagingException("Cannot read content from bodypart.", mex);
}
if (returnValue == null) {
return getContentByStream(bp, "UTF-8"); // TODO make configurable
} else {
return returnValue;
}
}
/**
* returns the content of the given body part by reading the stream directly. This ommits getting unsupported encoding exceptions, as the content
* is read with the given encoding
* @param bp the bodypart to read the content from
* @param encoding the encoding to force
* @return the content string read with the given encoding
* @throws IOException if the content cannot be read
* @throws MessagingException if the message cannot be processed
*/
private static String getContentByStream(BodyPart bp, String encoding) throws IOException, MessagingException {
String returnValue;
Reader input = null;
StringWriter output = null;
try {
input = new BufferedReader(new InputStreamReader(bp.getInputStream(), encoding));
output = new StringWriter();
char[] b = new char[4096];
while (input.read(b) != -1) {
output.write(b);
}
returnValue = output.toString();
} catch (IOException ioex) {
throw new IOException("Cannot read content from bodypart by reading content stream.", ioex);
} finally {
try {
output.close();
} catch (IOException ex) {
logger.debug(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
}
try {
input.close();
} catch (IOException ex) {
logger.debug(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
}
}
return returnValue;
}
/**
* returns the message id from the header of the given message
* @param message the message to return the message id from
* @return either the message id or null if the message id cannot be read
* @throws MessagingException if the message cannot be processed
*/
private static String getMessageId(Message message) throws MessagingException {
String[] messageHeaders = message.getHeader("Message-Id");
if ((messageHeaders != null) && (messageHeaders.length > 0)) {
return messageHeaders[0];
} else {
return null;
}
}
}

View File

@ -0,0 +1,103 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.mail;
import java.util.List;
import javax.mail.Folder;
/**
*
* @author joern@muehlencord.de
*/
public interface MailReader {
/** connects to the mailbox
*
* @throws MailReaderConnectionException if he connection cannot be established
*/
void connect() throws MailReaderConnectionException;
/** disconnects from mailbox */
void disconnect();
/** returns the default folder
*
* @return the default folder
*
* @throws MailReaderException if the folder cannot be retrieved
*/
String getDefaultFolder() throws MailReaderException;
/**
* returns the list of subfolders of the specified source folder
*
* @param sourceFolder the folder to return the folder list for
* @return the list of subfolders of the specified source folder
*
* @throws MailReaderException if the folder list cannot be retrieved
*/
List<String> getSubFolder(String sourceFolder) throws MailReaderException;
/**
* returns the folder, if folder path is a valid path to an existing folder
*
* @param folderPath the folder to return
* @return the folder, if folder path is a valid path to an existing folder
*
* @throws MailReaderException if the folder cannot be found
*/
String getFolder(String folderPath) throws MailReaderException;
/**
* returns the amount of message in the given folder
*
* @param holdFolder the folder to return the amount of messages for
* @return the amount of message in the given folder
*
* @throws MailReaderException if the folder cannot be accessed or the amount of messages cannot be determined
*/
int getMessageCount(String holdFolder) throws MailReaderException;
/**
* retrieves the list of messages stored in the given folder
*
* @param folder the folder to search return the emails for
* @return list of messages stored in the given folder
*
* @throws MailReaderException if the message list cannot be retrieved
*
*/
List<MailMessage> getMessages(String folder) throws MailReaderException;
/**
* copies the given message from the source folder to the destination folder
*
* @param mm the message to copy
* @param sourceFolder the folder the message currently resists in
* @param destFolder the folder the message should be copied to
* @throws MailReaderException if the operation fails
*/
void copyMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException;
/**
* moves the given message from the source folder to the destination folder
*
* @param mm the message to move
* @param sourceFolder the folder the message currently resists in
* @param destFolder the folder the message should be moved to
* @throws MailReaderException if the operation fails
*/
void moveMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException;
/**
* marks the messages as seen
*
* @param folder the folder to search for the email
* @param mm the message to mark as seen
* @param flagValue if set to true, the seen flag is set; otherwise it is removed (unset)
* @throws MailReaderException if the flag cannot be set
*/
void setSeenFlag(String folder, MailMessage mm, boolean flagValue) throws MailReaderException;
}

View File

@ -0,0 +1,61 @@
package de.muehlencord.shared.network.mail;
/**
*
* @author Joern Muehlencord
*/
public class MailReaderConfiguration {
/** server for smtp sessions */
private String smtpHost = null;
/** server for incoming emails - e.g. the imap or pop3 server */
private String readerHost = null;
/** the username to connect with */
private String userName = null;
/** the password to connect with */
private String password = null;
// TODO add checkConfig to asure the config is valid for the reader it is attached to
/**
* creates a new config
* @param mailHost the smtp host to connect to
* @param host the mailreader host (imap, exchange, pop, ...) to connect to
* @param user the username to connect with
* @param pw the password to connect with
*/
public MailReaderConfiguration (String mailHost, String host, String user, String pw) {
this.smtpHost = mailHost;
this.readerHost = host;
this.userName = user;
this.password = pw;
}
/**
* @return the smtpHost
*/
public String getSmtpHost() {
return smtpHost;
}
/**
* @return the readerHost
*/
public String getReaderHost() {
return readerHost;
}
/**
* @return the userName
*/
public String getUserName() {
return userName;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
}

View File

@ -0,0 +1,41 @@
package de.muehlencord.shared.network.mail;
/**
*
* @author joern@muehlencord.de
*/
public class MailReaderConfigurationException extends Exception {
/**
*
*/
private static final long serialVersionUID = 3874572911465653501L;
/**
* Creates a new instance of
* <code>MailReaderConfigurationException</code> without detail message.
*/
public MailReaderConfigurationException() {
}
/**
* Constructs an instance of
* <code>MailReaderConfigurationException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public MailReaderConfigurationException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>MailReaderConfigurationException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public MailReaderConfigurationException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,68 @@
package de.muehlencord.shared.network.mail;
import de.muehlencord.shared.util.StringUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import org.apache.log4j.Logger;
/**
*
* @author joern@muehlencord.de
*/
public abstract class MailReaderConfigurationFactory {
/** the logging object */
private final static Logger logger = Logger.getLogger(MailReaderConfigurationFactory.class.getName());
/**
* reads the config file and creates a configured mailreader configuration
*
* @param configFile the file to read
* @return the configured MailReaderConfiguration object
*
* @throws MailReaderConfigurationException if the file does not exist or the config cannot be created
*/
public static MailReaderConfiguration getConfiguration(String configFile) throws MailReaderConfigurationException {
File f = new File(configFile);
if (!f.exists()) {
throw new MailReaderConfigurationException("Cannot find configfile " + configFile);
}
Properties p = new Properties();
InputStream is = null;
try {
is = new FileInputStream(f);
p.load(is);
} catch (Exception ex) {
throw new MailReaderConfigurationException("Error while reading config file. Reason: " + ex.getMessage(), ex);
} finally {
try {
is.close();
} catch (Exception ex) {
logger.error("Error while reading input file.");
logger.debug(StringUtil.getStackTraceString(ex));
}
}
String smtpServer = p.getProperty("smtp.server");
if ((smtpServer == null) || (smtpServer.isEmpty())) {
throw new MailReaderConfigurationException("property smtp.server not specified. Please check config");
}
String host = p.getProperty("imap.server");
if ((smtpServer == null) || (smtpServer.isEmpty())) {
throw new MailReaderConfigurationException("property imap.server not specified. Please check config");
}
String userName = p.getProperty("imap.username");
if ((smtpServer == null) || (smtpServer.isEmpty())) {
throw new MailReaderConfigurationException("property imap.username not specified. Please check config");
}
String password = p.getProperty("imap.password");
if ((smtpServer == null) || (smtpServer.isEmpty())) {
throw new MailReaderConfigurationException("property imap.password not specified. Please check config");
}
return new MailReaderConfiguration(smtpServer, host, userName, password);
}
}

View File

@ -0,0 +1,45 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.mail;
/**
*
* @author jomu
*/
public class MailReaderConnectionException extends Exception {
/**
*
*/
private static final long serialVersionUID = -1593741665654202661L;
/**
* Creates a new instance of
* <code>MailReaderConnectionException</code> without detail message.
*/
public MailReaderConnectionException() {
}
/**
* Constructs an instance of
* <code>MailReaderConnectionException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public MailReaderConnectionException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>MailReaderConnectionException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing error
*/
public MailReaderConnectionException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,45 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.mail;
/**
*
* @author jomu
*/
public class MailReaderException extends Exception {
/**
*
*/
private static final long serialVersionUID = 4850689622364462635L;
/**
* Creates a new instance of
* <code>MailReaderException</code> without detail message.
*/
public MailReaderException() {
}
/**
* Constructs an instance of
* <code>MailReaderException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public MailReaderException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>MailReaderException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public MailReaderException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,54 @@
package de.muehlencord.shared.network.mail.imap;
import de.muehlencord.shared.network.mail.DefaultMailReader;
import de.muehlencord.shared.network.mail.MailReaderConfiguration;
import de.muehlencord.shared.network.mail.MailReaderConnectionException;
import javax.mail.Session;
import org.apache.log4j.Logger;
/**
* Implementation of MaiLReader to connect to an IMAP server
*
* @author joern@muehlencord.de
*/
public class ImapMailReader extends DefaultMailReader {
/** the logger object */
private final static Logger logger = Logger.getLogger(ImapMailReader.class);
/**
* creates a new instance to connect to an IMAP (or MS Exchange) server
*
* @param config the configuration of the mail reader
*/
public ImapMailReader(MailReaderConfiguration config) {
super(config);
}
@Override
public void connect() throws MailReaderConnectionException {
Session session = getDefaultSession();
String hostName = getConfiguration().getReaderHost();
String userName = getConfiguration().getUserName();
String password = getConfiguration().getPassword();
try {
setStore(session.getStore("imap")); // TODO add ssl support
getStore().connect(hostName, userName, password);
} catch (Exception ex) {
String hint = "Error while connecting to mailbox " + getConnectionShortCut();
hint += ". Reason: " + ex.getMessage();
throw new MailReaderConnectionException(hint, ex);
}
logger.info("Connected to " + getConnectionShortCut());
}
/**
* returns userName@hostname
*
* @return userName@hostname
*/
private String getConnectionShortCut() {
return getConfiguration().getUserName() + "@" + getConfiguration().getReaderHost();
}
}

View File

@ -0,0 +1,22 @@
package de.muehlencord.shared.network;
import java.net.URL;
import org.apache.log4j.PropertyConfigurator;
import org.junit.BeforeClass;
/**
*
* @author joern@muehlencord.de
*/
public class BaseTest {
/**
* inits logging according to default setup in package
*/
@BeforeClass
public static void initLogging() {
URL defaultConfigUrl = BaseTest.class.getResource("/logging.properties");
PropertyConfigurator.configure(defaultConfigUrl);
}
}

View File

@ -0,0 +1,152 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.ftp;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
*
* @author jomu
*/
public class FTPConnectionTest {
/** the properties loaded from the config file */
Properties props = null;
/** true, if init is complete to execute test */
boolean initDone = false;
@Before
public void initClass() {
System.out.println("\n[FTPConnectionTest]");
URL testConfigURL = FTPConnectionTest.class.getResource("/test.properties");
FileInputStream fin = null;
try {
File file = new File(testConfigURL.toURI());
props = new Properties();
if ((file == null) || (!file.exists())) {
initDone = false;
} else {
fin = new FileInputStream(file);
props.load(fin);
}
if ((props.containsKey("ftp.host")) && (props.containsKey("ftp.user")) && (props.containsKey("ftp.password")) && (props.containsKey("ftp.locale"))) {
initDone = true;
} else {
initDone = false;
}
} catch (Exception ex) {
initDone = false;
} finally {
try {
if (fin != null) {
fin.close();
}
} catch (IOException ex) {
Logger.getLogger(FTPConnectionTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/** tests connect / disconnect */
@Test
public void testConnectAndDisconnect() throws FTPConnectionException {
System.out.println("testConnectAndDisconnect");
if (initDone) {
String remoteHost = props.getProperty("ftp.host");
String user = props.getProperty("ftp.user");
String password = props.getProperty("ftp.password");
Locale locale = new Locale(props.getProperty("ftp.locale"));
FTPConnection con = new FTPConnection(remoteHost, user, password, locale);
con.connect();
con.disconnect();
System.out.println("executed successfully");
} else {
System.out.println("Skipped because config is not complete");
}
}
@Test
@Ignore
public void testList() throws FTPConnectionException {
System.out.println("list");
String dir = "";
FTPConnection instance = null;
List expResult = null;
List result = instance.list(dir);
assertEquals(expResult, result);
fail("The test case is a prototype.");
}
@Test
@Ignore
public void testListDirsOnly() throws FTPConnectionException {
System.out.println("listDirsOnly");
String dir = "";
FTPConnection instance = null;
List expResult = null;
List result = instance.listDirsOnly(dir);
assertEquals(expResult, result);
fail("The test case is a prototype.");
}
@Test
@Ignore
public void testListFilesOnly() throws FTPConnectionException {
System.out.println("listFilesOnly");
String dir = "";
FTPConnection instance = null;
List expResult = null;
List result = instance.listFilesOnly(dir);
assertEquals(expResult, result);
fail("The test case is a prototype.");
}
@Test
@Ignore
public void testListLinksOnly() throws FTPConnectionException {
System.out.println("listLinksOnly");
String dir = "";
FTPConnection instance = null;
List expResult = null;
List result = instance.listLinksOnly(dir);
assertEquals(expResult, result);
fail("The test case is a prototype.");
}
@Test
@Ignore
public void testUploadFile() throws FTPConnectionException {
System.out.println("uploadFile");
String localFilename = "";
String remoteFileName = "";
FTPConnection instance = null;
instance.uploadFile(localFilename, remoteFileName);
}
@Test
@Ignore
public void testRename() throws FTPConnectionException {
System.out.println("rename");
String remoteOldName = "";
String remoteNewName = "";
FTPConnection instance = null;
instance.rename(remoteOldName, remoteNewName);
fail("The test case is a prototype.");
}
}

View File

@ -0,0 +1,85 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.http;
import de.muehlencord.shared.network.BaseTest;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
import org.junit.Test;
/**
*
* @author jomu
*/
public class HttpLayerTest extends BaseTest {
@Test
@Ignore
public void testPostByMap() throws Exception {
System.out.println("testPostByMap");
Map<String, String[]> map = new HashMap<String, String[]>();
String[] value = {"Hello World!", "Hello World again"};
map.put("message", value);
HttpLayer httpLayer = new HttpLayer(
"http://localhost:8080/HttpPostListener/HttpPostListener");
httpLayer.post(map);
}
@Test
@Ignore
public void testPostByMapList() throws Exception {
System.out.println("testPostByMapList");
List<Map<String, String[]>> list = new LinkedList<Map<String, String[]>>();
Map<String, String[]> map = new HashMap<String, String[]>();
String[] value = {"Hello World!", "Hello World again"};
map.put("message", value);
list.add(map);
map = new HashMap<String, String[]>();
String[] urlValue = {"http://localhost:8080/testurl"};
map.put("url", urlValue);
list.add(map);
HttpLayer httpLayer = new HttpLayer("http://localhost:8080/HttpPostListener/HttpPostListener");
httpLayer.post(list);
}
@Test
@Ignore
public void testByValue() throws Exception {
System.out.println("testByValue");
HttpLayer httpLayer = new HttpLayer(
"http://localhost:8080/HttpPostListener/HttpPostListener");
httpLayer.post("message", "Hello World by single parameter");
}
@Test(expected = MessageNotSendException.class)
public void testWithUnknownURL() throws MessageNotSendException {
System.out.println("testWithUnknownURL");
HttpLayer httpLayer = new HttpLayer(
"http://localhost/thisURLDoesNotExist");
httpLayer.post("message", "Hello World by single parameter");
}
@Test(expected = MessageNotSendException.class)
public void testInvalidURL() throws MessageNotSendException {
System.out.println("testInvalidURL");
HttpLayer httpLayer = new HttpLayer("joern@muehlencord.de");
httpLayer.post("message", "Hello World by single parameter");
}
@Test(expected = MessageNotSendException.class)
public void testUnsupportedURL() throws MessageNotSendException {
System.out.println("testUnsupportedURL");
HttpLayer httpLayer = new HttpLayer("ftp://localhost");
httpLayer.post("message", "Hello World by single parameter");
}
}

View File

@ -0,0 +1,43 @@
package de.muehlencord.shared.network.mail;
import de.muehlencord.shared.network.BaseTest;
import de.muehlencord.shared.network.mail.imap.ImapMailReader;
import java.io.File;
import java.net.URL;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author joern@muehlencord.de
*/
public class MailMessageUtilsTest extends BaseTest {
@Before
public void setup() {
System.out.println ("\n[MailMessageUtilsTest]");
}
@Test
public void testGetInstance() throws Exception {
System.out.println("testGetInstance");
URL testConfigURL = MailMessageUtilsTest.class.getResource("/test.properties");
File file = new File(testConfigURL.toURI());
if ((file == null) || (!file.exists())) {
return; // Skip test if config file is not available
}
String testConfigFile = file.toString();
MailReaderConfiguration config = MailReaderConfigurationFactory.getConfiguration(testConfigFile);
MailReader mr = new ImapMailReader(config);
mr.connect();
List<MailMessage> mm = mr.getMessages("INBOX");
mr.disconnect();
assertNotNull(mm);
assertTrue(mm.size() > 0);
}
}

View File

@ -0,0 +1,78 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.network.mail.imap;
import de.muehlencord.shared.network.BaseTest;
import de.muehlencord.shared.network.mail.MailReader;
import de.muehlencord.shared.network.mail.MailReaderConfiguration;
import de.muehlencord.shared.network.mail.MailReaderConnectionException;
import de.muehlencord.shared.network.mail.MailReaderException;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author jomu
*/
public class ImapMailReaderTest extends BaseTest {
/**
* tests the connection of the configured mailbox
*
* @throws Exception if the tests fails
*/
@Test
public void testConnect() throws Exception {
System.out.println("connect");
String meta = "meta.muehlencord.intra";
MailReaderConfiguration config = new MailReaderConfiguration(meta, meta, "jomutest", "jomutest");
MailReader instance = new ImapMailReader(config);
instance.connect();
instance.disconnect();
}
@Test
public void testGetFolder() throws Exception {
System.out.println("getFolder");
String meta = "meta.muehlencord.intra";
MailReaderConfiguration config = new MailReaderConfiguration(meta, meta, "jomutest", "jomutest");
MailReader instance = new ImapMailReader(config);
instance.connect();
String testFolder = "INBOX/test/test1";
String foundFolder = instance.getFolder(testFolder);
assertEquals(testFolder, foundFolder);
instance.disconnect();
}
@Test
public void testGetMessageCount() throws MailReaderConnectionException, MailReaderException {
System.out.println("testGetMessageCount");
String meta = "meta.muehlencord.intra";
MailReaderConfiguration config = new MailReaderConfiguration(meta, meta, "jomutest", "jomutest");
MailReader instance = new ImapMailReader(config);
instance.connect();
int value = instance.getMessageCount("INBOX/test/test1");
assertEquals(3, value);
instance.disconnect();
}
@Test
public void testGetSubFolder() throws MailReaderConnectionException, MailReaderException {
System.out.println("getSubFolder");
String meta = "meta.muehlencord.intra";
MailReaderConfiguration config = new MailReaderConfiguration(meta, meta, "jomutest", "jomutest");
MailReader instance = new ImapMailReader(config);
instance.connect();
List<String> subFolders = instance.getSubFolder("INBOX/test");
assertEquals(2, subFolders.size());
System.out.println(subFolders.toString());
assertTrue(subFolders.contains("INBOX.test.test1"));
assertTrue(subFolders.contains("INBOX.test.test2"));
instance.disconnect();
}
}

View File

@ -0,0 +1,8 @@
log4j.rootLogger=ALL, ConsoleLogger
log4j.debug=false
# ConsoleAppender
log4j.appender.ConsoleLogger=org.apache.log4j.ConsoleAppender
log4j.appender.ConsoleLogger.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleLogger.layout.ConversionPattern= %d - %m (%c)%n
log4j.appender.ConsoleLogger.threshold=INFO

View File

@ -0,0 +1,13 @@
## connection to smtp server
smtp.server=meta.muehlencord.intra
## connection to imap server
imap.server=meta.muehlencord.intra
imap.username=jomutest
imap.password=jomutest
## ftp connection data
#ftp.host=
#ftp.user=
#ftp.password=
ftp.locale=en_EN

View File

@ -0,0 +1,15 @@
## connection to smtp server
smtp.server=meta.muehlencord.intra
## connection to imap server
imap.server=meta.muehlencord.intra
#imap.username=jomutest
#imap.password=jomutest
imap.username=jomu
imap.password=fR4vbHuL
## ftp connection data
ftp.host=ftp.bytecamp.net
ftp.user=asverked
ftp.password=76z0fs9Bsx
ftp.locale=en_EN