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,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.checkstyle.format>true</netbeans.checkstyle.format>
</properties>
</project-shared-configuration>

44
configuration/pom.xml Normal file
View File

@ -0,0 +1,44 @@
<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-configuration</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<name>shared-configuration</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,51 @@
package de.muehlencord.shared.configuration;
import de.muehlencord.shared.configuration.converter.BooleanStringConverter;
/**
* A Boolean parameter
* @author joern@muehlencord.de
*/
public class BooleanParameter extends Parameter<Boolean> {
/**
* creates a new mandatory parameter object using default string converter
*
* @param name the name of the parameter
*/
public BooleanParameter(String name) {
super(name, new BooleanStringConverter(), true);
}
/**
* creates a new mandatory parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public BooleanParameter(String name, StringConverter<Boolean> converter) {
super(name, converter, true);
}
/**
* creates a new parameter object using default string converter
*
* @param name the name of the parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public BooleanParameter(String name, boolean mandatory) {
super(name, new BooleanStringConverter(), mandatory);
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public BooleanParameter(String name, StringConverter<Boolean> converter, boolean mandatory) {
super(name, converter, mandatory);
}
}

View File

@ -0,0 +1,79 @@
package de.muehlencord.shared.configuration;
/**
*
* @author jomu
*/
public interface Configuration<T, V extends T> {
/**
* adds a new parameter to the configuration
*
* @param p the parameter to add
* @throws ConfigurationException if the parameter cannot be added
*/
public void addParameter(Parameter<T> p) throws ConfigurationException;
/**
* sets the value of the given parameter
*
* @param p parameter to set
* @param value value to set
* @throws ConfigurationException if the parameter is not defined
*/
public void setParameterValue(Parameter<T> p, V value) throws ConfigurationException;
/**
* sets the value of parameter with given name
*
* @param parameterName parameter to set
* @param value value to set
* @throws ConfigurationException if the parameter is not defined
*/
public void setParameterValue(String parameterName, V value) throws ConfigurationException;
/**
* sets the value of the given parameter
*
* @param p parameter to set
* @param value value to set
* @throws ConfigurationException if the parameter is not defined
*/
public void setParameterValueByString(Parameter<T> p, String value) throws ConfigurationException;
/**
* sets the value of the given parameter
*
* @param parameterName the name of the parameter to set the value for
* @param stringValue the value of the parameter as string
* @throws ConfigurationException if the parameter cannot be found or set
*/
public void setParameterValueByString(String parameterName, String stringValue) throws ConfigurationException;
/**
* returns the value of the given parameter
*
* @param p the parameter to return the value for
* @return the value of the given parameter; null if not set
*
* @throws ConfigurationException if the parameter is not defined or if the value is not set
*/
public V getParameterValue(Parameter<T> p) throws ConfigurationException;
/**
* returns the value of the given parameter
*
* @param parameterName the name of the parameter to return the value for
* @return the value of the given parameter; null if not set
*
* @throws ConfigurationException if the parameter is not defined or if the value is not set
*/
public V getParameterValue(String parameterName) throws ConfigurationException;
/**
* validates the configuration
*
* @throws ConfigurationException if the configuration is invalid
*/
public void validateConfiguration() throws ConfigurationException;
}

View File

@ -0,0 +1,36 @@
package de.muehlencord.shared.configuration;
/**
*
* @author jomu
*/
public class ConfigurationException extends Exception {
/**
* Creates a new instance of
* <code>ParameterException</code> without detail message.
*/
public ConfigurationException() {
}
/**
* Constructs an instance of
* <code>ParameterException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public ConfigurationException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>ParameterException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the root cause
*/
public ConfigurationException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,36 @@
package de.muehlencord.shared.configuration;
/**
*
* @author jomu
*/
public class ConverterException extends Exception {
/**
* Creates a new instance of
* <code>ConverterException</code> without detail message.
*/
public ConverterException() {
}
/**
* Constructs an instance of
* <code>ConverterException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public ConverterException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>ConverterException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public ConverterException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,52 @@
package de.muehlencord.shared.configuration;
import de.muehlencord.shared.configuration.converter.DateStringConverter;
import java.util.Date;
/**
* A Date parameter
* @author joern@muehlencord.de
*/
public class DateParameter extends Parameter<Date> {
/**
* creates a new mandatory parameter object using default string converter
*
* @param name the name of the parameter
*/
public DateParameter(String name) {
super(name, new DateStringConverter(), true);
}
/**
* creates a new mandatory parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public DateParameter(String name, StringConverter<Date> converter) {
super(name, converter, true);
}
/**
* creates a new parameter object using default string converter
*
* @param name the name of the parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public DateParameter(String name, boolean mandatory) {
super(name, new DateStringConverter(), mandatory);
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public DateParameter(String name, StringConverter<Date> converter, boolean mandatory) {
super(name, converter, mandatory);
}
}

View File

@ -0,0 +1,224 @@
package de.muehlencord.shared.configuration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
*
* @param <T> the type of the parameter
* @param <V> the value of the parameter - must be the same class as the type class of the parameter
* @author joern@muehlencord.de
*/
public class DefaultConfiguration<T, V extends T> implements Configuration<T, V> {
/**
* the parameter map
*/
private Map<Parameter<T>, V> parameterMap;
/** mapping from name to parameter */
private Map<String, Parameter<T>> parameterNameMap;
/**
* creates a new instance of a configuration
*/
public DefaultConfiguration() {
parameterMap = new HashMap<Parameter<T>, V>();
parameterNameMap = new HashMap<String, Parameter<T>>();
}
/**
* returns the map of parameters and values
*
* @return the map of parameters and values
*/
protected Map<Parameter<T>, V> getParameterMap() {
return parameterMap;
}
/**
* adds a new parameter to the configuration
*
* @param p the parameter to add
* @throws ConfigurationException if the parameter cannot be added
*/
@Override
public void addParameter(Parameter p) throws ConfigurationException {
if (parameterMap.containsKey(p)) {
throw new ConfigurationException("Parameter named " + p.getName() + " already defined");
} else {
parameterMap.put(p, null);
parameterNameMap.put(p.getName(), p);
}
}
/**
* validates the configuration
*
* @throws ConfigurationException if the configuration is invalid
*/
@Override
public void validateConfiguration() throws ConfigurationException {
List<Parameter> missingMandatoryParameters = new LinkedList<Parameter>();
for (Parameter p : parameterMap.keySet()) {
if ((!validateParameter(p)) && (!missingMandatoryParameters.contains(p))) {
missingMandatoryParameters.add(p);
}
}
if (!missingMandatoryParameters.isEmpty()) {
throw new ConfigurationException("Configuration invalid, mandatory parameters missing: " + missingMandatoryParameters.toString());
}
}
/**
* sets the value of the given parameter
*
* @param p parameter to set
* @param value value to set
* @throws ConfigurationException if the parameter is not defined
*/
@Override
public void setParameterValue(Parameter<T> p, V value) throws ConfigurationException {
if (parameterMap.containsKey(p)) {
parameterMap.put(p, value);
} else {
throw new ConfigurationException("Parameter " + p.getName() + " not defined");
}
}
/**
* sets the value of parameter with given name
*
* @param parameterName parameter to set
* @param value value to set
* @throws ConfigurationException if the parameter is not defined
*/
@Override
public void setParameterValue(String parameterName, V value) throws ConfigurationException {
if (parameterNameMap.containsKey(parameterName)) {
Parameter<T> p = parameterNameMap.get(parameterName);
parameterMap.put(p, value);
} else {
throw new ConfigurationException("Parameter " + parameterName + " not defined");
}
}
/**
* sets the value of the given parameter
*
* @param p parameter to set
* @param stringValue value to set
* @throws ConfigurationException if the parameter is not defined
*/
@Override
public void setParameterValueByString(Parameter<T> p, String stringValue) throws ConfigurationException {
if (parameterMap.containsKey(p)) {
try {
V value = p.getStringConverter().fromString(stringValue);
parameterMap.put(p, value);
} catch (ConverterException ex) {
throw new ConfigurationException("Error while setting parameter value for parameter " + p.getName() + ". Reason:" + ex.getMessage(), ex);
}
} else {
throw new ConfigurationException("Parameter " + p.getName() + " not defined");
}
}
/**
* sets the value of the given parameter
*
* @param parameterName name of parameter to set the value for
* @param stringValue value to set
* @throws ConfigurationException if the parameter is not defined
*/
@Override
public void setParameterValueByString(String parameterName, String stringValue) throws ConfigurationException {
if (parameterNameMap.containsKey(parameterName)) {
Parameter<T> p = parameterNameMap.get(parameterName);
if (parameterMap.containsKey(p)) {
try {
V value = p.getStringConverter().fromString(stringValue);
parameterMap.put(p, value);
} catch (ConverterException ex) {
throw new ConfigurationException("Error while setting parameter value for parameter " + p.getName() + ". Reason:" + ex.getMessage(), ex);
}
} else {
throw new ConfigurationException("Parameter " + p.getName() + " not defined");
}
} else {
throw new ConfigurationException("Parameter with name " + parameterName + " not found in configuration");
}
}
/**
* returns the value of the given parameter
*
* @param p the parameter to return the value for
* @return the value of the given parameter
*
* @throws ConfigurationException if the value cannot be determined
*/
@Override
public V getParameterValue(Parameter<T> p) throws ConfigurationException {
if (parameterMap.containsKey(p)) {
return parameterMap.get(p);
} else {
throw new ConfigurationException("Parameter " + p.getName() + " not defined");
}
}
/**
* returns the value of the given parameter
*
* @param parameterName the name of the parameter to return the value for
* @return the value of the given parameter; null if not set
*
* @throws ConfigurationException if the parameter is not defined or if the value is not set
*/
@Override
public V getParameterValue(String parameterName) throws ConfigurationException {
if (parameterNameMap.containsKey(parameterName)) {
Parameter<T> p = parameterNameMap.get(parameterName);
return getParameterValue(p);
} else {
throw new ConfigurationException("Parameter " + parameterName + " not defined");
}
}
/**
* validates a parameter. Returns true, if the parameter setup is valid; false otherwise
*
* @param p the parameter to validate
* @return true, if the parameter is valid (mandatory parameter set, depending parameters set); false otherwise
*
* @throws ConfigurationException if a check fails
*/
private boolean validateParameter(Parameter<T> p) throws ConfigurationException {
// check if parameter is mandatory and available
if ((p.isMandatory()) && (parameterMap.get(p) == null)) {
return false;
}
// check if parameter has required parameters and if these are set
V parameterValue = getParameterValue(p);
if (parameterValue != null) {
for (Parameter rp : p.getRequiredParameter()) {
if (getParameterValue(rp) == null) {
return false;
}
}
}
// check if parameter has uses value list -if yes ensure only valid value is selected
if (!p.isValid(parameterValue)) {
throw new ConfigurationException("Value for paramter " + p.getName() + " is invalid.");
}
return true;
}
}

View File

@ -0,0 +1,51 @@
package de.muehlencord.shared.configuration;
import de.muehlencord.shared.configuration.converter.IntegerStringConverter;
/**
* A Integer parameter
*
* @author joern@muehlencord.de
*/
public class IntegerParameter extends Parameter<Integer> {
/**
* creates a new mandatory parameter object using default string converter
*
* @param name the name of the parameter
*/
public IntegerParameter(String name) {
super(name, new IntegerStringConverter(), true);
}
/**
* creates a new mandatory parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public IntegerParameter(String name, StringConverter<Integer> converter) {
super(name, converter, true);
}
/**
* creates a new parameter object using default string converter
*
* @param name the name of the parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public IntegerParameter(String name, boolean mandatory) {
super(name, new IntegerStringConverter(), mandatory);
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public IntegerParameter(String name, StringConverter<Integer> converter, boolean mandatory) {
super(name, converter, mandatory);
}
}

View File

@ -0,0 +1,168 @@
package de.muehlencord.shared.configuration;
import java.util.LinkedList;
import java.util.List;
/**
*
* @param <T> type of parameter
* @author jomu
*/
public abstract class Parameter<T> {
/** the name of the parameter */
private String name;
/** the long description of this parameter */
private String description;
/** boolean flag if this is a mandatory parameter or not */
private boolean mandatory;
/** the type of the value object for this paramterer */
// private T type;
/** the string converter to convert the object to string and back again */
private StringConverter<T> stringConverter;
/** list of mandatory parameters, if this parameter is active */
private List<Parameter<?>> requiredParameters;
/** optional validator */
private Validator<T> validator;
/**
* creates a new mandatory string parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public Parameter(String name, StringConverter<T> converter) {
this.name = name;
this.description = name;
this.mandatory = true;
this.stringConverter = converter;
this.requiredParameters = new LinkedList<Parameter<?>>();
this.validator = null;
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public Parameter(String name, StringConverter<T> converter, boolean mandatory) {
this(name, converter);
this.mandatory = mandatory;
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param description the long text description of this parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public Parameter(String name, StringConverter<T> converter, String description, boolean mandatory) {
this(name, converter);
this.description = description;
this.mandatory = mandatory;
}
@Override
public String toString() {
return name;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @return the mandatory
*/
public boolean isMandatory() {
return mandatory;
}
/**
* @return the stringConverter
*/
public StringConverter<T> getStringConverter() {
return stringConverter;
}
/**
* adds a parameter to the list of required parameters
*
* @param param the parameter to add
*/
public void addRequiredParameter(Parameter param) {
if (!requiredParameters.contains(param)) {
requiredParameters.add(param);
}
}
/**
* returns the list of parameters the given parameter requires
*
* @return the list of parameters the given parameter requires
*/
public List<Parameter<?>> getRequiredParameter() {
return requiredParameters;
}
/**
* returns true, if the given value is part of the possible value list or if the given value list is true
*
* @param value the value to validate
* @return true if no value list is defined or value is part of the value list; false otherwise
*/
public boolean isValid(T value) {
if (validator == null) {
return true;
} else {
try {
validator.validate(value);
return true;
} catch (ValidationException ex) {
return false;
}
}
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o instanceof Parameter) {
Parameter param = (Parameter) o;
return param.getName().equals(getName());
} else {
return false;
}
}
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}
/**
* @param validator the validator to set
*/
public void setValidator(Validator<T> validator) {
this.validator = validator;
}
}

View File

@ -0,0 +1,49 @@
package de.muehlencord.shared.configuration;
import java.net.URI;
import java.util.Date;
/**
*
* @author jomu
*/
public abstract class ParameterFactory {
private ParameterFactory() {
// hide public constructor to force factory
}
public static Parameter getParameterInstance(String name, boolean mandatory, Class clazz) throws ConfigurationException {
if (clazz.equals(String.class)) {
return new StringParameter(name, mandatory);
} else if (clazz.equals(Boolean.class)) {
return new BooleanParameter(name, mandatory);
} else if (clazz.equals(Date.class)) {
return new DateParameter(name, mandatory);
} else if (clazz.equals(Integer.class)) {
return new IntegerParameter(name, mandatory);
} else if (clazz.equals(URI.class)) {
return new URIParameter(name, mandatory);
} else {
throw new ConfigurationException("Unsupported type " + clazz);
}
}
public static Parameter getParameterInstance(String name, boolean mandatory, Object value) throws ConfigurationException {
return getParameterInstance(name, mandatory, value.getClass());
}
public static Parameter getParameterInstance(String name) throws ConfigurationException {
return getParameterInstance(name, true, String.class);
}
public static Parameter getParameterInstance(String name, boolean mandatory) throws ConfigurationException {
return getParameterInstance(name, mandatory, String.class);
}
}

View File

@ -0,0 +1,27 @@
package de.muehlencord.shared.configuration;
/**
*
* @param <T> the class type of the parameter value to convert
* @author jomu
*/
public interface StringConverter<T> {
/**
* Converter a parameter object to a string representation
* @param o the parameter value to convert
* @return the parameter value as string
* @throws ConverterException if the conversion fails
*/
public String toString (T o) throws ConverterException;
/**
* Converter a string to a the given type
* @param <V> the type of the converter
* @param s string representation of a parameter value to convert to an object
* @return the parameter value as object
* @throws ConverterException if the conversion fails
*/
public <V> V fromString (String s) throws ConverterException;
}

View File

@ -0,0 +1,50 @@
package de.muehlencord.shared.configuration;
import de.muehlencord.shared.configuration.converter.StringStringConverter;
/**
* A String parameter
* @author joern@muehlencord.de
*/
public class StringParameter extends Parameter<String> {
/**
* creates a new mandatory parameter object using default string converter
*
* @param name the name of the parameter
*/
public StringParameter(String name) {
super(name, new StringStringConverter(), true);
}
/**
* creates a new mandatory parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public StringParameter(String name, StringConverter<String> converter) {
super(name, converter, true);
}
/**
* creates a new parameter object using default string converter
*
* @param name the name of the parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public StringParameter(String name, boolean mandatory) {
super(name, new StringStringConverter(), mandatory);
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public StringParameter(String name, StringConverter<String> converter, boolean mandatory) {
super(name, converter, mandatory);
}
}

View File

@ -0,0 +1,52 @@
package de.muehlencord.shared.configuration;
import de.muehlencord.shared.configuration.converter.URIStringConverter;
import java.net.URI;
/**
* A URI parameter
* @author joern@muehlencord.de
*/
public class URIParameter extends Parameter<URI> {
/**
* creates a new mandatory parameter object using default string converter
*
* @param name the name of the parameter
*/
public URIParameter(String name) {
super(name, new URIStringConverter(), true);
}
/**
* creates a new mandatory parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
*/
public URIParameter(String name, StringConverter<URI> converter) {
super(name, converter, true);
}
/**
* creates a new parameter object using default string converter
*
* @param name the name of the parameter
* @param mandatory detremines if this is a mandatory parameter or not
*/
public URIParameter(String name, boolean mandatory) {
super(name, new URIStringConverter(), mandatory);
}
/**
* creates a new parameter object
*
* @param name the name of the parameter
* @param converter the converter object to convert the value of the parameter to string and vice versa
* @param mandatory detremines if this is a mandatory parameter or not
*/
public URIParameter(String name, StringConverter<URI> converter, boolean mandatory) {
super(name, converter, mandatory);
}
}

View File

@ -0,0 +1,36 @@
package de.muehlencord.shared.configuration;
/**
*
* @author joern@muehlencord.de
*/
public class ValidationException extends Exception {
/**
* Creates a new instance of
* <code>ValidationException</code> without detail message.
*/
public ValidationException() {
}
/**
* Constructs an instance of
* <code>ValidationException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public ValidationException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>ValidationException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the root cause
*/
public ValidationException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,17 @@
package de.muehlencord.shared.configuration;
/**
*
* @param <T> the type of the validator
* @author joern@muehlencord.de
*/
public interface Validator<T> {
/**
* validates the parameter value
*
* @param value the value of the parameter to validate
* @throws ValidationException if the value is not valid according to the validator configuration
*/
public void validate(T value) throws ValidationException;
}

View File

@ -0,0 +1,21 @@
package de.muehlencord.shared.configuration.converter;
import de.muehlencord.shared.configuration.ConverterException;
import de.muehlencord.shared.configuration.StringConverter;
/**
*
* @author joern@muehlencord.de
*/
public class BooleanStringConverter implements StringConverter<Boolean> {
@Override
public String toString(Boolean o) throws ConverterException {
return o.toString();
}
@Override
public Boolean fromString(String s) throws ConverterException {
return Boolean.parseBoolean(s);
}
}

View File

@ -0,0 +1,49 @@
package de.muehlencord.shared.configuration.converter;
import de.muehlencord.shared.configuration.ConverterException;
import de.muehlencord.shared.configuration.StringConverter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
*
* @author jomu
*/
public class DateStringConverter implements StringConverter<Date> {
/**
* dateformat to convert from string to date and vice versa
*/
private static final String format = "yyyy-MM-dd HH:mm:ss";
/**
* Converter a parameter object to a string representation
*
* @param d the parameter value to convert
* @return the parameter value as string
*/
@Override
public String toString(Date d) {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
return sdf.format(d);
}
/**
* Converter a string to date
*
* @param s string representation of a parameter value to convert to an object
* @return the parameter value as date
*
* @throws ConverterException if the conversion fails
*/
@Override
public Date fromString(String s) throws ConverterException {
try {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
return sdf.parse(s);
} catch (Exception ex) {
throw new ConverterException("Error while converting " + s + "*to date. Reason: " + ex.getMessage(), ex);
}
}
}

View File

@ -0,0 +1,20 @@
package de.muehlencord.shared.configuration.converter;
import de.muehlencord.shared.configuration.ConverterException;
import de.muehlencord.shared.configuration.StringConverter;
/**
*
* @author jomu
*/
public class IntegerStringConverter implements StringConverter<Integer> {
public String toString(Integer o) throws ConverterException {
return o.toString();
}
public Integer fromString(String s) throws ConverterException {
return Integer.parseInt(s);
}
}

View File

@ -0,0 +1,22 @@
package de.muehlencord.shared.configuration.converter;
import de.muehlencord.shared.configuration.ConverterException;
import de.muehlencord.shared.configuration.StringConverter;
/**
*
* @author jomu
*/
public class StringStringConverter implements StringConverter<String> {
@Override
public String toString(String o) throws ConverterException {
return o;
}
@Override
public String fromString(String s) throws ConverterException {
return s;
}
}

View File

@ -0,0 +1,23 @@
package de.muehlencord.shared.configuration.converter;
import de.muehlencord.shared.configuration.ConverterException;
import de.muehlencord.shared.configuration.StringConverter;
import java.net.URI;
/**
*
* @author jomu
*/
public class URIStringConverter implements StringConverter<URI> {
@Override
public String toString(URI o) throws ConverterException {
return o.toString();
}
@Override
public URI fromString(String s) throws ConverterException {
return URI.create(s);
}
}

View File

@ -0,0 +1,27 @@
package de.muehlencord.shared.configuration.validator;
import de.muehlencord.shared.configuration.ValidationException;
import de.muehlencord.shared.configuration.Validator;
/**
*
* @author joern@muehlencord.de
*/
public class IntgerRangeValidator implements Validator<Integer> {
private Integer lowerBoundary;
private Integer upperBoundary;
public IntgerRangeValidator(Integer lb, Integer ub) {
this.lowerBoundary = lb;
this.upperBoundary = ub;
}
@Override
public void validate(Integer value) throws ValidationException {
if ((value > upperBoundary) || (value < lowerBoundary)) {
throw new ValidationException("Value must be between " + lowerBoundary + " and " + upperBoundary + " but is " + value);
}
}
}

View File

@ -0,0 +1,32 @@
package de.muehlencord.shared.configuration.validator;
import de.muehlencord.shared.configuration.ValidationException;
import de.muehlencord.shared.configuration.Validator;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author joern@muehlencord.de
*/
public class StringValueListValidator implements Validator<String> {
private List<String> valueList;
public StringValueListValidator() {
this.valueList = new LinkedList<String>();
}
public StringValueListValidator(String... values) {
this();
valueList.addAll(Arrays.asList(values));
}
@Override
public void validate(String value) throws ValidationException {
if (!valueList.contains(value)) {
throw new ValidationException("Value " + value + " not valid. One of " + valueList.toString() + " expected");
}
}
}

View File

@ -0,0 +1,38 @@
package de.muehlencord.shared.configuration;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

81
jeeutil/pom.xml Normal file
View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>de.muehlencord.app</groupId>
<artifactId>shared-jeeutil</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>ejb</packaging>
<name>shared-jeeutil</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>6.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,58 @@
package de.muehlencord.app.sharedjeeutil;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
/**
* Filter to suppress ClickJacking by adding X-FRAME-OPTIONS to header.
* see https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet for details
*
* @author joern@muehlencord.de
*/
public class ClickJackFIlter implements Filter {
/** mode to use */
private String mode = "DENY";
/**
* inits the filter. Checks if a parameter "mode" is available in parameter map tp use instead default "DENY"
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String configMode = filterConfig.getInitParameter("mode");
if (configMode != null) {
mode = configMode;
}
}
/**
* Add X-FRAME-OPTIONS response header to tell IE8 (and any other browsers who decide to implement) not to display this content in a frame. For details,
* please refer to http://blogs.msdn.com/sdl/archive/2009/02/05/clickjacking-defense-in-ie8.aspx.
*
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("X-FRAME-OPTIONS", mode);
chain.doFilter(request, response);
}
@Override
public void destroy() {
// nothing todo here
}
}

View File

@ -0,0 +1,2 @@
Manifest-Version: 1.0

30
jmpass/pom.xml Normal file
View File

@ -0,0 +1,30 @@
<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>jmpass</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>jmpass</name>
<url>http://www.mühlencord.de/</url>
<issueManagement>
<system>Bugzilla</system>
<url>https://jomu.timelord.de/bugzilla/</url>
</issueManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,56 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.jmpass;
/**
*
* @author jomu
*/
public class Bcrypt {
// http://en.wikipedia.org/wiki/Bcrypt
public String bcrypt(long cost, byte[] salt, String input) {
String state = eksBlowfishSetup(cost, salt, input);
String cText = "OrpheanBeholderScryDoubt"; // FIXME - what is this string for, 3 64 bit blocks
for (int i=0; i<64; i++) { // FIXME - why 64?
cText = encryptECB(state, cText);
}
return concatenate(cost, salt, cText);
}
private String eksBlowfishSetup(long cost, String salt, String key) {
String state = initState();
state = expandKey (state, salt, key);
// TODO buffer overflow check, max size of cost
long rounds = Math.round(Math.pow(2, cost));
for (int i=0; i<rounds; i++) {
state = expandKey (state, 0, key);
state = expandKey (state, 0, salt);
}
}
private String initState() {
throw new UnsupportedOperationException("Not yet implemented");
}
private String expandKey(String state, String salt, String input) {
throw new UnsupportedOperationException("Not yet implemented");
}
private String encryptECB(String state, String cText) {
throw new UnsupportedOperationException("Not yet implemented");
}
private String concatenate(long cost, byte[] salt, String cText) {
throw new UnsupportedOperationException("Not yet implemented");
}
}

View File

@ -0,0 +1,82 @@
package de.muehlencord.shared.jmpass;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
*
* @author joern@muehlencord.de
*/
public class Password {
private final static int SALT_BYTES = 16;
private long rounds;
private byte[] hash;
private byte[] salt;
public Password(int iterations) {
rounds = Math.round(Math.pow(2, iterations));
}
public void hashPassword(String password) throws PasswordException {
try {
salt = createSalt();
hash = createHash(password, salt);
} catch (Exception ex) {
throw new PasswordException("Error while hashing password. Reason: " + ex.getMessage(), ex);
}
}
public String getPasswordHashString() {
StringBuilder sb = new StringBuilder();
sb.append("$");
sb.append(rounds);
sb.append("$");
sb.append(salt);
sb.append(hash);
return sb.toString();
}
private int getIterationsFromString(String hashedPassword) throws PasswordException {
if (hashedPassword.length() < 20) {
throw new PasswordException("Given string is not a valid hashed password");
}
String roundsString = hashedPassword.substring(0, 3);
if ((!roundsString.startsWith("$")) || (!roundsString.endsWith("$"))) {
throw new PasswordException("Cannot read iterations value from given string");
}
try {
int rounds = Integer.parseInt(roundsString.substring(1, 2));
return rounds;
} catch (Exception ex) {
throw new PasswordException("Cannot parse iterations value from given string", ex);
}
}
private byte[] createSalt() throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
// Salt generation 64 bits long
byte[] bSalt = new byte[SALT_BYTES];
random.nextBytes(bSalt);
return bSalt;
}
private byte[] createHash(String password, byte[] salt) throws UnsupportedEncodingException, NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
digest.update(salt);
byte[] input = digest.digest(password.getBytes("UTF-8"));
for (int i = 0; i < rounds; i++) {
digest.reset();
input = digest.digest(input);
}
return input;
}
}

View File

@ -0,0 +1,26 @@
package de.muehlencord.shared.jmpass;
/**
*
* @author joern@muehlencord.de
*/
class PasswordException extends Exception {
/**
* creats an instance of PasswordException with the given message
* @param msg the msg of the exception
*/
public PasswordException(String msg) {
super (msg);
}
/**
* creats an instance of PasswordException with the given message
* @param msg the msg of the exception
* @param th the causing exception
*/
public PasswordException(String msg, Throwable th) {
super (msg);
}
}

View File

@ -0,0 +1,16 @@
package de.muehlencord.shared.jmpass;
/**
*
* @author joern@muehlencord.de
*/
public class PasswordValidator {
public static boolean validatePassword(String plainPassword, String hashedPassword) {
Password pw = new Password(8);
pw.hashPassword(plainPassword);
String hash = pw.getPasswordHashString();
return hashedPassword.equals(hash);
}
}

View File

@ -0,0 +1,38 @@
package de.muehlencord.shared.jmpass;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

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

16
pom.xml Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<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</groupId>
<artifactId>shared</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>shared</name>
<modules>
<module>configuration</module>
<module>network</module>
<module>security</module>
<module>util</module>
<module>jeeutil</module>
</modules>
</project>

View File

@ -0,0 +1,6 @@
#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/<project>=UTF-8

View File

@ -0,0 +1,6 @@
#Thu Jul 05 02:27:50 CEST 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

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

40
security/pom.xml Normal file
View File

@ -0,0 +1,40 @@
<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-security</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>shared-security</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-security/</url>
</ciManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
<type>jar</type>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,184 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.security;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import org.apache.commons.codec.binary.Base64;
/**
*
* @author joern@muehlencord.de
*/
public abstract class PasswordUtil {
/**
* returns password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
*
* @param plainTextPassword he
* @param saltLength the length of the salt to use
* @return the password (pos 0) and the salt (pos 1) of given plaintext password. Both strings are base64 encoded
*
* @throws de.muehlencord.shared.security.SecurityException if any error occurs during the password generation
*/
public static String[] getMD5Password(final String plainTextPassword, final int saltLength) throws SecurityException {
byte[] unHashedPassword = getBase64MD5HashedPassword(plainTextPassword);
byte[] salt = createSalt(saltLength);
byte[] hashedPassword = hashPasswordWithSalt(unHashedPassword, salt);
// test
String saltStr = base64Encode(salt);
byte[] salt2 = base64Decode(saltStr);
if (!Arrays.equals(salt, salt2)) {
throw new SecurityException("Salt conversion failed");
}
String[] returnValue = new String[2];
returnValue[0] = base64Encode(hashedPassword);
returnValue[1] = base64Encode(salt);
return returnValue;
}
/**
* Checks if the given password (plain text) matches the given crypted password. The crypted password is hashed with the given salt. Both strings, crypted
* password and salt, have to be base64 encoded
*
* @param plainTextPassword the plaintext password to compare to
* @param cryptedPasswordStr the crypted password to compare to
* @param saltStr the salt needed to hash the plaintext password with to get the correct crypted password if both passwords match
* @return true, if and only if the encryption of plainTextPassword (hashed with saltStr) equals to cryptedPasswordStr
*
* @throws de.muehlencord.shared.security.SecurityException if any error occures during the check
*/
public static boolean checkPassword(String plainTextPassword, String cryptedPasswordStr, String saltStr) throws SecurityException {
byte[] salt = base64Decode(saltStr);
byte[] newPassword = getBase64MD5HashedPassword(plainTextPassword);
byte[] newHashedPassword = hashPasswordWithSalt(newPassword, salt);
byte[] crytepdPassword = base64Decode(cryptedPasswordStr);
return Arrays.equals(crytepdPassword, newHashedPassword);
}
/**
* returns a new salt as a string
*
* @param saltLength the length of the salt
* @return a new salt as a string (base64 encoded)
*
* @throws SecurityException if the creation of the salt fails
*/
public static String createSaltString(int saltLength) throws SecurityException {
byte[] salt = createSalt(saltLength);
return base64Encode(salt);
}
/* *** private methods *** */
/**
* creates a salt and returns the value as byte[]
*
* @param saltLength the length the salt string should have
* @return the generated salt as byte[]
*
* @throws SecurityException if the salt creation fails
*/
private static byte[] createSalt(int saltLength) throws SecurityException {
try {
SecureRandom sha1SecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte salt[] = new byte[saltLength];
synchronized (sha1SecureRandom) {
sha1SecureRandom.nextBytes(salt);
}
return salt;
} catch (Exception ex) {
throw new SecurityException("Cannot created salt", ex);
}
}
/**
* hashes the given password (md5 hashed, base64 coded) with the given salt
* @param text the text to salt
* @param salt the salt to use
* @return the input text salted with password
* @throws SecurityException
*/
private static byte[] hashPasswordWithSalt(byte text[], byte salt[]) throws SecurityException {
try {
MessageDigest sha1Algorithm = MessageDigest.getInstance("SHA-1");
byte[] digest;
synchronized (sha1Algorithm) {
sha1Algorithm.reset();
sha1Algorithm.update(salt);
digest = sha1Algorithm.digest(text);
}
return digest;
} catch (NoSuchAlgorithmException ex) {
throw new SecurityException("Cannot hash password with salt", ex);
}
}
/**
* returns the given password as md5 without appliying salt
*
* @param plainTextPassword the password to convert
* @return the given password as md5 without appliying salt
*
* @throws SecurityException if the passwor cannot be converted
*/
private static byte[] getBase64MD5HashedPassword(final String plainTextPassword) throws SecurityException {
try {
MessageDigest algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(plainTextPassword.getBytes());
byte[] messageDigest = algorithm.digest();
StringBuilder buf = new StringBuilder();
for (int i = 0; i < messageDigest.length; i++) {
int halfbyte = (messageDigest[i] >>> 4) & 0x0F;
int twoHalfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9)) {
buf.append((char) ('0' + halfbyte));
} else {
buf.append((char) ('a' + (halfbyte - 10)));
}
halfbyte = messageDigest[i] & 0x0F;
} while (twoHalfs++ < 1);
}
// take password and hash with salt
byte[] unHashedPassword = base64Decode(buf.toString());
return unHashedPassword;
} catch (Exception ex) {
throw new SecurityException("Cannot created password", ex);
}
}
/**
* returns the plain byte[] as base64 coded string
*
* @param data the data to convert
* @return the plain byte[] as base64 coded string
*/
private static String base64Encode(final byte[] data) {
Base64 encoder = new Base64();
byte[] result = encoder.encode(data);
return new String(result);
}
/**
* returns the given base64 coded string as decoded byte[]
*
* @param data the string to convert
* @return the given base64 coded string as decoded byte[]
*/
private static byte[] base64Decode(final String data) {
Base64 decoder = new Base64();
return decoder.decode(data.getBytes());
}
}

View File

@ -0,0 +1,29 @@
/*
*/
package de.muehlencord.shared.security;
/**
*
* @author joern@muehlencord.de
*/
public class SecurityException extends Exception {
public SecurityException() {
super ("An error occured during a security action");
}
public SecurityException(String msg) {
super (msg);
}
public SecurityException(String msg, Throwable cause) {
super(msg, cause);
}
public SecurityException(Throwable cause) {
super (cause);
}
}

View File

@ -0,0 +1,115 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.security;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author jomu
*/
public class PasswordUtilTest {
public PasswordUtilTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of createSaltString method, of class PasswordUtil.
*/
@Test
public void createSaltString() throws Exception {
System.out.println("createSaltString");
int saltLength = 40;
String result = PasswordUtil.createSaltString(saltLength);
assertNotNull(result);
}
/**
* Test of getMD5Password method, of class PasswordUtil.
*/
@Test
public void getMD5Password() throws Exception {
System.out.println("getMD5Password");
String plainTextPassword = "";
int saltLength = 40;
String[] result1 = PasswordUtil.getMD5Password(plainTextPassword, saltLength);
String password1 = result1[0];
String salt1 = result1[1];
assertNotNull(result1);
assertNotNull(password1);
assertNotNull(salt1);
String[] result2 = PasswordUtil.getMD5Password(plainTextPassword, saltLength);
String password2 = result2[0];
String salt2 = result2[1];
assertNotNull(result2);
assertNotNull(password2);
assertNotNull(salt2);
assertNotSame(result1, result2);
assertNotSame(password1, password2);
assertNotSame(salt1, salt2);
}
/**
* Test of checkPassword method, of class PasswordUtil.
*/
@Test
public void checkPassword() throws Exception {
System.out.println("checkPassword");
String plainTextPassword = "welcome";
String plainTextPassword2 = "this is not the correct password";
String[] data = PasswordUtil.getMD5Password(plainTextPassword, 40);
String cryptedPassword = data[0];
String salt = data[1];
String salt2 = PasswordUtil.createSaltString(40);
String salt3 = PasswordUtil.createSaltString(10);
boolean expResult = true;
boolean result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt);
assertEquals(expResult, result);
expResult = false;
result = PasswordUtil.checkPassword(plainTextPassword2, cryptedPassword, salt);
assertEquals(expResult, result);
expResult = false;
result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt2);
assertEquals(expResult, result);
expResult = false;
result = PasswordUtil.checkPassword(plainTextPassword, cryptedPassword, salt3);
assertEquals(expResult, result);
}
}

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,6 @@
#Thu Jul 05 02:27:50 CEST 2012
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

