001: /*
002: * $Header: /export/home/cvsroot/MyPersonalizerRepository/MyPersonalizer/Subsystems/Admin/Sources/es/udc/mypersonalizer/admin/model/tasks/SampleMailTask.java,v 1.1.1.1 2004/03/25 12:08:39 fbellas Exp $
003: * $Revision: 1.1.1.1 $
004: * $Date: 2004/03/25 12:08:39 $
005: *
006: * =============================================================================
007: *
008: * Copyright (c) 2003, The MyPersonalizer Development Group
009: * (http://www.tic.udc.es/~fbellas/mypersonalizer/index.html) at
010: * University Of A Coruņa
011: * All rights reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions are met:
015: *
016: * - Redistributions of source code must retain the above copyright notice,
017: * this list of conditions and the following disclaimer.
018: *
019: * - Redistributions in binary form must reproduce the above copyright notice,
020: * this list of conditions and the following disclaimer in the documentation
021: * and/or other materials provided with the distribution.
022: *
023: * - Neither the name of the University Of A Coruņa nor the names of its
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
028: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
029: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
030: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
031: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
032: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
033: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
034: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
035: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
036: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
037: * POSSIBILITY OF SUCH DAMAGE.
038: *
039: */
040: package es.udc.mypersonalizer.admin.model.tasks;
041:
042: import java.io.BufferedReader;
043: import java.io.IOException;
044: import java.io.InputStream;
045: import java.io.InputStreamReader;
046: import java.util.ArrayList;
047: import java.util.Collection;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.Properties;
051: import javax.mail.*;
052: import javax.mail.internet.*;
053:
054: import es.udc.mypersonalizer.kernel.model.metainfo.MetaCompoundProperty;
055: import es.udc.mypersonalizer.kernel.model.metainfo.MetaProperty;
056: import es.udc.mypersonalizer.kernel.model.metainfo.MetaPropertyNotFoundException;
057: import es.udc.mypersonalizer.kernel.model.metainfo.MetaSimpleProperty;
058: import es.udc.mypersonalizer.kernel.model.properties.CompoundProperty;
059: import es.udc.mypersonalizer.kernel.model.properties.PropertyNotFoundException;
060: import es.udc.mypersonalizer.kernel.model.tasks.*;
061: import es.udc.mypersonalizer.kernel.util.exceptions.InternalErrorException;
062:
063: /**
064: * Sample task that sends an e-mail to a user, aplying the following
065: * substitutions:
066: * ${name} : The user's name.
067: * ${surmane} : The user's surname.
068: *
069: * The e-mail text is read from the resource "email-template.txt", which
070: * must be in the classpath.
071: *
072: * @author Abel Muinho
073: */
074: public class SampleMailTask implements Task {
075: /** Name of the configuration resource. */
076: private static final String CONFIG_NAME = "SampleMailTask.properties";
077: /** Name of the property contaning the SMTP host. */
078: private static final String SMTP_HOST_PROP = "SampleMailTask.host";
079: /** Name of the property contaning the sender's e-mail address. */
080: private static final String SENDER_ADDRESS_PROP = "SampleMailTask.sender";
081: /** Name of the property contaning the message subject. */
082: private static final String SUBJECT_PROP = "SampleMailTask.subject";
083:
084: /** Tells if we the configuration is complete (i.e. if there is a
085: * value for every required parameter). It does not check if the
086: * parameters are valid.
087: */
088: private static final boolean configOK;
089:
090: /** Our mail server. */
091: private static final String host;
092: /** The address to use as the sender. */
093: private static final String from;
094: /** The subject of the email.*/
095: private static final String subject;
096:
097: private List messages = new ArrayList();
098:
099: static {
100: Properties config = new Properties();
101: boolean errors = false;
102: try {
103: InputStream configStream = null;
104: ClassLoader loader = SampleMailTask.class.getClassLoader();
105: configStream = loader.getResourceAsStream(CONFIG_NAME);
106: config.load(configStream);
107: } catch (Exception e) {
108: errors = true;
109: }
110: if (!errors) {
111: host = config.getProperty(SMTP_HOST_PROP);
112: from = config.getProperty(SENDER_ADDRESS_PROP);
113: subject = config.getProperty(SUBJECT_PROP);
114: configOK = host != null && from != null && subject != null;
115: } else {
116: configOK = false;
117: host = null;
118: from = null;
119: subject = null;
120: }
121: }
122:
123: /**
124: * The metaproperty must:
125: * <ul>
126: * <li>Be compound.</li>
127: * <li>Be single-valued.</li>
128: * <li>Have a <code>name</code> simple metaproperty, with type
129: * <code>String</code>.</li>
130: * <li>Have a <code>surname</code> simple metaproperty, with type
131: * <code>String</code>.</li>
132: * <li>Have a <code>email</code> simple metaproperty, with type
133: * <code>String</code>.</li>
134: * </ul>
135: * @see #validateSimpleString(MetaCompoundProperty, String)
136: */
137: public boolean isCompatibleWith(MetaProperty metadata) {
138: if (metadata.isMultiValued() == false
139: && metadata instanceof MetaCompoundProperty) {
140: MetaCompoundProperty mcp = (MetaCompoundProperty) metadata;
141: return validateSimpleString(mcp, "name")
142: && validateSimpleString(mcp, "surname")
143: && validateSimpleString(mcp, "email");
144: } else {
145: return false;
146: }
147: }
148:
149: /**
150: * Utility function for checking that the parent metaproperty has a child
151: * with the given name which:
152: * <ul>
153: * <li>Is singlevalued.</li>
154: * <li>Is a simple metaproperty</li>
155: * <li>Is of <code>java.lang.String</code> type.
156: * </ul>
157: * @param parent the parent metaproperty
158: * @param childName the child property name to be checked.
159: * @return <code>true</code> if the conditions are met, <code>false</code>
160: * otherwise.
161: */
162: private boolean validateSimpleString(MetaCompoundProperty parent,
163: String childName) {
164: try {
165: MetaProperty child = parent.findMetaProperty(childName);
166:
167: return child.isMultiValued() == false
168: && child instanceof MetaSimpleProperty
169: && ((MetaSimpleProperty) child).getJavaType()
170: .equals(String.class);
171: } catch (MetaPropertyNotFoundException e) {
172: return false;
173: }
174: }
175:
176: public void execute(Collection properties)
177: throws InternalErrorException {
178: if (!configOK) {
179: messages
180: .add("Invalid configuration resource, can't send any mail.");
181: throw new InternalErrorException(
182: "Invalid configuration resource (" + CONFIG_NAME
183: + "), can't send any mail.");
184: }
185:
186: Properties prop = new Properties();
187: prop.put("mail.smtp.host", host);
188: Session session = Session.getDefaultInstance(prop, null);
189: try {
190: ClassLoader loader = getClass().getClassLoader();
191: InputStream is = loader
192: .getResourceAsStream("email-template.txt");
193: BufferedReader reader = new BufferedReader(
194: new InputStreamReader(is));
195: String line;
196: StringBuffer templateBuffer = new StringBuffer(3000);
197: while ((line = reader.readLine()) != null) {
198: templateBuffer.append(line).append("\n");
199: }
200: String template = templateBuffer.toString();
201: templateBuffer = null; /* Allow it to be garbage-collected */
202: Iterator it = properties.iterator();
203: while (it.hasNext()) {
204: sendMail((CompoundProperty) it.next(), session,
205: template);
206: }
207: } catch (IOException e) {
208: messages.add("Error reading template mail file.");
209: throw new InternalErrorException(e);
210: }
211: }
212:
213: private void sendMail(CompoundProperty uri, Session ses,
214: String messageTemplate) throws InternalErrorException {
215: String to = null;
216: String name = null;
217: String surname = null;
218: try {
219: /* Does this user have a valid e-mail? */
220: if (uri.findProperty("0.email").getValuesAsString().length == 0) {
221: /* Silently ignore users without a mail address. These will
222: * probably be the special "mypersonalizer" and "anonymous"
223: * users.
224: */
225: return;
226: }
227: /* Get the parameters for the e-mail. */
228: to = uri.findProperty("0.email").getValuesAsString()[0];
229: name = uri.findProperty("0.name").getValuesAsString()[0];
230: surname = uri.findProperty("0.surname").getValuesAsString()[0];
231:
232: // Set the parameters
233: String message = messageTemplate.replaceAll(
234: "\\$\\{name\\}", name).replaceAll(
235: "\\$\\{surname\\}", surname);
236:
237: // The code to send mail
238: MimeMessage msg = new MimeMessage(ses);
239: msg.setFrom(new InternetAddress(from));
240: msg.addRecipient(Message.RecipientType.TO,
241: new InternetAddress(to));
242: msg.setSubject(subject);
243: msg.setText(message);
244: Transport.send(msg);
245: } catch (javax.mail.internet.AddressException ae) {
246: messages
247: .add("The e-mail address '"
248: + to
249: + "' contains format errors. Mail has not been sent.");
250: } catch (javax.mail.MessagingException me) {
251: messages.add("Unexpected errors sending mail to " + to
252: + ": " + me.getMessage());
253: } catch (PropertyNotFoundException e) {
254: messages.add("Not existant property " + e.getPropertyName()
255: + ".");
256: } catch (ArrayIndexOutOfBoundsException e) {
257: messages
258: .add("Some properties had no value, address skipped.");
259: }
260: }
261:
262: public Collection getMessages() {
263: return messages;
264: }
265: }
|