From c27966d194ff56df5b61cc47b87701448c2f574c Mon Sep 17 00:00:00 2001 From: ribeaudc <ribeaudc> Date: Wed, 27 Jun 2007 22:22:47 +0000 Subject: [PATCH] add: - new classes. SVN: 711 --- .../cisd/common/mail/JavaMailProperties.java | 50 +++++ .../systemsx/cisd/common/mail/MailClient.java | 171 ++++++++++++++++++ .../common/utilities/ExtendedProperties.java | 146 +++++++++++++++ .../utilities/ExtendedPropertiesTest.java | 63 +++++++ 4 files changed, 430 insertions(+) create mode 100644 common/source/java/ch/systemsx/cisd/common/mail/JavaMailProperties.java create mode 100644 common/source/java/ch/systemsx/cisd/common/mail/MailClient.java create mode 100644 common/source/java/ch/systemsx/cisd/common/utilities/ExtendedProperties.java create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/utilities/ExtendedPropertiesTest.java diff --git a/common/source/java/ch/systemsx/cisd/common/mail/JavaMailProperties.java b/common/source/java/ch/systemsx/cisd/common/mail/JavaMailProperties.java new file mode 100644 index 00000000000..d99365ab76d --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/mail/JavaMailProperties.java @@ -0,0 +1,50 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.mail; + +/** + * The <i>JavaMail API</i> supports the following standard properties. + * + * @author Christian Ribeaud + */ +public final class JavaMailProperties +{ + + private JavaMailProperties() + { + // Can not be instantiated. + } + + /** Specifies the default message access protocol. */ + public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; + + /** The initial debug mode. */ + public static final String MAIL_DEBUG = "mail.debug"; + + /** The return email address of the current user. */ + public static final String MAIL_FROM = "mail.from"; + + /** The default host name of the mail server for Transports. */ + public static final String MAIL_SMTP_HOST = "mail.smtp.host"; + + /** The default user name to use when connecting to the mail server. */ + public static final String MAIL_SMTP_USER = "mail.smtp.user"; + + /** Whether authentication is needed when connecting to the mail server. */ + public static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; + +} diff --git a/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java b/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java new file mode 100644 index 00000000000..7296e42063b --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/mail/MailClient.java @@ -0,0 +1,171 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.mail; + +import java.util.Arrays; +import java.util.Properties; + +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +import org.apache.log4j.Logger; + +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; + +/** + * A small mail client that simplifies the sending of emails using of <i>JavaMail API</i>. + * <p> + * Just instantiate this class and use {@link #sendMessage(String, String, String[])} to send the email via SMTP. + * </p> + * + * @author Christian Ribeaud + */ +public final class MailClient extends Authenticator +{ + + /** This system property is not supported by the <i>JavaMail API</i> */ + public final static String MAIL_SMTP_PASSWORD = "mail.smtp.user"; + + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, MailClient.class); + + private final String smtpUsername; + + private final String smtpPassword; + + private final String smtpHost; + + private final String from; + + public MailClient(final String from, final String smtpHost) + { + this(from, smtpHost, null, null); + } + + public MailClient(Properties properties) + { + this(properties.getProperty(JavaMailProperties.MAIL_FROM), properties + .getProperty(JavaMailProperties.MAIL_SMTP_HOST), properties + .getProperty(JavaMailProperties.MAIL_SMTP_USER), properties.getProperty(MAIL_SMTP_PASSWORD)); + } + + public MailClient(final String from, final String smtpHost, final String smtpUsername, final String smtpPassword) + { + assert from != null; + assert smtpHost != null; + + this.from = from; + this.smtpHost = smtpHost; + this.smtpUsername = smtpUsername; + this.smtpPassword = smtpPassword; + } + + private final Properties createProperties() + { + Properties properties = null; + try + { + properties = new Properties(System.getProperties()); + } catch (SecurityException ex) + { + properties = new Properties(); + } + if (smtpUsername != null) + { + properties.put(JavaMailProperties.MAIL_SMTP_USER, smtpUsername); + } + if (smtpHost != null) + { + properties.put(JavaMailProperties.MAIL_SMTP_HOST, smtpHost); + } + if (smtpPassword != null && smtpUsername != null) + { + properties.put(JavaMailProperties.MAIL_SMTP_AUTH, Boolean.TRUE.toString()); + } + properties.put(JavaMailProperties.MAIL_DEBUG, operationLog.isDebugEnabled() ? Boolean.TRUE.toString() + : Boolean.FALSE.toString()); + properties.put(JavaMailProperties.MAIL_TRANSPORT_PROTOCOL, "smtp"); + return properties; + } + + private final Session createSession() + { + Properties properties = createProperties(); + if (operationLog.isDebugEnabled()) + { + operationLog.debug("Creating mail session with following properties '" + properties + "'."); + } + boolean mailSmtpAuth = Boolean.parseBoolean(properties.getProperty(JavaMailProperties.MAIL_SMTP_AUTH)); + Session session = Session.getInstance(properties, mailSmtpAuth ? this : null); + session.setDebug(operationLog.isDebugEnabled()); + return session; + } + + private final static InternetAddress createInternetAddress(String internetAddress) + { + try + { + return new InternetAddress(internetAddress); + } catch (AddressException e) + { + operationLog.error("Could not parse address [" + internetAddress + "].", e); + return null; + } + } + + /** + * Sends a mail with given <var>subject</var> and <var>content</var> to given <var>recipients</var>. + * + * @param recipients list of recipients (of type <code>Message.RecipientType.TO</code>) + */ + public final void sendMessage(String subject, String content, String... recipients) throws MessagingException + { + if (operationLog.isInfoEnabled()) + { + operationLog.info("SENDING message from '" + from + "' to recipients '" + Arrays.asList(recipients) + "'"); + } + int len = recipients.length; + InternetAddress[] internetAddresses = new InternetAddress[len]; + for (int i = 0; i < len; i++) + { + internetAddresses[i] = createInternetAddress(recipients[i]); + } + MimeMessage msg = new MimeMessage(createSession()); + msg.setFrom(createInternetAddress(from)); + msg.addRecipients(Message.RecipientType.TO, internetAddresses); + msg.setSubject(subject); + msg.setText(content); + Transport.send(msg); + } + + // + // Authenticator + // + + @Override + protected final PasswordAuthentication getPasswordAuthentication() + { + return new PasswordAuthentication(smtpUsername, smtpPassword); + } +} diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ExtendedProperties.java b/common/source/java/ch/systemsx/cisd/common/utilities/ExtendedProperties.java new file mode 100644 index 00000000000..f9de6fdd7ef --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ExtendedProperties.java @@ -0,0 +1,146 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ch.systemsx.cisd.common.utilities; + +import java.util.Enumeration; +import java.util.Properties; + +/** + * This implementation supports parameters substitution in property value. + * + * @see #getProperty(String) + * @author Christian Ribeaud + */ +public final class ExtendedProperties extends Properties +{ + private static final long serialVersionUID = 1L; + + /** Default placeholder prefix: "${" */ + private static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; + + /** Default placeholder suffix: "}" */ + private static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; + + /** + * @see java.util.Properties#Properties() + */ + public ExtendedProperties() + { + super(); + } + + /** + * @see java.util.Properties#Properties(java.util.Properties) + */ + public ExtendedProperties(Properties defs) + { + super(defs); + } + + /** + * Any parameter like <code>${propertyName}</code> in property value will be replaced with the value of property + * with name <code>propertyName</code>. + * <p> + * For example, for the following set of properties: + * + * <pre> + * param1 = abcd + * param2 = efgh + * param3 = Alphabet starts with: ${param1}${param2} + * </pre> + * + * The call <code>props.getProperty("param3")</code> returns: + * + * <pre> + * Alphabet starts with: abcdefgh + * </pre> + * + * Note also that call <code>props.get("param3")</code> returns: + * + * <pre> + * Alphabet starts with: ${param1}${param2} + * </pre> + * + * So the {@link java.util.Map#get(java.lang.Object)} works as usual and returns raw (not expanded with substituted + * parameters) property value. + * </p> + * + * @see java.util.Properties#getProperty(java.lang.String) + */ + @Override + public String getProperty(String key) + { + String result = super.getProperty(key); + return result == null ? null : expandValue(result); + } + + /** + * @see java.util.Properties#getProperty(java.lang.String, java.lang.String) + */ + @Override + public String getProperty(String key, String defaultValue) + { + String result = getProperty(key); + return result == null ? expandValue(defaultValue) : result; + } + + /** + * Returns a subset of given <code>Properties</code> based on given property key prefix. + * + * @param prefix string, each property key should start with. + */ + public final ExtendedProperties getSubset(final String prefix) + { + ExtendedProperties result = new ExtendedProperties(); + for (Enumeration enumeration = propertyNames(); enumeration.hasMoreElements();) + { + String key = enumeration.nextElement().toString(); + if (key.startsWith(prefix)) + { + result.put(key, getProperty(key)); + } + } + return result; + } + + private final String expandValue(final String value) + { + if (value == null || value.length() < 4) + { + return value; + } + StringBuilder result = new StringBuilder(value.length()); + result.append(value); + int p1 = result.indexOf(DEFAULT_PLACEHOLDER_PREFIX); + int p2 = result.indexOf(DEFAULT_PLACEHOLDER_SUFFIX, p1 + 2); + while (p1 >= 0 && p2 > p1) + { + String paramName = result.substring(p1 + 2, p2); + String paramValue = getProperty(paramName); + if (paramValue != null) + { + result.replace(p1, p2 + 1, paramValue); + p1 += paramValue.length(); + } else + { + p1 = p2 + 1; + } + p1 = result.indexOf(DEFAULT_PLACEHOLDER_PREFIX, p1); + p2 = result.indexOf(DEFAULT_PLACEHOLDER_SUFFIX, p1 + 2); + } + return result.toString(); + } +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ExtendedPropertiesTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ExtendedPropertiesTest.java new file mode 100644 index 00000000000..c942233a8ef --- /dev/null +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ExtendedPropertiesTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2007 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.utilities; + +import static org.testng.AssertJUnit.*; + +import java.util.Properties; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * Test cases for the {@link ExtendedProperties} class. + * + * @author Christian Ribeaud + */ +public final class ExtendedPropertiesTest +{ + private ExtendedProperties extendedProperties; + + @BeforeMethod + public final void setUp() { + Properties props = new Properties(); + props.setProperty("one", "eins"); + props.setProperty("un", "${one}"); + props.setProperty("two", "zwei"); + props.setProperty("three", "drei"); + extendedProperties = new ExtendedProperties(props); + } + + @Test + public final void testGetPropertyString() + { + assertEquals("eins", extendedProperties.getProperty("one")); + assertEquals("eins", extendedProperties.getProperty("un")); + } + + @Test + public final void testGetSubsetString() + { + ExtendedProperties props = extendedProperties.getSubset("t"); + assert props.size() == 2; + assert props.getProperty("two").equals("zwei"); + props = extendedProperties.getSubset("un"); + assert props.size() == 1; + assert props.getProperty("un").equals("eins"); + } + +} -- GitLab