18
util/nb-configuration.xml Normal file
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>

55
util/pom.xml Normal file
View File

@ -0,0 +1,55 @@
<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>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<artifactId>shared</artifactId>
<groupId>de.muehlencord</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>shared-util</name>
<artifactId>shared-util</artifactId>
<ciManagement>
<system>hudson</system>
<url>http://sunrise.muehlencord.intra:8088/jenkins/job/shared-util/</url>
</ciManagement>
</project>

View File

@ -0,0 +1,46 @@
/*
* OSUtil.java
*
* Created on 10. Dezember 2007, 16:50
*
*/
package de.muehlencord.shared.util;
/**
*
* @author joern@muehlencord.de
*/
public abstract class OSUtil {
/** OS unknown */
public final static int OS_UNKNOWN = 0;
/** OS Linux */
public final static int OS_WINDOWS = 1;
/** OS Linux */
public final static int OS_LINUX = 2;
/** OS MacOS X */
public final static int OS_MACOS = 3;
/**
* returns the operation system the current JVM is running on
*
* @return an OS_xxxx constants identifiying the operating system the current JVM is running on;
*/
public static int getOperationSystem() {
String osName = System.getProperties().getProperty("os.name");
if (osName != null) {
osName = osName.toUpperCase();
if (osName.contains("WINDOWS")) {
return OS_WINDOWS;
} else if (osName.contains("LINUX")) {
return OS_LINUX;
} else if (osName.contains("MAC")) {
return OS_MACOS;
} else {
return OS_UNKNOWN;
}
} else {
return OS_UNKNOWN;
}
}
}

