001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/framework/trigger/TriggerProvider.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.framework.trigger;
044    
045    import java.lang.reflect.Constructor;
046    import java.net.URL;
047    import java.util.ArrayList;
048    import java.util.HashMap;
049    import java.util.List;
050    import java.util.Map;
051    
052    import org.deegree.framework.log.ILogger;
053    import org.deegree.framework.log.LoggerFactory;
054    import org.deegree.framework.trigger.TriggerCapabilities.TRIGGER_TYPE;
055    import org.deegree.framework.util.BootLogger;
056    import org.deegree.i18n.Messages;
057    
058    /**
059     * 
060     * 
061     * 
062     * @version $Revision: 9339 $
063     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
064     * @author last edited by: $Author: apoth $
065     * 
066     * @version 1.0. $Revision: 9339 $, $Date: 2007-12-27 13:31:52 +0100 (Do, 27 Dez 2007) $
067     * 
068     * @since 2.0
069     */
070    public class TriggerProvider {
071    
072        private static Map<String, TriggerProvider> providerMap = new HashMap<String, TriggerProvider>();
073    
074        private static TriggerCapabilities triggerCapabilities;
075        
076        private static final ILogger LOG = LoggerFactory.getLogger( TriggerProvider.class );
077    
078        static {
079            try {
080                URL url = TriggerProvider.class.getResource( "triggerConfiguration.xml" );
081                TriggerConfigurationDocument doc = new TriggerConfigurationDocument();
082                doc.load( url );
083                triggerCapabilities = doc.parseTriggerCapabilities();
084                // try reading trigger definitions from root that may overrides
085                // default trigger
086                url = TriggerProvider.class.getResource( "/triggerConfiguration.xml" );
087                try {
088    
089                    if ( url != null ) {
090                        LOG.logDebug( "Trying to create trigger from local configuration: " + url );
091                        doc = new TriggerConfigurationDocument();
092                        doc.load( url );
093                        TriggerCapabilities temp = doc.parseTriggerCapabilities();
094                        triggerCapabilities.merge( temp );
095                    } else {
096                        LOG.logDebug( "No local configuration found." );
097                    }
098    
099                } catch ( Exception e ) {
100                    e.printStackTrace();
101                    BootLogger.log( "!!! BOOTLOG: No valid trigger configuration available from root." );
102                }
103            } catch ( Exception e ) {
104                e.printStackTrace();
105            }
106        }
107    
108        private String className = null;
109    
110        private TriggerProvider( String className ) {
111            this.className = className;
112        }
113    
114        /**
115         * 
116         * @param clss
117         */
118        public static TriggerProvider create( Class clss ) {
119            String s = clss.getName();
120            if ( providerMap.get( s ) == null ) {
121                providerMap.put( s, new TriggerProvider( s ) );
122            }
123            return providerMap.get( s );
124        }
125    
126        /**
127         * @return all pre triggers assigend to the calling method
128         */
129        public List<Trigger> getPreTrigger()
130                                            throws TriggerException {
131    
132            List<Trigger> trigger = new ArrayList<Trigger>();
133    
134            StackTraceElement[] st = Thread.currentThread().getStackTrace();
135    
136            String mn = null;
137            for ( int i = 0; i < st.length; i++ ) {
138                if ( st[i].getClassName().equals( className ) ) {
139                    mn = st[i].getMethodName();
140                    break;
141                }
142            }
143            if ( mn != null ) {
144                TriggerCapability tc = triggerCapabilities.getTriggerCapability( className,
145                                                                                 mn,
146                                                                                 TRIGGER_TYPE.PRE );
147                if ( tc != null ) {
148                    appendTrigger( trigger, tc );
149    
150                    List<TriggerCapability> tCaps = tc.getTrigger();
151                    for ( int i = 0; i < tCaps.size(); i++ ) {
152                        appendTrigger( trigger, tCaps.get( i ) );
153                    }
154                }
155            }
156    
157            return trigger;
158        }
159    
160        /**
161         * returns all post triggers assigend to the calling method
162         * 
163         * @return all post triggers assigend to the calling method
164         */
165        public List<Trigger> getPostTrigger()
166                                             throws TriggerException {
167            List<Trigger> trigger = new ArrayList<Trigger>();
168    
169            StackTraceElement[] st = Thread.currentThread().getStackTrace();
170            String mn = null;
171            for ( int i = 0; i < st.length; i++ ) {
172                if ( st[i].getClassName().equals( className ) ) {
173                    mn = st[i].getMethodName();
174                    break;
175                }
176            }
177    
178            if ( mn != null ) {
179                TriggerCapability tc = triggerCapabilities.getTriggerCapability( className, mn, TRIGGER_TYPE.POST );
180    
181                if ( tc != null ) {
182                    appendTrigger( trigger, tc );
183    
184                    List<TriggerCapability> tCaps = tc.getTrigger();
185                    for ( int i = 0; i < tCaps.size(); i++ ) {
186                        appendTrigger( trigger, tCaps.get( i ) );
187                    }
188                }
189            }
190            return trigger;
191        }
192    
193        /**
194         * creates a Trigger instance from the passed TriggerCapability and add it to the passed list. If the
195         * TriggerCapability contains futher TriggerCapability entries they will also be added within a recursion
196         * 
197         * @param trigger
198         * @param tc
199         * @return extended list
200         * @throws TriggerException
201         */
202        private List<Trigger> appendTrigger( List<Trigger> trigger, TriggerCapability tc )
203                                                                                          throws TriggerException {
204            Class clss = tc.getPerformingClass();
205            List<String> paramNames = tc.getInitParameterNames();
206            Class[] initClasses = new Class[paramNames.size()];
207            Object[] paramVals = new Object[paramNames.size()];
208            for ( int i = 0; i < initClasses.length; i++ ) {
209                paramVals[i] = tc.getInitParameterValue( paramNames.get( i ) );
210                initClasses[i] = paramVals[i].getClass();
211            }
212            try {
213                Constructor cstrtr = clss.getConstructor( initClasses );
214                LOG.logDebug( "Trying to instantiate new class" );
215                trigger.add( (Trigger) cstrtr.newInstance( paramVals ) );
216                LOG.logDebug( "Succesfully instantiated configured trigger class." );
217            } catch ( Exception e ) {
218                e.printStackTrace();
219                throw new TriggerException( Messages.getMessage( "FRAMEWORK_ERROR_INITIALIZING_TRIGGER", clss ) );
220            }
221            return trigger;
222        }
223    
224        /**
225         * performs pre triggers assigend to the calling method
226         * 
227         * @param caller
228         * @param obj
229         * @return changed object passed to the trigger(s)
230         * @throws TriggerException
231         */
232        public Object[] doPreTrigger( Object caller, Object... obj )
233                                                                    throws TriggerException {
234            List<Trigger> list = getPreTrigger();
235            if( LOG.getLevel() == ILogger.LOG_DEBUG ){
236                LOG.logDebug("list of appliable pretriggers: " + list );
237            }
238            for ( int i = 0; i < list.size(); i++ ) {
239                obj = list.get( i ).doTrigger( caller, obj );
240            }
241            return obj;
242        }
243    
244        /**
245         * performs post triggers assigend to the calling method
246         * 
247         * @param caller
248         * @param obj
249         * @return changed object passed to the trigger(s)
250         */
251        public Object[] doPostTrigger( Object caller, Object... obj ) {
252            List<Trigger> list = getPostTrigger();
253            if( LOG.getLevel() == ILogger.LOG_DEBUG ){
254                LOG.logDebug("list of appliable posttriggers: " + list );
255            }
256            for ( int i = 0; i < list.size(); i++ ) {
257                obj = list.get( i ).doTrigger( caller, obj );
258            }
259            return obj;
260        }
261    
262        /**
263         * returns the root capabilities
264         * 
265         * @return the root capabilities
266         */
267        public TriggerCapabilities getCapabilities() {
268            return triggerCapabilities;
269        }
270    
271    }