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 public static Logger log = LoggerFactory.getLogger(MgnlCommand.class);
62
63
64
65
66 private Map defaultProperties;
67
68 private boolean isClone = false;
69
70 private boolean isEnabled = true;
71
72
73
74
75
76
77 class MgnlCommandFactory extends BasePoolableObjectFactory {
78
79
80
81
82 private MgnlCommand prototype;
83
84
85
86
87 public MgnlCommandFactory(MgnlCommand prototype) {
88 this.prototype = prototype;
89 }
90
91 @Override
92 public Object makeObject() throws Exception {
93 MgnlCommand cmd = (MgnlCommand) BeanUtils.cloneBean(this.prototype);
94 cmd.setClone(true);
95 return cmd;
96 }
97
98 @Override
99 public void activateObject(Object arg0) throws Exception {
100 super.activateObject(arg0);
101
102 BeanUtils.populate(arg0, defaultProperties);
103 }
104
105 @Override
106 public void passivateObject(Object cmd) throws Exception {
107 ((MgnlCommand) cmd).release();
108 super.passivateObject(cmd);
109 }
110
111 }
112
113
114
115
116 private StackObjectPool pool;
117
118
119
120
121 private boolean pooling = true;
122
123
124
125
126
127 @Override
128 public boolean execute(Context ctx) throws Exception {
129 if (!(ctx instanceof info.magnolia.context.Context)) {
130 throw new IllegalArgumentException("context must be of type " + info.magnolia.context.Context.class);
131 }
132
133 if (this.defaultProperties == null) {
134 initDefaultProperties();
135 }
136
137 MgnlCommand cmd;
138
139 if (pooling) {
140
141
142 if (pool == null) {
143 pool = new StackObjectPool(new MgnlCommandFactory(this));
144 }
145
146 try {
147
148 cmd = (MgnlCommand) pool.borrowObject();
149 }
150
151 catch (Throwable t) {
152 pooling = false;
153
154 return execute(ctx);
155 }
156 }
157 else {
158 cmd = this;
159 }
160
161 boolean success = executePooledOrSynchronized(ctx, cmd);
162
163 return !success;
164 }
165
166 private boolean executePooledOrSynchronized(Context ctx, MgnlCommand cmd) throws Exception {
167 boolean success = false;
168
169
170 if (pooling) {
171 BeanUtils.populate(cmd, ctx);
172
173 try {
174 success = cmd.execute((info.magnolia.context.Context) ctx);
175 }
176 catch (Exception e) {
177 AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
178 throw new NestableException("exception during executing command", e);
179 }
180 finally {
181 pool.returnObject(cmd);
182 }
183 }
184 else {
185 synchronized (cmd) {
186 BeanUtils.populate(cmd, ctx);
187 try {
188 success = cmd.execute((info.magnolia.context.Context) ctx);
189 }
190 catch (Exception e) {
191 AlertUtil.setException(e, (info.magnolia.context.Context) ctx);
192 throw new NestableException("exception during executing command", e);
193 }
194 finally {
195 if (pooling) {
196 pool.returnObject(cmd);
197 }
198 else {
199 cmd.release();
200 BeanUtils.populate(cmd, defaultProperties);
201 }
202 }
203 }
204 }
205 return success;
206 }
207
208 private void initDefaultProperties() {
209 try {
210 this.defaultProperties = PropertyUtils.describe(this);
211 } catch (Exception e) {
212 if (log.isDebugEnabled()) {
213 log.warn("Failed to persist "+ this.getClass().getName()+" command properties due to "+ e.getMessage()+". Please review your configuration.", e);
214 } else {
215 log.warn("Failed to persist {} command properties due to {}. Please review your configuration.", this.getClass().getName(), e.getMessage());
216 }
217 this.defaultProperties = Collections.EMPTY_MAP;
218 }
219 }
220
221 public abstract boolean execute(info.magnolia.context.Context context) throws Exception;
222
223
224
225
226 public void release() {
227 }
228
229
230
231
232 protected boolean isClone() {
233 return isClone;
234 }
235
236
237
238
239 protected void setClone(boolean isClone) {
240 this.isClone = isClone;
241 }
242
243
244 public boolean isEnabled() {
245 return this.isEnabled;
246 }
247
248
249 public void setEnabled(boolean isEnabled) {
250 this.isEnabled = isEnabled;
251 }
252
253 }