View File

@ -0,0 +1,40 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.util;
/**
*
* @author joern@muehlencord.de
*/
public class StringEncodingException extends Exception {
/**
* Creates a new instance of
* <code>StringEncodingException</code> without detail message.
*/
public StringEncodingException() {
}
/**
* Constructs an instance of
* <code>StringEncodingException</code> with the specified detail message.
*
* @param msg the detail message.
*/
public StringEncodingException(String msg) {
super(msg);
}
/**
* Constructs an instance of
* <code>StringEncodingException</code> with the specified detail message.
*
* @param msg the detail message.
* @param th the causing exception
*/
public StringEncodingException(String msg, Throwable th) {
super(msg, th);
}
}

View File

@ -0,0 +1,90 @@
/*
* StringUtil.java
*
* Created on 4. Mai 2007, 12:36
*/
package de.muehlencord.shared.util;
import java.text.ParseException;
import org.apache.log4j.Logger;
/**
*
* @author joern@muehlencord.de
*/
public abstract class StringUtil {
/** the logging object */
private static final Logger logger = Logger.getLogger(StringUtil.class);
/**
* returns the given string in ISO-8859-1 encoding
*
* @param input the input string in UTF-8
* @return the converted string in
*
* @throws StringEncodingException if the string cannot be converted
*/
public static String getISOString(String input) throws StringEncodingException {
try {
byte[] b = input.getBytes("UTF-8");
return new String(b, "ISO-8859-1");
} catch (Exception ex) {
logger.debug(getStackTraceString(ex));
throw new StringEncodingException("Cannot convert string from UTF-8 to ISO-8859-1. Reason: " + ex.getMessage(), ex);
}
}
/**
* returns the stackstrace as one string
*
* @param ex the exception to return the string for
* @return the stackstrace as one string
*/
public static String getStackTraceString(Throwable ex) {
String logString = ex.toString() + "\n";
StackTraceElement[] stack = ex.getStackTrace();
for (int i = 0; i < stack.length; i++) {
logString += (stack[i].toString()) + "\n";
}
return logString;
}
/**
* fills s with blanks if s < length
*
*
*
*
* @param length the needed length for this field
* @param s the field to extend with blanks
* @return s extended by trainling blanks. s.length == length
*/
public static String getBlankedString(int length, String s) {
if (s == null) {
return "";
}
String returnValue = s;
while (s.length() < length) {
returnValue += " ";
}
return returnValue;
}
public static String getValueBetweenKeywords(String content, String keyWord1, String keyWord2) throws ParseException {
int pos1 = content.indexOf(keyWord1);
if (pos1 == -1) {
throw new ParseException("Keyword1=" + keyWord1 + " not found in content string",0);
}
int pos2 = content.indexOf(keyWord2, pos1);
if (pos2 == -1) {
throw new ParseException("Keyword2=" + keyWord2 + " not found in content string",0);
}
String returnValue = content.substring(pos1+keyWord1.length(), pos2);
returnValue = returnValue.trim();
return returnValue;
}
}

