1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.commands;
35
36 import info.magnolia.cms.util.AlertUtil;
37
38 import java.util.Collections;
39 import java.util.Map;
40
41 import org.apache.commons.beanutils.BeanUtils;
42 import org.apache.commons.beanutils.PropertyUtils;
43 import org.apache.commons.chain.Command;
44 import org.apache.commons.chain.Context;
45 import org.apache.commons.lang.exception.NestableException;
46 import org.apache.commons.pool.BasePoolableObjectFactory;
47 import org.apache.commons.pool.impl.StackObjectPool;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51
52
53
54
55
56
57
58
59 public abstract class MgnlCommand implements Command {
60
61
62
63
64 public static Logger log = LoggerFactory.getLogger(MgnlCommand.class);
65
66
67
68
69
70 private Map defaultProperties;
71
72 private boolean isClone = false;
73
74 private boolean isEnabled = true;
75
76
77
78
79
80
81 class MgnlCommandFactory extends BasePoolableObjectFactory {
82
83
84
85
86 private MgnlCommand prototype;
87
88
89
90
91 public MgnlCommandFactory(MgnlCommand prototype) {
92 this.prototype = prototype;
93 }
94
95 public Object makeObject() throws Exception {
96 MgnlCommand cmd = (MgnlCommand) BeanUtils.cloneBean(this.prototype);
97 cmd.setClone(true);
98 return cmd;
99 }
100
101 public void activateObject(Object arg0) throws Exception {
102 super.activateObject(arg0);
103
104 BeanUtils.populate(arg0, defaultProperties);
105 }
106
107 public void passivateObject(Object cmd) throws Exception {
108 ((MgnlCommand) cmd).release();
109 super.passivateObject(cmd);
110 }
111
112 }
113
114
115
116
117 private StackObjectPool pool;
118
119
120
121
122 private boolean pooling = true;
123
124
125
126
127 public boolean execute(Context ctx) throws Exception {
128 if (!(ctx instanceof info.magnolia.context.Context)) {
129 throw new IllegalArgumentException("context must be of type " + info.magnolia.context.Context.class);
130 }
131
132 if (this.defaultProperties == null) {
133 initDefaultProperties();
134 }
135
136 MgnlCommand cmd;
137
138 if (pooling) {
139
140
141 if (pool == null) {
142 pool = new StackObjectPool(new MgnlCommandFactory(this));
143 }
144
145 try {
146
147 cmd = (MgnlCommand) pool.borrowObject();
148 }
149
150 catch (Throwable t) {
151 pooling = false;
152
153 return execute(ctx);
154 }
155 }
156 else {
157 cmd = this;
158 }
159
160 boolean success = executePooledOrSynchronized(ctx, cmd);
161
162 return !success;
163 }
164
165 private boolean executePooledOrSynchronized(Context ctx, MgnlCommand cmd) throws Exception {
166 boolean success = false;
167
168
169 if (pooling) {
170 BeanUtils.populate(cmd, ctx);
171
172 try {
173 success = cmd.execute((info.magnolia.context.Context) ctx);
174 }
175 catch (Exception e) {
176 AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
177 throw new NestableException("exception during executing command", e);
178 }
179 finally {
180 pool.returnObject(cmd);
181 }
182 }
183 else {
184 synchronized (cmd) {
185 BeanUtils.populate(cmd, ctx);
186 try {
187 success = cmd.execute((info.magnolia.context.Context) ctx);
188 }
189 catch (Exception e) {
190 AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
191 throw new NestableException("exception during executing command", e);
192 }
193 finally {
194 if (pooling) {
195 pool.returnObject(cmd);
196 }
197 else {
198 cmd.release();
199 BeanUtils.populate(cmd, defaultProperties);
200 }
201 }
202 }
203 }
204 return success;
205 }
206
207 private void initDefaultProperties() {
208 try {
209 this.defaultProperties = PropertyUtils.describe(this);
210 }
211 catch (Exception e) {
212 this.defaultProperties = Collections.EMPTY_MAP;
213 }
214 }
215
216 public abstract boolean execute(info.magnolia.context.Context context) throws Exception;
217
218
219
220
221 public void release() {
222 }
223
224
225
226
227 protected boolean isClone() {
228 return isClone;
229 }
230
231
232
233
234 protected void setClone(boolean isClone) {
235 this.isClone = isClone;
236 }
237
238
239 public boolean isEnabled() {
240 return this.isEnabled;
241 }
242
243
244 public void setEnabled(boolean isEnabled) {
245 this.isEnabled = isEnabled;
246 }
247
248 }