001    /*
002     * Copyright 2010 the original author or authors.
003     * 
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package com.hs.mail.sieve;
017    
018    import java.lang.reflect.InvocationTargetException;
019    import java.lang.reflect.Method;
020    import java.util.HashMap;
021    import java.util.Map;
022    
023    import javax.mail.MessagingException;
024    
025    import org.apache.jsieve.mail.Action;
026    import org.apache.jsieve.mail.ActionFileInto;
027    import org.apache.jsieve.mail.ActionKeep;
028    import org.apache.jsieve.mail.ActionRedirect;
029    import org.apache.jsieve.mail.ActionReject;
030    import org.apache.jsieve.mail.MailAdapter;
031    
032    import com.hs.mail.mailet.MailetContext;
033    
034    public class ActionDispatcher {
035            /**
036             * The sole instance of the receiver.
037             */
038            static private ActionDispatcher fieldInstance;
039    
040            /**
041             * A Map keyed by the type of Action. The values are the methods to invoke
042             * to handle the Action.
043             */
044            private Map fieldMethodMap;
045    
046            /**
047             * Constructor for ActionDispatcher.
048             */
049            private ActionDispatcher() {
050                    super();
051            }
052    
053            /**
054             * Returns the sole instance of the receiver, lazily initialised.
055             * 
056             * @return ActionDispatcher
057             */
058            public static synchronized ActionDispatcher getInstance() {
059                    ActionDispatcher instance = null;
060                    if (null == (instance = getInstanceBasic())) {
061                            updateInstance();
062                            return getInstance();
063                    }
064                    return instance;
065            }
066    
067            /**
068             * Returns the sole instance of the receiver.
069             * 
070             * @return ActionDispatcher
071             */
072            private static ActionDispatcher getInstanceBasic() {
073                    return fieldInstance;
074            }
075    
076            /**
077             * Returns a new instance of the receiver.
078             * 
079             * @return ActionDispatcher
080             */
081            protected static ActionDispatcher computeInstance() {
082                    return new ActionDispatcher();
083            }
084    
085            /**
086             * Sets the instance.
087             * 
088             * @param instance
089             *            The instance to set
090             */
091            protected static void setInstance(ActionDispatcher instance) {
092                    fieldInstance = instance;
093            }
094    
095            /**
096             * Resets the instance.
097             */
098            public static void resetInstance() {
099                    setInstance(null);
100            }
101    
102            /**
103             * Updates the instance.
104             */
105            protected static void updateInstance() {
106                    setInstance(computeInstance());
107            }
108    
109        /**
110         * Method execute executes the passed Action by invoking the method mapped by the
111         * receiver with a parameter of the EXACT type of Action.
112         * @param anAction
113         * @param aMail
114         * @param aMailetContext
115         * @throws NoSuchMethodException
116         * @throws IllegalAccessException
117         * @throws InvocationTargetException
118         * @throws MessagingException
119         */
120            public void execute(Action anAction, MailAdapter aMail,
121                            MailetContext aMailetContext) throws NoSuchMethodException,
122                            IllegalArgumentException, IllegalAccessException,
123                            InvocationTargetException {
124                    Method actionMethod = (Method) getMethodMap().get(anAction.getClass());
125                    if (null == actionMethod)
126                            throw new NoSuchMethodException("Method accepting parameters ("
127                                            + anAction.getClass().getName() + ", "
128                                            + aMail.getClass().getName() + ", "
129                                            + aMailetContext.getClass().getName() + ") not mapped.");
130                    actionMethod.invoke(null, new Object[] { anAction, aMail,
131                                    aMailetContext });
132            }
133    
134            /**
135             * Returns the methodMap, lazily initialised.
136             * 
137             * @return Map
138             * @throws NoSuchMethodException
139             */
140            protected synchronized Map getMethodMap() throws NoSuchMethodException {
141                    Map methodMap = null;
142                    if (null == (methodMap = getMethodMapBasic())) {
143                            updateMethodMap();
144                            return getMethodMap();
145                    }
146                    return methodMap;
147            }
148    
149            /**
150             * Returns the methodMap.
151             * 
152             * @return Map
153             */
154            private Map getMethodMapBasic() {
155                    return fieldMethodMap;
156            }
157    
158        /**
159         * Returns a new methodMap.
160         * @return Map
161         */
162            protected Map computeMethodMap() throws NoSuchMethodException {
163                    Map methodNameMap = new HashMap();
164            methodNameMap.put(
165                    ActionFileInto.class,
166                    Actions.class.getMethod(
167                        "execute",
168                        new Class[] {
169                            ActionFileInto.class,
170                            SieveMailAdapter.class,
171                            MailetContext.class }));
172                methodNameMap.put(
173                    ActionKeep.class,
174                    Actions.class.getMethod(
175                        "execute",
176                        new Class[] {
177                            ActionKeep.class,
178                            SieveMailAdapter.class,
179                            MailetContext.class }));
180                methodNameMap.put(
181                    ActionRedirect.class,
182                    Actions.class.getMethod(
183                        "execute",
184                        new Class[] {
185                            ActionRedirect.class,
186                            SieveMailAdapter.class,
187                            MailetContext.class }));
188                methodNameMap.put(
189                    ActionReject.class,
190                    Actions.class.getMethod(
191                        "execute",
192                        new Class[] {
193                            ActionReject.class,
194                            SieveMailAdapter.class,
195                            MailetContext.class }));
196            return methodNameMap;
197            }
198        
199            /**
200             * Sets the methodMap.
201             * 
202             * @param methodMap
203             *            The methodMap to set
204             */
205            protected void setMethodMap(Map methodMap) {
206                    fieldMethodMap = methodMap;
207            }
208    
209            /**
210             * Updates the methodMap.
211             * 
212             * @throws NoSuchMethodException
213             */
214            protected void updateMethodMap() throws NoSuchMethodException {
215                    setMethodMap(computeMethodMap());
216            }
217    
218    }