View File

@ -0,0 +1,19 @@
package de.muehlencord.shared.util.file;
import java.io.Serializable;
/**
*
* @author joern@muehlencord.de
*/
public class FileHandlingException extends Exception implements Serializable {
public FileHandlingException (String hint) {
super(hint);
}
public FileHandlingException (String hint, Throwable th) {
super (hint, th);
}
}

View File

@ -0,0 +1,157 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.util.file;
import de.muehlencord.shared.util.StringUtil;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.Format;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
/**
*
* @author joern@muehlencord.de
*/
public abstract class FileUtil {
/** the logging object */
private static final Logger logger = Logger.getLogger(FileUtil.class);
/**
* returns a list of files found by the given regexp in the given folder
*
* @param directory the folder to search in as a string
* @param regEx the regular expression to search with
* @return a list of files
*
* @throws FileHandlingException if the given directory cannot be found
*/
public static List<File> getFilesFromDirecotry(final String directory, final String regEx) throws FileHandlingException {
List<File> returnValue = new LinkedList<File>();
File dir = new File(directory);
if (!dir.exists()) {
throw new FileHandlingException("Directory " + directory + " does not exist");
}
if (!dir.isDirectory()) {
throw new FileHandlingException(directory + " is not a directory");
}
FileFilter ff = new FileFilter() {
@Override
public boolean accept(File pathname) {
boolean isFile = pathname.isFile();
boolean match = pathname.toString().matches(regEx);
return isFile && match;
}
};
File[] files = dir.listFiles(ff);
if (files != null) {
returnValue.addAll(Arrays.asList(files));
}
return returnValue;
} // method getFilesFromDirecotry
/**
* returns a file handle to a file in the given folder using the given formater and the given number.
*
* @param outputFolder the folder to link the file to as strnig
* @param ft a format object to use to format the filename of the given file
* @param number a number used to call the given formater to name the file number
* @return a file handle build from formater and number linked to given directory
*/
public static File getFileName(final String outputFolder, final Format ft, final int number) {
String folderName = outputFolder;
String fileName = ft.format(number);
if (!outputFolder.endsWith(File.separator)) {
folderName += File.separator;
}
fileName = folderName + fileName;
return new File(fileName);
}
/**
* copies the givn source file to the given destination filename
*
* @param source the file to copy from
* @param destination the destination filename to copy the source file to
* @return true, if the vile was copied, false, else
*/
public static boolean copyFileTo(File source, File destination) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(source);
fos = new FileOutputStream(destination);
byte[] buf = new byte[4096];
int loaded;
while ((loaded = fis.read(buf)) > 0) {
fos.write(buf, 0, loaded);
}
} catch (IOException e) {
return false;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
logger.error(ex.getMessage());
logger.debug(StringUtil.getStackTraceString(ex));
}
}
}
return true;
}
/**
* moves / renames the given file to the new file
*
* @param source the source file
* @param destination the file to rename the source file to
* @return true, if move / rename was successfull; false else
*/
public static boolean moveFileTo(File source, File destination) {
boolean isRenamed;
if (doesPathExists(destination.getAbsolutePath())) {
destination.delete();
}
isRenamed = source.renameTo(destination);
if (!isRenamed) {
copyFileTo(source, destination);
source.delete();
}
return isRenamed;
}
/**
* returns true, if the givn path exists; false otherwise
*
* @param path the path to check
* @return true, if the givn path exists; false otherwise
*/
public static boolean doesPathExists(String path) {
File location = new File(path);
return location.exists();
}
}

