KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > commands > MgnlCommand


1 /**
2  *
3  * Magnolia and its source-code is licensed under the LGPL.
4  * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
5  * When copying, adapting, or redistributing this document in keeping with the guidelines above,
6  * you are required to provide proper attribution to obinary.
7  * If you reproduce or distribute the document without making any substantive modifications to its content,
8  * please use the following attribution line:
9  *
10  * Copyright 1993-2005 obinary Ltd. (http://www.obinary.com) All rights reserved.
11  *
12  */

13 package info.magnolia.commands;
14
15 import info.magnolia.cms.util.AlertUtil;
16
17 import java.util.Collections JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.apache.commons.beanutils.BeanUtils;
21 import org.apache.commons.chain.Command;
22 import org.apache.commons.chain.Context;
23 import org.apache.commons.lang.exception.NestableException;
24 import org.apache.commons.pool.BasePoolableObjectFactory;
25 import org.apache.commons.pool.impl.StackObjectPool;
26
27
28 /**
29  * To make the coding of commands as easy as possible the default values set in the config are set and the values of the
30  * context are set as properties too if the naming matches. To get a better performance we use an inner object pool. The
31  * execution of the command gets a clone from the pool and executes the clone
32  * @author Philipp Bracher
33  * @version $Revision: 6591 $ ($Author: philipp $)
34  */

35 public abstract class MgnlCommand implements Command {
36
37     /**
38      * The default properties. Lazy bound.
39      */

40     private Map JavaDoc defaultProperties;
41
42     private boolean isClone = false;
43
44     /**
45      * Create clones
46      * @author Philipp Bracher
47      * @version $Id: MgnlCommand.java 6591 2006-10-05 15:51:05Z philipp $
48      */

49     class MgnlCommandFactory extends BasePoolableObjectFactory {
50
51         /**
52          * The prototype we clone for faster execution
53          */

54         private MgnlCommand prototype;
55
56         /**
57          * @param prototype
58          */

59         public MgnlCommandFactory(MgnlCommand prototype) {
60             this.prototype = prototype;
61         }
62
63         public Object JavaDoc makeObject() throws Exception JavaDoc {
64             MgnlCommand cmd = (MgnlCommand) BeanUtils.cloneBean(this.prototype);
65             cmd.setClone(true);
66             return cmd;
67         }
68
69         public void activateObject(Object JavaDoc arg0) throws Exception JavaDoc {
70             super.activateObject(arg0);
71             // set default properties
72
BeanUtils.populate(arg0, defaultProperties);
73         }
74
75         public void passivateObject(Object JavaDoc cmd) throws Exception JavaDoc {
76             ((MgnlCommand) cmd).release();
77             super.passivateObject(cmd);
78         }
79
80     }
81
82     /**
83      * Pool of inner commands
84      */

85     private StackObjectPool pool;
86
87     /**
88      * True if we can use object pooling. Else we synchronize the execution.
89      */

90     private boolean pooling = true;
91
92     /**
93      * Make sure that the context is castable to a magnolia context
94      */

95     public boolean execute(Context ctx) throws Exception JavaDoc {
96         if (!(ctx instanceof info.magnolia.context.Context)) {
97             throw new IllegalArgumentException JavaDoc("context must be of type " + info.magnolia.context.Context.class);
98         }
99
100         if (this.defaultProperties == null) {
101             initDefaultProperties();
102         }
103
104         MgnlCommand cmd;
105
106         if (pooling) {
107             // do not instantiate until the pool is really needed
108
// means: do not create a pool for command objects created in the pool itself
109
if (pool == null) {
110                 pool = new StackObjectPool(new MgnlCommandFactory(this));
111             }
112
113             try {
114                 // try to use the pool
115
cmd = (MgnlCommand) pool.borrowObject();
116             }
117             // this happens if the commans constructor is not public: anonymous classes for example
118
catch (InstantiationException JavaDoc e) {
119                 pooling = false;
120                 // start again
121
return execute(ctx);
122             }
123         }
124         else {
125             cmd = this;
126         }
127
128         boolean success = executePooledOrSynchronized(ctx, cmd);
129         // convert the confusing true false behavior to fit commons chain
130
return !success;
131     }
132
133     private boolean executePooledOrSynchronized(Context ctx, MgnlCommand cmd) throws Exception JavaDoc {
134         boolean success = false; // break execution
135

136         // populate the command if we are using a pool
137
if (pooling) {
138             BeanUtils.populate(cmd, ctx);
139             // cast to mgnl context class
140
try {
141                 success = cmd.execute((info.magnolia.context.Context) ctx);
142             }
143             catch (Exception JavaDoc e) {
144                 AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
145                 throw new NestableException("exception during executing command", e);
146             }
147             finally {
148                 pool.returnObject(cmd);
149             }
150         }
151         else {
152             synchronized (cmd) {
153                 BeanUtils.populate(cmd, ctx);
154                 try {
155                     success = cmd.execute((info.magnolia.context.Context) ctx);
156                 }
157                 catch (Exception JavaDoc e) {
158                     AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
159                     throw new NestableException("exception during executing command", e);
160                 }
161                 finally {
162                     if (pooling) {
163                         pool.returnObject(cmd);
164                     }
165                     else {
166                         cmd.release();
167                         BeanUtils.populate(cmd, defaultProperties);
168                     }
169                 }
170             }
171         }
172         return success;
173     }
174
175     private void initDefaultProperties() {
176         try {
177             this.defaultProperties = BeanUtils.describe(this);
178         }
179         catch (Exception JavaDoc e) {
180             this.defaultProperties = Collections.EMPTY_MAP;
181         }
182     }
183
184     public abstract boolean execute(info.magnolia.context.Context context) throws Exception JavaDoc;
185
186     /**
187      * If a clone is passivated we call this method. Please clean up private properties.
188      */

189     public void release() {
190     }
191
192     /**
193      * @return the isClone
194      */

195     protected boolean isClone() {
196         return isClone;
197     }
198
199     /**
200      * @param isClone the isClone to set
201      */

202     protected void setClone(boolean isClone) {
203         this.isClone = isClone;
204     }
205
206 }
207
Popular Tags