001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2001, Institut de Recherche pour le Développement
006: * (C) 1999, Pêches et Océans Canada
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation; either
011: * version 2.1 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: */
018: package org.geotools.gui.headless;
019:
020: // J2SE dependencies
021: import java.util.Date;
022: import java.util.Locale;
023: import java.util.Properties;
024: import java.util.logging.Level;
025: import java.util.logging.LogRecord;
026:
027: // Formatting
028: import java.io.PrintWriter;
029: import java.io.CharArrayWriter;
030: import java.text.NumberFormat;
031: import java.text.FieldPosition;
032:
033: // Java Mail
034: import javax.mail.Session;
035: import javax.mail.Address;
036: import javax.mail.Message;
037: import javax.mail.Transport;
038: import javax.mail.MessagingException;
039: import javax.mail.internet.MimeMessage;
040: import javax.mail.internet.InternetAddress;
041: import javax.mail.internet.AddressException;
042:
043: // Geotools dependencies
044: import org.geotools.util.ProgressListener;
045: import org.geotools.util.SimpleInternationalString;
046: import org.geotools.util.logging.Logging;
047: import org.geotools.resources.Utilities;
048: import org.geotools.resources.i18n.Vocabulary;
049: import org.geotools.resources.i18n.VocabularyKeys;
050: import org.opengis.util.InternationalString;
051:
052: /**
053: * Reports progress by sending email to the specified address at regular interval.
054: *
055: * @since 2.0
056: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/widgets-swing/src/main/java/org/geotools/gui/headless/ProgressMailer.java $
057: * @version $Id: ProgressMailer.java 27862 2007-11-12 19:51:19Z desruisseaux $
058: * @author Martin Desruisseaux
059: */
060: public class ProgressMailer implements ProgressListener {
061: /**
062: * Nom de l'opération en cours. Le pourcentage sera écris à la droite de ce nom.
063: */
064: private String description;
065:
066: /**
067: * Langue à utiliser pour le formattage.
068: */
069: private final Locale locale;
070:
071: /**
072: * Session à utiliser pour envoyer des courriels.
073: */
074: private final Session session;
075:
076: /**
077: * Adresses des personnes à qui envoyer un rapport sur les progrès.
078: */
079: private final Address[] address;
080:
081: /**
082: * Laps de temps entre deux courriers électroniques informant des progrès.
083: * On attendra que ce laps de temps soit écoulés avant d'envoyer un nouveau courriel.
084: */
085: private long timeInterval = 3 * 60 * 60 * 1000L;
086:
087: /**
088: * Date et heure à laquelle envoyer le prochain courriel.
089: */
090: private long nextTime;
091:
092: /**
093: * {@code true} if the action has been canceled.
094: */
095: private volatile boolean canceled;
096:
097: /**
098: * Creates an objects reporting progress to the specified email address.
099: *
100: * @param host The server to use for sending emails.
101: * @param address Email adress where to send progress reports.
102: * @throws AddressException if the specified address use an invalid syntax.
103: */
104: public ProgressMailer(final String host, final String address)
105: throws AddressException {
106: this (Session.getDefaultInstance(properties(host)),
107: new InternetAddress[] { new InternetAddress(address) });
108: }
109:
110: /**
111: * Creates an objects reporting progress to the specified email adresses.
112: *
113: * @param session Session to use for sending emails.
114: * @param address
115: */
116: public ProgressMailer(final Session session, final Address[] address) {
117: this .session = session;
118: this .address = address;
119: this .locale = Locale.getDefault();
120: nextTime = System.currentTimeMillis();
121: }
122:
123: /**
124: * Retourne un ensemble de propriétés nécessaires pour ouvrir une session.
125: *
126: * @param host Nom du serveur à utiliser pour envoyer des courriels.
127: */
128: private static final Properties properties(final String host) {
129: final Properties props = new Properties();
130: props.setProperty("mail.smtp.host", host);
131: return props;
132: }
133:
134: /**
135: * Returns the time laps (in milliseconds) between two emails.
136: */
137: public long getTimeInterval() {
138: return timeInterval;
139: }
140:
141: /**
142: * Set the time laps (in milliseconds) between two emails.
143: * The default value is 3 hours.
144: */
145: public synchronized void setTimeInterval(final long interval) {
146: this .timeInterval = interval;
147: }
148:
149: /**
150: * {@inheritDoc}
151: *
152: * @deprecated Replaced by {@link #getTask}.
153: */
154: public String getDescription() {
155: return description;
156: }
157:
158: /**
159: * {@inheritDoc}
160: *
161: * @deprecated Replaced by {@link #setTask}.
162: */
163: public synchronized void setDescription(final String description) {
164: this .description = description;
165: }
166:
167: /**
168: * {@inheritDoc}
169: *
170: * @since 2.3
171: */
172: public void setTask(final InternationalString task) {
173: setDescription(task.toString());
174: }
175:
176: /**
177: * {@inheritDoc}
178: *
179: * @since 2.3
180: */
181: public InternationalString getTask() {
182: return new SimpleInternationalString(getDescription());
183: }
184:
185: /**
186: * Envoie le message spécifié par courrier électronique.
187: *
188: * @param method Nom de la méthode qui appelle celle-ci. Cette information
189: * est utilisée pour produire un message d'erreur en cas d'échec.
190: * @param subjectKey Clé du sujet: {@link ResourceKeys#PROGRESS},
191: * {@link ResourceKeys#WARNING} ou {@link ResourceKeys#EXCEPTION}.
192: * @param messageText Message à envoyer par courriel.
193: */
194: private void send(final String method, final int subjectKey,
195: final String messageText) {
196: try {
197: final Message message = new MimeMessage(session);
198: message.setFrom();
199: message.setRecipients(Message.RecipientType.TO, address);
200: message.setSubject(Vocabulary.getResources(locale)
201: .getString(subjectKey));
202: message.setSentDate(new Date());
203: message.setText(messageText);
204: Transport.send(message);
205: } catch (MessagingException exception) {
206: final LogRecord warning = new LogRecord(Level.WARNING,
207: "CATCH " + Utilities.getShortClassName(exception));
208: warning.setSourceClassName(ProgressMailer.class.getName());
209: warning.setSourceMethodName(method);
210: warning.setThrown(exception);
211: Logging.getLogger("org.geotools.gui.progress").log(warning);
212: }
213: }
214:
215: /**
216: * Envoie par courrier électronique un rapport des progrès.
217: *
218: * @param method Nom de la méthode qui appelle celle-ci. Cette information
219: * est utilisée pour produire un message d'erreur en cas d'échec.
220: * @param percent Pourcentage effectué (entre 0 et 100).
221: */
222: private void send(final String method, final float percent) {
223: final Runtime system = Runtime.getRuntime();
224: final float MEMORY_UNIT = (1024f * 1024f);
225: final float freeMemory = system.freeMemory() / MEMORY_UNIT;
226: final float totalMemory = system.totalMemory() / MEMORY_UNIT;
227: final Vocabulary resources = Vocabulary.getResources(locale);
228: final NumberFormat format = NumberFormat
229: .getPercentInstance(locale);
230: final StringBuffer buffer = new StringBuffer(
231: description != null ? description : resources
232: .getString(VocabularyKeys.PROGRESSION));
233: buffer.append(": ");
234: format.format(percent / 100, buffer, new FieldPosition(0));
235: buffer.append('\n');
236: buffer.append(resources.getString(
237: VocabularyKeys.MEMORY_HEAP_SIZE_$1, new Float(
238: totalMemory)));
239: buffer.append('\n');
240: buffer.append(resources.getString(
241: VocabularyKeys.MEMORY_HEAP_USAGE_$1, new Float(1
242: - freeMemory / totalMemory)));
243: buffer.append('\n');
244: send(method, VocabularyKeys.PROGRESSION, buffer.toString());
245: }
246:
247: /**
248: * Send an emails saying that the operation started.
249: */
250: public synchronized void started() {
251: send("started", 0);
252: }
253:
254: /**
255: * Notifies progress. This method will send an email only if at least the amount
256: * of time specified by {@link #setTimeInterval} is ellapsed since the last email.
257: */
258: public synchronized void progress(float percent) {
259: final long time = System.currentTimeMillis();
260: if (time > nextTime) {
261: nextTime = time + timeInterval;
262: if (percent < 1f)
263: percent = 1f;
264: if (percent > 99f)
265: percent = 99f;
266: send("progress", percent);
267: }
268: }
269:
270: /**
271: * Send an emails saying that the operation finished.
272: */
273: public synchronized void complete() {
274: send("complete", 100);
275: }
276:
277: /**
278: * Releases any resource used by this object.
279: */
280: public void dispose() {
281: }
282:
283: /**
284: * {@inheritDoc}
285: */
286: public boolean isCanceled() {
287: return canceled;
288: }
289:
290: /**
291: * {@inheritDoc}
292: */
293: public void setCanceled(final boolean canceled) {
294: this .canceled = canceled;
295: }
296:
297: /**
298: * Send a warning by email.
299: */
300: public synchronized void warningOccurred(final String source,
301: final String margin, final String warning) {
302: final StringBuffer buffer = new StringBuffer();
303: if (source != null) {
304: buffer.append(source);
305: if (margin != null) {
306: buffer.append(" (");
307: buffer.append(margin);
308: buffer.append(')');
309: }
310: buffer.append(": ");
311: } else if (margin != null) {
312: buffer.append(margin);
313: buffer.append(": ");
314: }
315: buffer.append(warning);
316: send("warningOccurred", VocabularyKeys.WARNING, buffer
317: .toString());
318: }
319:
320: /**
321: * Send an exception stack trace by email.
322: */
323: public synchronized void exceptionOccurred(final Throwable exception) {
324: final CharArrayWriter buffer = new CharArrayWriter();
325: exception.printStackTrace(new PrintWriter(buffer));
326: send("exceptionOccurred", VocabularyKeys.EXCEPTION, buffer
327: .toString());
328: }
329: }
|