001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    
021    package org.apache.mailet.base;
022    
023    import javax.mail.MessagingException;
024    
025    import org.apache.mailet.Mail;
026    import org.apache.mailet.Mailet;
027    import org.apache.mailet.MailetConfig;
028    import org.apache.mailet.MailetContext;
029    import org.apache.mailet.MailetContext.LogLevel;
030    
031    import java.util.*;
032    
033    /**
034     * GenericMailet makes writing mailets easier. It provides simple
035     * versions of the lifecycle methods init and destroy and of the methods
036     * in the MailetConfig interface. GenericMailet also implements the log
037     * method, declared in the MailetContext interface.
038     * <p>
039     * To write a generic mailet, you need only override the abstract service
040     * method.
041     *
042     * @version 1.0.0, 24/04/1999
043     */
044    public abstract class GenericMailet implements Mailet, MailetConfig {
045        private MailetConfig config = null;
046    
047        /**
048         * Called by the mailer container to indicate to a mailet that the
049         * mailet is being taken out of service.
050         */
051        public void destroy() {
052            //Do nothing
053        }
054    
055        /**
056         * <p>Gets a boolean valued init parameter.</p>
057         * <p>A convenience method. The result is parsed
058         * from the value of the named parameter in the {@link MailetConfig}.</p>
059         * @param name name of the init parameter to be queried
060         * @param defaultValue this value will be substituted when the named value
061         * cannot be parse or when the init parameter is absent
062         * @return true when the init parameter is <code>true</code> (ignoring case);
063         * false when the init parameter is <code>false</code> (ignoring case);
064         * otherwise the default value
065         * @throws NullPointerException before {@link #init(MailetConfig)}
066         */
067        public boolean getInitParameter(String name, boolean defaultValue) {
068            if (config == null) {
069                throw new NullPointerException("Mailet configuration must be set before getInitParameter is called.");
070            }
071            return MailetUtil.getInitParameter(config, name, defaultValue);
072        }
073        
074        /**
075         * Returns a String containing the value of the named initialization
076         * parameter, or null if the parameter does not exist.
077         * <p>
078         * This method is supplied for convenience. It gets the value of the
079         * named parameter from the mailet's MailetConfig object.
080         *
081         * @param name - a String specifying the name of the initialization parameter
082         * @return a String containing the value of the initalization parameter
083         */
084        public String getInitParameter(String name) {
085            return config.getInitParameter(name);
086        }
087    
088        /**
089         * Returns a String containing the value of the named initialization
090         * parameter, or defValue if the parameter does not exist.
091         * <p>
092         * This method is supplied for convenience. It gets the value of the
093         * named parameter from the mailet's MailetConfig object.
094         *
095         * @param name - a String specifying the name of the initialization parameter
096         * @param defValue - a String specifying the default value when the parameter
097         *                    is not present
098         * @return a String containing the value of the initalization parameter
099         */
100        public String getInitParameter(String name, String defValue) {
101            String res = config.getInitParameter(name);
102            if (res == null) {
103                return defValue;
104            } else {
105                return res;
106            }
107        }
108    
109        /**
110         * Returns the names of the mailet's initialization parameters as an
111         * Iterator of String objects, or an empty Iterator if the mailet has no
112         * initialization parameters.
113         * <p>
114         * This method is supplied for convenience. It gets the parameter names from
115         * the mailet's MailetConfig object.
116         *
117         * @return an Iterator of String objects containing the names of
118         *          the mailet's initialization parameters
119         */
120        public Iterator<String> getInitParameterNames() {
121            return config.getInitParameterNames();
122        }
123    
124        /**
125         * Returns this Mailet's MailetConfig object.
126         *
127         * @return the MailetConfig object that initialized this mailet
128         */
129        public MailetConfig getMailetConfig() {
130            return config;
131        }
132    
133        /**
134         * Returns a reference to the MailetContext in which this mailet is
135         * running.
136         *
137         * @return the MailetContext object passed to this mailet by the init method
138         */
139        public MailetContext getMailetContext() {
140            return getMailetConfig().getMailetContext();
141        }
142    
143        /**
144         * Returns information about the mailet, such as author, version, and
145         * copyright.  By default, this method returns an empty string. Override
146         * this method to have it return a meaningful value.
147         *
148         * @return information about this mailet, by default an empty string
149         */
150        public String getMailetInfo() {
151            return "";
152        }
153    
154        /**
155         * Returns the name of this mailet instance.
156         *
157         * @return the name of this mailet instance
158         */
159        public String getMailetName() {
160            return config.getMailetName();
161        }
162    
163    
164        /**
165         * <p>Called by the mailet container to indicate to a mailet that the
166         * mailet is being placed into service.</p>
167         *
168         * <p>This implementation stores the MailetConfig object it receives from
169         * the mailet container for later use. When overriding this form of the
170         * method, call super.init(config).</p>
171         *
172         * @param newConfig - the MailetConfig object that contains
173         *          configutation information for this mailet
174         * @throws MessagingException
175         *          if an exception occurs that interrupts the mailet's normal operation
176         */
177        public void init(MailetConfig newConfig) throws MessagingException {
178            config = newConfig;
179            init();
180        }
181    
182        /**
183         * <p>A convenience method which can be overridden so that there's no
184         * need to call super.init(config).</p>
185         *
186         * Instead of overriding init(MailetConfig), simply override this
187         * method and it will be called by GenericMailet.init(MailetConfig config).
188         * The MailetConfig object can still be retrieved via getMailetConfig().
189         *
190         * @throws MessagingException
191         *          if an exception occurs that interrupts the mailet's normal operation
192         */
193        public void init() throws MessagingException {
194            //Do nothing... can be overriden
195        }
196    
197        /**
198         * Writes the specified message to a mailet log file.
199         *
200         * @param message - a String specifying the message to be written to the log file
201         */
202        public void log(String message) {
203            getMailetContext().log(LogLevel.INFO, message);
204        }
205    
206        /**
207         * Writes an explanatory message and a stack trace for a given Throwable
208         * exception to the mailet log file.
209         *
210         * @param message - a String that describes the error or exception
211         * @param t - the java.lang.Throwable to be logged
212         */
213        public void log(String message, Throwable t) {
214            getMailetContext().log(LogLevel.ERROR, message, t);
215        }
216    
217        /**
218         * <p>Called by the mailet container to allow the mailet to process a
219         * message.</p>
220         *
221         * <p>This method is declared abstract so subclasses must override it.</p>
222         *
223         * @param mail - the Mail object that contains the MimeMessage and
224         *          routing information
225         * @throws javax.mail.MessagingException - if an exception occurs that interferes with the mailet's normal operation
226         */
227        public abstract void service(Mail mail) throws javax.mail.MessagingException;
228        
229        
230        
231        /**
232         * Utility method: Checks if there are unallowed init parameters specified in the 
233         * configuration file against the String[] allowedInitParameters.
234         * @param allowedArray array of strings containing the allowed parameter names
235         * @throws MessagingException if an unknown parameter name is found
236         */
237        protected final void checkInitParameters(String[] allowedArray) throws MessagingException {
238            // if null then no check is requested
239            if (allowedArray == null) {
240                return;
241            }
242            
243            Collection<String> allowed = new HashSet<String>();
244            Collection<String> bad = new ArrayList<String>();
245    
246            Collections.addAll(allowed, allowedArray);
247            
248            Iterator<String> iterator = getInitParameterNames();
249            while (iterator.hasNext()) {
250                String parameter = iterator.next();
251                if (!allowed.contains(parameter)) {
252                    bad.add(parameter);
253                }
254            }
255            
256            if (bad.size() > 0) {
257                throw new MessagingException("Unexpected init parameters found: "
258                        + arrayToString(bad.toArray()));
259            }
260        }
261        
262        /**
263         * Utility method for obtaining a string representation of an array of Objects.
264         */
265        protected final String arrayToString(Object[] array) {
266            if (array == null) {
267                return "null";
268            }
269            StringBuilder sb = new StringBuilder(1024);
270            sb.append("[");
271            for (int i = 0; i < array.length; i++) {
272                if (i > 0) {
273                    sb.append(",");
274                }
275                sb.append(array[i]);
276            }
277            sb.append("]");
278            return sb.toString();
279        }
280    
281    }
282    
283