View File

@ -0,0 +1,33 @@
package de.muehlencord.shared.util;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author joern@muehlencord.de
*/
public class DefaultTest {
public String readContentFromFile(String name) throws IOException {
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[4096];
InputStream is = DefaultTest.class.getResourceAsStream(name);
if (is == null) {
throw new IOException("File " + name + " not found");
}
BufferedInputStream bis = new BufferedInputStream(is);
int bytesRead = 0;
while ((bytesRead = bis.read(buffer)) != -1) {
sb.append(new String(buffer, 0, bytesRead));
}
bis.close();
is.close();
return sb.toString();
}
}

View File

@ -0,0 +1,23 @@
package de.muehlencord.shared.util;
import java.io.IOException;
import java.text.ParseException;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* Basic StringUtilTests
* @author joern@muehlencord.de
*/
public class StringUtilTest extends DefaultTest {
@Test
public void testGetValueBetweenKeywords() throws ParseException, IOException {
String content = readContentFromFile("/test.txt");
String ipAddress = StringUtil.getValueBetweenKeywords(content, "The IP", "has just");
assertEquals ("ipAddress", "222.184.230.118", ipAddress);
}
}

View File

@ -0,0 +1,41 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package de.muehlencord.shared.util.file;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
/**
*
* @author jomu
*/
public class FileUtilTest {
/**
* tests the function getFilesFromDirectory
* @throws FileHandlingException if the files could not be listed
* @throws URISyntaxException if the testfile specification is wrong
*/
@Test
public void testGetFilesFromDirecotry() throws FileHandlingException, URISyntaxException {
System.out.println("testGetFilesFromDirectory");
URL url = getClass().getResource("/testfile.txt");
File testFile = new File(url.getFile());
List<File> fileList = FileUtil.getFilesFromDirecotry(testFile.getParent(), ".*.java");
Iterator<File> it = fileList.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

View File

@ -0,0 +1,78 @@
Hi,
The IP 222.184.230.118 has just been banned by Fail2Ban after
4 attempts against ssh.
Here are more information about 222.184.230.118:
% [whois.apnic.net node-4]
% Whois data copyright terms http://www.apnic.net/db/dbcopyright.html
inetnum: 222.184.0.0 - 222.191.255.255
netname: CHINANET-JS
descr: CHINANET jiangsu province network
descr: China Telecom
descr: A12,Xin-Jie-Kou-Wai Street
descr: Beijing 100088
country: CN
admin-c: CH93-AP
tech-c: CJ186-AP
mnt-by: APNIC-HM
mnt-lower: MAINT-CHINANET-JS
mnt-routes: MAINT-CHINANET-JS
remarks: This object can only modify by APNIC hostmaster
remarks: If you wish to modify this object details please
remarks: send email to hostmaster@apnic.net with your
remarks: organisation account name in the subject line.
changed: hm-changed@apnic.net 20040223
status: ALLOCATED PORTABLE
source: APNIC
role: CHINANET JIANGSU
address: 260 Zhongyang Road,Nanjing 210037
country: CN
phone: +86-25-86588231
phone: +86-25-86588745
fax-no: +86-25-86588104
e-mail: ip@jsinfo.net
remarks: send anti-spam reports to spam@jsinfo.net
remarks: send abuse reports to abuse@jsinfo.net
remarks: times in GMT+8
admin-c: CH360-AP
tech-c: CS306-AP
tech-c: CN142-AP
nic-hdl: CJ186-AP
remarks: www.jsinfo.net
notify: ip@jsinfo.net
mnt-by: MAINT-CHINANET-JS
changed: dns@jsinfo.net 20090831
changed: ip@jsinfo.net 20090831
changed: hm-changed@apnic.net 20090901
source: APNIC
changed: hm-changed@apnic.net 20111114
person: Chinanet Hostmaster
nic-hdl: CH93-AP
e-mail: anti-spam@ns.chinanet.cn.net
address: No.31 ,jingrong street,beijing
address: 100032
phone: +86-10-58501724
fax-no: +86-10-58501724
country: CN
changed: dingsy@cndata.com 20070416
mnt-by: MAINT-CHINANET
source: APNIC
Lines containing IP:222.184.230.118 in /var/log/auth.log
Jan 6 23:35:47 localhost sshd[31328]: Invalid user cgi from 222.184.230.118
Jan 6 23:35:49 localhost sshd[31330]: Invalid user richie from 222.184.230.118
Jan 6 23:35:51 localhost sshd[31332]: Invalid user shirsh from 222.184.230.118
Jan 6 23:36:00 localhost sshd[31340]: Invalid user system from 222.184.230.118
Regards,
Fail2Ban

View File

@ -0,0 +1 @@
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.