View Javadoc

1   /**
2    * $Id: SpringResourceManagerImpl.java 79 2006-12-15 21:39:11Z maldito_orco $
3    * $Revision: 79 $
4    * $Date: 2006-12-15 18:39:11 -0300 (Fri, 15 Dec 2006) $
5    *
6    * =========================================================================
7    *
8    * Copyright 2005 Tubo
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   */
22  package org.tubo.resource.springimpl;
23  
24  //log
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  //velocity
28  import org.apache.velocity.VelocityContext;
29  import org.apache.velocity.Template;
30  import org.apache.velocity.exception.ResourceNotFoundException;
31  import org.apache.velocity.exception.ParseErrorException;
32  import org.apache.velocity.app.Velocity;
33  //spring
34  import org.springframework.beans.factory.BeanFactory;
35  import org.springframework.beans.factory.BeanFactoryAware;
36  import org.springframework.beans.factory.xml.XmlBeanFactory;
37  import org.springframework.beans.BeansException;
38  import org.springframework.core.io.ByteArrayResource;
39  //tubo
40  import org.tubo.configuration.def.*;
41  import org.tubo.resource.Manager;
42  import org.tubo.resource.flow.FlowExecutor;
43  import org.tubo.resource.flow.FlowContext;
44  import org.tubo.resource.baseimpl.BaseAbstractResourceManager;
45  import org.tubo.exception.TuboResourceException;
46  import org.tubo.exception.ExceptionManager;
47  import org.tubo.exception.TuboException;
48  import org.tubo.item.Item;
49  import org.tubo.event.Event;
50  import org.tubo.kernel.Kernel;
51  //java-util
52  import java.util.Map;
53  import java.util.Iterator;
54  import java.util.Properties;
55  import java.util.HashMap;
56  //java-io
57  import java.io.StringWriter;
58  
59  /**
60   *
61   * Created: Dec 1, 2005 6:02:44 AM
62   * Last Modification Date: $Date: 2006-12-15 18:39:11 -0300 (Fri, 15 Dec 2006) $
63   *
64   * @author maldito_orco (maldito_orco@users.sourceforge.net)
65   * @version $Revision: 79 $
66   */
67  public class SpringResourceManagerImpl extends BaseAbstractResourceManager implements BeanFactoryAware {
68      public static final String RCS_ID = "$Id: SpringResourceManagerImpl.java 79 2006-12-15 21:39:11Z maldito_orco $";
69      private static Log log = LogFactory.getLog(SpringResourceManagerImpl.class);
70  
71      /** Template file for beans based on exceptions */
72      public final static String BEAN_EXCEPTION_MANAGER_TEMPLATE = "META-INF/templates/exception-manager-template.vm";
73  
74      /** Template file for beans based on exceptions */
75      public final static String BEAN_EXCEPTION_TEMPLATE = "META-INF/templates/exception-template.vm";
76  
77      /** Template file for beans based on consumers */
78      public final static String BEAN_CONSUMER_TEMPLATE = "META-INF/templates/bean-consumer-template.vm";
79  
80      /** Template file for beans based on components */
81      public final static String BEAN_COMPONENT_TEMPLATE = "META-INF/templates/bean-component-template.vm";
82  
83      /** Template file for beans based on flows */
84      public final static String BEAN_DEFAULT_TEMPLATE = "META-INF/templates/bean-default-template.vm";
85  
86      /** Template file for beans based on flows */
87      public final static String BEAN_FLOW_TEMPLATE = "META-INF/templates/bean-flow-template.vm";
88  
89      /** Header for every spring xml context file */
90      public static final String SPRING_CONTEXT_HEADFILE =
91              "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
92                      "<!DOCTYPE beans PUBLIC \"-//SPRING//DTD BEAN//EN\" \"http://www.springframework.org/dtd/spring-beans.dtd\">";
93  
94      /** Kernel bean ID */
95      public static final String SPRING_KERNEL_BEAN_ID = "kernel";
96  
97      /** ResourceManager bean ID */
98      public static final String SPRING_RESOURCE_MANAGER_BEAN_ID = "resourceManager";
99  
100     /** Item bean ID */
101     public static final String SPRING_ITEM_BEAN_ID = "item";
102 
103     /** Event bean ID */
104     public static final String SPRING_EVENT_BEAN_ID = "event";
105 
106     /** FlowContext bean ID */
107     public static final String SPRING_FLOW_CONTEXT_BEAN_ID = "flowContext";
108 
109     /** ExceptionManager bean ID */
110     public static final String SPRING_EXCEPTION_MANAGER_BEAN_ID = "exceptionManager";
111 
112     /** FlowExecutor bean ID */
113     public static final String SPRING_FLOW_EXECUTOR_BEAN_ID = "flowExecutor";
114 
115     /** Spring bean factory */
116     private BeanFactory beanFactory;
117 
118 
119     /**
120      * Default constructor protected. Used by test cases.
121      * Don't change. USED ONLY BY TEST CASES!
122      * @throws TuboResourceException
123      */
124     protected SpringResourceManagerImpl() throws TuboException {
125     }
126 
127     public BeanFactory getBeanFactory() {
128         return beanFactory;
129     }
130 
131     public void setBeanFactory(BeanFactory beanFactory) {
132         this.beanFactory = beanFactory;
133     }
134 
135 
136     /**
137      * <p>
138      * Get kernel instance
139      * </p>
140      * @return kernel instance
141      * @throws TuboException
142      */
143     public Kernel getKernel() throws TuboException {
144         Kernel kernel = null;
145         try {
146             //
147             // get Item via Spring
148             kernel = (Kernel)beanFactory.getBean(SPRING_KERNEL_BEAN_ID);
149         } catch (BeansException e) {
150             //
151             // log error
152             log.error("Error trying to get a KERNEL", e);
153             //
154             // throw
155             throw new TuboResourceException("Error trying to get a Kernel",e);
156         }
157         //
158         // return
159         return kernel;
160     }
161 
162 
163     /**
164      * <p>
165      * Create a new Item instance
166      * </p>
167      * @return new Item instance
168      * @throws TuboException
169      */
170     public Item getNewItem() throws TuboException {
171         Item item = null;
172         try {
173             //
174             // get Item via Spring
175             item = (Item)beanFactory.getBean(SPRING_ITEM_BEAN_ID);
176         } catch (BeansException e) {
177             //
178             // log error
179             log.error("Error trying to get an Item", e);
180             //
181             // throw
182             throw new TuboResourceException("Error trying to get an Item",e);
183         }
184         //
185         // return
186         return item;
187     }
188 
189     /**
190      * <p>
191      * Create a new Item instance
192      * </p>
193      * @return new Item instance
194      * @throws TuboException
195      */
196     public Event getNewEvent() throws TuboException {
197         Event event = null;
198         try {
199             //
200             // get Event via Spring
201             event = (Event)beanFactory.getBean(SPRING_EVENT_BEAN_ID);
202         } catch (BeansException e) {
203             //
204             // log error
205             log.error("Error trying to get an Event", e);
206             //
207             // throw
208             throw new TuboResourceException("Error trying to get an Event",e);
209         }
210         //
211         // return
212         return event;
213     }
214 
215     /**
216      * <p>
217      * Create a new FlowContext instance
218      * </p>
219      * @return new FlowContext instance
220      * @throws TuboException
221      */
222     public FlowContext getNewFlowContext() throws TuboException {
223         FlowContext flowContext = null;
224         try {
225             //
226             // get FlowContext via Spring
227             flowContext = (FlowContext)beanFactory.getBean(SPRING_FLOW_CONTEXT_BEAN_ID);
228         } catch (BeansException e) {
229             //
230             // log error
231             log.error("Error trying to get a FlowContext", e);
232             //
233             // throw
234             throw new TuboResourceException("Error trying to get a FlowContext",e);
235         }
236         //
237         // return
238         return flowContext;
239     }
240 
241     public ExceptionManager getExceptionManager() throws TuboException {
242         ExceptionManager manager = null;
243         try {
244             //
245             // get ExceptionManager via Spring
246             manager = (ExceptionManager)beanFactory.getBean(SPRING_EXCEPTION_MANAGER_BEAN_ID);
247         } catch (BeansException e) {
248             //
249             // log error
250             log.error("Error trying to get ExceptionManager", e);
251             //
252             // throw
253             throw new TuboResourceException("Error trying to get ExceptionManager '"+SPRING_EXCEPTION_MANAGER_BEAN_ID+"'",e);
254         }
255         //
256         // check if manager==null (I need to be sure of this ... this method can'tt return null!)
257         if (manager == null) {
258             //
259             // log error
260             log.error("Error when returning ExceptionManager, return null");
261             //
262             // throw
263             throw new TuboResourceException("Error when returning ExceptionManager, return null");
264         }
265         //
266         // return 
267         return manager;
268     }
269 
270     public FlowExecutor getFlowExecutor() throws TuboException {
271         FlowExecutor manager = null;
272         try {
273             //
274             // get FlowExecutor via Spring
275             manager = (FlowExecutor)beanFactory.getBean(SPRING_FLOW_EXECUTOR_BEAN_ID);
276         } catch (BeansException e) {
277             //
278             // log error
279             log.error("Error trying to get FlowExecutor", e);
280             //
281             // throw
282             throw getExceptionManager().getException(1302,SPRING_FLOW_EXECUTOR_BEAN_ID,e);
283         }
284         return manager;
285     }
286 
287     /**
288      * get a bean manager from spring
289      * @param id
290      * @return
291      */
292     public Manager getManager(String id) throws TuboException {
293         //
294         // reconfig id to adapt to all Managers
295         id = id+"Manager";
296         //
297         // get manager
298         Manager manager = null;
299         try {
300             //
301             // get manager via Spring
302             manager = (Manager)beanFactory.getBean(id);
303         } catch (BeansException e) {
304             //
305             // log error
306             log.error("Error trying to get Manager identified by '"+id+"'", e);
307             //
308             // throw
309             throw getExceptionManager().getException(1303,id,e);
310         }
311         //
312         // return
313         return manager;
314     }
315 
316 
317 
318 
319     public static SpringResourceManagerImpl newInstance(Configuration config) {
320         //
321         // trace
322         if (log.isTraceEnabled()) log.trace(".newInstance() - Enter");
323         //
324         // initialize velocity
325         initVelocity();
326         //
327         // create Spring resource descriptor based on configuration
328         String stringResource = null;
329         try {
330             stringResource = createSpringContext(config);
331         } catch (TuboResourceException e) {
332             throw new TuboResourceException("Tubo configuration can't be created",e);
333         }
334         //
335         // create Bean Factory
336         ByteArrayResource byteResource = new ByteArrayResource(stringResource.getBytes());
337         BeanFactory beanFactory = new XmlBeanFactory(byteResource);
338         //
339         // get resource manager
340         SpringResourceManagerImpl rm = null;
341         try {
342             //
343             // get FlowExecutor via Spring
344             rm = (SpringResourceManagerImpl)beanFactory.getBean(SPRING_RESOURCE_MANAGER_BEAN_ID);
345         } catch (BeansException e) {
346             //
347             // log error
348             log.error("Error trying to get ResourceManager", e);
349             //
350             // throw
351             throw new TuboResourceException("Error trying to get Spring ResourceManager",e);
352         }
353         //
354         // set configuration
355         // TODO: can be inyected? 
356         rm.setConfiguration(config);
357         //
358         // trace
359         if (log.isTraceEnabled()) log.trace(".newInstance() - Leave");
360         //
361         //  return resource manager
362         return rm;
363     }
364 
365 
366 
367 
368     /**
369      *
370      */
371     private static void initVelocity() throws TuboResourceException {
372         //
373         // setup velocity
374         //Velocity.init("velocity.properties"); TODO: ver de poder cargar estas propiedades desde un file
375         Properties p = new Properties();
376         p.setProperty("resource.loader", "class");
377         p.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
378         try {
379             Velocity.init(p);
380         } catch (Exception e) {
381             throw new TuboResourceException("Velocity can't be initialized",e);
382         }
383     }
384 
385     /**
386      * Create a Spring Context (Spring configuration) based on Configuration object.
387      * @param config Configuration
388      * @return A String with Spring representation of Configuration object.
389      */
390     protected static String createSpringContext(Configuration config) throws TuboResourceException {
391         //
392         // create StringBuffer
393         StringBuffer buffer = new StringBuffer();
394         //
395         // add string context head file
396         buffer.append(SPRING_CONTEXT_HEADFILE);
397         //
398         // open tag beans
399         buffer.append("<beans>");
400         //
401         // === Default configuration
402         //
403         // create ExceptionManager spring definition
404         appendSpringDefaultConfiguration(buffer,config);
405         //
406         // === Exception Contexts
407         //
408         // create ExceptionManager spring definition
409         appendSpringExceptionManagerDefinition(buffer);
410         //
411         // === Flow Contexts
412         //
413         // create Flows spring definitions
414         appendSpringFlowDefinition(buffer,config);
415         //
416         // get consumer defs
417         Map exceptionMap = config.getExceptionDefs();
418         //
419         // iterate exception Defs and append definitions to spring context
420         for (Iterator it=exceptionMap.values().iterator(); it.hasNext();) {
421             ExceptionDef def = (ExceptionDef)it.next();
422             //
423             // create Exception spring definition
424             buffer = appendSpringDefinition(buffer,def);
425         }
426         //
427         // === Consumer Contexts
428         //
429         // get consumer defs
430         Map consumersMap = config.getConsumerDefs();
431         //
432         // iterate consumer Defs and append definitions to spring context
433         for (Iterator it=consumersMap.values().iterator(); it.hasNext();) {
434             ConsumerDef def = (ConsumerDef)it.next();
435             //
436             // create spring definition
437             buffer = appendSpringDefinition(buffer,def);
438         }
439         //
440         // === Component Contexts
441         //
442         // get component Defs
443         Map componentsMap = config.getComponentDefs();
444         //
445         // iterate component Defs and append definitions to spring context
446         for (Iterator it=componentsMap.values().iterator(); it.hasNext();) {
447             ComponentDef def = (ComponentDef)it.next();
448             //
449             // create spring definition
450             buffer = appendSpringDefinition(buffer,def);
451         }
452         //
453         // close tag beans
454         buffer.append("</beans>");
455         //
456         // return Spring Resource
457         return buffer.toString();
458     }
459 
460     protected static StringBuffer appendSpringDefaultConfiguration(StringBuffer buffer, Configuration config) throws TuboResourceException {
461         //
462         // create Velocity props
463         Map props = new HashMap();
464         props.put("config",config);
465         //
466         // create spring definition (using Velocity)
467         buffer = appendSpringDefinition(buffer,null,BEAN_DEFAULT_TEMPLATE,props);
468         return buffer;
469     }
470 
471     protected static StringBuffer appendSpringFlowDefinition(StringBuffer buffer, Configuration config) throws TuboResourceException {
472         //
473         // create Velocity props
474         Map props = new HashMap();
475         props.put("config",config);
476         //
477         // create spring definition (using Velocity)
478         buffer = appendSpringDefinition(buffer,null,BEAN_FLOW_TEMPLATE,props);
479         return buffer;
480     }
481 
482     protected static StringBuffer appendSpringExceptionManagerDefinition(StringBuffer buffer) throws TuboResourceException {
483         //
484         // create Velocity props
485         Map props = new HashMap();
486         props.put("id",BEAN_EXCEPTION_MANAGER_TEMPLATE);
487         //
488         // create spring definition (using Velocity)
489         buffer = appendSpringDefinition(buffer,null,BEAN_EXCEPTION_MANAGER_TEMPLATE,props);
490         return buffer;
491     }
492 
493     protected static StringBuffer appendSpringDefinition(StringBuffer buffer, Definition def) throws TuboResourceException {
494         if (def instanceof ExceptionDef) {
495             buffer = appendSpringDefinition(buffer,def,BEAN_EXCEPTION_TEMPLATE,null);
496             return buffer;
497         }
498         if (def instanceof ConsumerDef) {
499             buffer = appendSpringDefinition(buffer,def,BEAN_CONSUMER_TEMPLATE,null);
500             return buffer;
501         }
502         if (def instanceof ComponentDef) {
503             buffer = appendSpringDefinition(buffer,def,BEAN_COMPONENT_TEMPLATE,null);
504             return buffer;
505         }
506         throw new TuboResourceException("Definition type not know.");
507     }
508 
509     /**
510      * Append a Spring configuration of ComponentDef instance.
511      * @param buffer Spring configuration
512      * @param def A ComponentDef instance
513      * @return The same StringBuffer but with a new component (bean) definition append to end;
514      */
515     protected static StringBuffer appendSpringDefinition(StringBuffer buffer, Definition def, String templateFile, Map props) throws TuboResourceException {
516         try {
517             //
518             // Make a context object and populate with the data.  This
519             // is where the Velocity engine gets the data to resolve the
520             // references (ex. $list) in the template
521             VelocityContext context = new VelocityContext();
522             context.put("def", def);
523             //
524             // add props to Velocity context
525             if (props!=null)
526                 for(Iterator it=props.keySet().iterator(); it.hasNext();) {
527                     String key = (String)it.next();
528                     Object value = props.get(key);
529                     context.put(key,value);
530                 }
531             //
532             // get the Template object.  This is the parsed version of your
533             // template input file.  Note that getTemplate() can throw
534             // ResourceNotFoundException : if it doesn't find the template
535             // ParseErrorException : if there is something wrong with the VTL
536             // Exception : if something else goes wrong (this is generally
537             // indicative of as serious problem...)
538             Template template =  null;
539             try {
540                 template = Velocity.getTemplate(templateFile);
541             } catch( ResourceNotFoundException rnfe ) {
542                 throw new TuboResourceException("Velocity template "+templateFile+" can't be founded",rnfe);
543             } catch( ParseErrorException pee ) {
544                 throw new TuboResourceException("Velocity parsing error procesing template "+templateFile,pee);
545             }
546             //
547             // Now have the template engine process your template using the
548             // data placed into the context.  Think of it as a  'merge'
549             // of the template and the data to produce the output stream.
550             StringWriter writer = new StringWriter();
551             if ( template != null)
552                 template.merge(context, writer);
553             //
554             //  flush and cleanup
555             writer.flush();
556             writer.close();
557 
558             buffer.append(writer.toString());
559         } catch (Exception e) {
560             throw new TuboResourceException("Error creating spring definition",e);
561         }
562         return buffer;
563     }
564 
565 }