This Subversion repository is deprecated; projects are migrated to Git.

As of April 2012, parts of this repository have migrated to Git.

Please see details and status on the following pages:

All contents from this repository will remain available.

All migrated projects (and only migrated projects) will be switched to a read-only mode, and will not be maintained on Subversion any further.

Nothing changes for projects which do not get migrated.

If you would like a particular project to be migrated, please contact gregory dot joseph at magnolia-cms dot com.

/[main]/community/magnolia/trunk/magnolia-module-admininterface/src/main/java/info/magnolia/module/admininterface/commands/ActivationCommand.java

Contents of /community/magnolia/trunk/magnolia-module-admininterface/src/main/java/info/magnolia/module/admininterface/commands/ActivationCommand.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 52496 - (show annotations) (download)
Thu Dec 8 17:04:52 2011 UTC (5 months, 1 week ago) by had
File size: 14141 byte(s)
MAGNOLIA-3904 Use public-private key encryption and resource signing to secure transport instead of using users credentials.
1 /**
2 * This file Copyright (c) 2003-2011 Magnolia International
3 * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4 *
5 *
6 * This file is dual-licensed under both the Magnolia
7 * Network Agreement and the GNU General Public License.
8 * You may elect to use one or the other of these licenses.
9 *
10 * This file is distributed in the hope that it will be
11 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12 * implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14 * Redistribution, except as permitted by whichever of the GPL
15 * or MNA you select, is prohibited.
16 *
17 * 1. For the GPL license (GPL), you can redistribute and/or
18 * modify this file under the terms of the GNU General
19 * Public License, Version 3, as published by the Free Software
20 * Foundation. You should have received a copy of the GNU
21 * General Public License, Version 3 along with this program;
22 * if not, write to the Free Software Foundation, Inc., 51
23 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24 *
25 * 2. For the Magnolia Network Agreement (MNA), this file
26 * and the accompanying materials are made available under the
27 * terms of the MNA which accompanies this distribution, and
28 * is available at http://www.magnolia-cms.com/mna.html
29 *
30 * Any modifications to this file must keep this entire header
31 * intact.
32 *
33 */
34 package info.magnolia.module.admininterface.commands;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.exchange.ExchangeException;
38 import info.magnolia.cms.i18n.MessagesManager;
39 import info.magnolia.cms.util.AlertUtil;
40 import info.magnolia.context.Context;
41
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.Comparator;
46 import java.util.List;
47 import java.util.Map;
48
49 import javax.jcr.Node;
50 import javax.jcr.NodeIterator;
51 import javax.jcr.RepositoryException;
52
53 import org.apache.commons.lang.StringUtils;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57
58 /**
59 * the activation command which do real activation
60 * @author jackie
61 * $Id$
62 */
63 public class ActivationCommand extends BaseActivationCommand {
64
65 /**
66 * Log
67 */
68 private static Logger log = LoggerFactory.getLogger(ActivationCommand.class);
69
70 private boolean recursive;
71
72 private String versionNumber;
73
74 private List versionMap;
75
76 /**
77 * Execute activation
78 */
79 @Override
80 public boolean execute(Context ctx) {
81 boolean success = false;
82 try {
83 log.debug("Will activate content from {} repository with uuid {} and path {}", new Object[] {getRepository(), getUuid(), getPath()});
84 final Content originalState = getNode(ctx);
85 Content thisState = originalState;
86 if (!recursive) {
87 if (StringUtils.isNotEmpty(getVersion())) {
88 try {
89 thisState = thisState.getVersionedContent(getVersion());
90 } catch (RepositoryException re) {
91 log.error("Failed to get version "+getVersion()+" for "+thisState.getHandle(), re);
92 }
93 }
94 success = activateUpdate(ctx, originalState);
95 } else {
96 success = activateBulkUpdate(ctx, getNode(ctx));
97 }
98 }
99 catch (Exception e) {
100 log.error("can't activate", e);
101 AlertUtil.setException(MessagesManager.get("tree.error.activate"), e, ctx);
102 }
103 return success;
104 }
105
106 private boolean activateUpdate(Context ctx, Content thisState) throws ExchangeException, RepositoryException {
107 boolean success;
108 String parentPath = StringUtils.substringBeforeLast(thisState.getHandle(), "/");
109 if (StringUtils.isEmpty(parentPath)) {
110 parentPath = "/";
111 }
112 log.debug("Activate content {} as a child of {}", new Object[] {thisState.getName(), parentPath});
113 // make multiple activations instead of a big bulk
114 List orderInfo = getOrderingInfo(thisState);
115 if (StringUtils.isNotEmpty(getVersion())) {
116 try {
117 thisState = thisState.getVersionedContent(getVersion());
118 } catch (RepositoryException re) {
119 // TODO: is this correct? should not we fail completely rather then silently ignore versions?
120 log.error("Failed to get version "+getVersion()+" for "+thisState.getHandle() + ". Activating current content instead.", re);
121 }
122 }
123 getSyndicator().activate(parentPath, thisState, orderInfo);
124 log.debug("exec successfully.");
125 success = true;
126 return success;
127 }
128
129 private boolean activateBulkUpdate(Context ctx, Content thisState) throws ExchangeException, RepositoryException {
130 boolean success;
131 // make multiple activations instead of a big bulk
132 List versionMap = getVersionMap();
133 if (versionMap == null) {
134 String parentPath = StringUtils.substringBeforeLast(thisState.getHandle(), "/");
135 if (StringUtils.isEmpty(parentPath)) {
136 parentPath = "/";
137 }
138 log.debug("Activate content {} as a child of {}", new Object[] {thisState.getName(), parentPath});
139 activateRecursive(parentPath, thisState, ctx);
140 } else {
141 activateRecursive(ctx, versionMap);
142 }
143 log.debug("exec successfully.");
144 success = true;
145 return success;
146 }
147
148 /**
149 * Activate recursively. This is done one by one to send only small peaces (memory friendly).
150 * @param parentPath
151 * @param node
152 * @throws ExchangeException
153 * @throws RepositoryException
154 */
155 protected void activateRecursive(String parentPath, Content node, Context ctx)
156 throws ExchangeException, RepositoryException {
157
158 getSyndicator().activate(parentPath, node, getOrderingInfo(node));
159
160 Collection children = node.getChildren(new Content.ContentFilter() {
161 @Override
162 public boolean accept(Content content) {
163 try {
164 return !getRule().isAllowed(content.getNodeTypeName());
165 }
166 catch (RepositoryException e) {
167 log.error("can't get nodetype", e);
168 return false;
169 }
170 }
171 });
172
173 // FYI: need to reverse order of child activation since content ordering info is also bottom-up
174 // Hackish at best. If changing this, don't forget to also change other activateRecursive() method
175 // and most importantly ensure that ordering of siblings in ReceiveFilter is done in same direction!
176 Content[] childArray = (Content[]) children.toArray(new Content[children.size()]);
177 for (int i = childArray.length - 1; i >=0; i--) {
178 this.activateRecursive(node.getHandle(), childArray[i], ctx);
179 }
180 }
181
182 /**
183 * @param ctx
184 * @param versionMap
185 * */
186 protected void activateRecursive(Context ctx, List versionMap)
187 throws ExchangeException, RepositoryException {
188 // activate all uuid's present in versionMap
189 Map<String, Object>[] versions = (Map<String, Object>[]) versionMap.toArray(new Map[0]);
190 // add path and order info into the entries
191 for (int i = 0; i < versions.length; i++) {
192 Map<String, Object> entry = versions[i];
193 String uuid = (String) entry.get("uuid");
194 if (StringUtils.equalsIgnoreCase("class", uuid)) {
195 // TODO: this should not happen in between the serialized list, somewhere a bug
196 // for the moment simply ignore it
197 versionMap.remove(entry);
198 }
199 try {
200 Content content = ctx.getHierarchyManager(getRepository()).getContentByUUID(uuid);
201 entry.put("handle", content.getHandle());
202 entry.put("index", i);
203 } catch (RepositoryException re) {
204 log.error("Failed to activate node with UUID : "+uuid);
205 log.error(re.getMessage());
206 versionMap.remove(entry);
207 }
208 }
209 versions = null;
210
211 // versionMap is a flat list of all activated content. We need to ensure that the content is ordered from top down and siblings are activated from bottom up
212 Collections.sort((List<Map<String, Object>>) versionMap, new Comparator<Map<String, Object>>() {
213
214 @Override
215 public int compare(Map<String, Object> o1, Map<String, Object> o2) {
216 String handle1 = (String) o1.get("handle");
217 String handle2 = (String) o2.get("handle");
218 if (handle2.startsWith(handle1)) {
219 // o2 is child of o1, say o1 is smaller to get it ordered BEFORE o2
220 return -1;
221 }
222 String parent1 = StringUtils.substringBeforeLast(handle1, "/");
223 String parent2 = StringUtils.substringBeforeLast(handle2, "/");
224 if (parent1.equals(parent2)) {
225 // siblings ... to reverse order, the higher index value get ordered before lower values index
226 int idx1 = (Integer) o1.get("index");
227 int idx2 = (Integer) o2.get("index");
228 // index is generated in the loop above and can be never same for 2 items ... skip equality case
229 return idx1 < idx2 ? 1 : -1;
230 }
231
232 // unrelated entries, the one closer to the root should be returned first
233 int dirLevels1 = StringUtils.countMatches(handle1, "/");
234 int dirLevels2 = StringUtils.countMatches(handle2, "/");
235 // since parents are checked above, the equality case here means different hierarchy of same depth and is irrelevant to activation order
236 return dirLevels1 < dirLevels2 ? -1 : 1;
237 }});
238
239 // FYI: need to reverse order of child activation since content ordering info is also bottom-up
240 // Hackish at best. If changing this, don't forget to also change other activateRecursive() method
241 // and most importantly ensure that ordering of siblings in ReceiveFilter is done in same direction!
242 for (Map entry : (List<Map>) versionMap) {
243
244 String uuid = (String) entry.get("uuid");
245 String versionNumber = (String) entry.get("version");
246 if (StringUtils.equalsIgnoreCase("class", uuid)) {
247 // TODO: this should not happen in between the serialized list, somewhere a bug
248 // for the moment simply ignore it
249 continue;
250 }
251 try {
252 Content content = ctx.getHierarchyManager(getRepository()).getContentByUUID(uuid);
253 // NOTE : on activation of the version use current hierarchy to order
254 // since versioning operation does not preserve order anywhere
255 List orderedList = getOrderingInfo(content);
256 String parentPath = content.getParent().getHandle();
257 content = content.getVersionedContent(versionNumber);
258 // add order info for the first node as it represents the parent in a tree
259 getSyndicator().activate(parentPath, content, orderedList);
260 } catch (RepositoryException re) {
261 log.error("Failed to activate node with UUID : "+uuid);
262 log.error(re.getMessage());
263 }
264 }
265 }
266
267 /**
268 * collect node UUID of the siblings in the exact order as it should be written on
269 * subscribers
270 * @param node
271 * */
272 protected List getOrderingInfo(Content node) {
273 //do not use magnolia Content class since these objects are only meant for a single use to read UUID
274 // TODO: what's wrong with using magnolia content???
275 List siblings = new ArrayList();
276 Node thisNode = node.getJCRNode();
277 try {
278 String thisNodeType = node.getNodeTypeName();
279 String thisNodeUUID = node.getUUID();
280 NodeIterator nodeIterator = thisNode.getParent().getNodes();
281 while (nodeIterator.hasNext()) { // only collect elements after this node
282 Node sibling = nodeIterator.nextNode();
283 // skip till the actual position
284 if (sibling.isNodeType(thisNodeType)) {
285 if (thisNodeUUID.equalsIgnoreCase(sibling.getUUID())) {
286 break;
287 }
288 }
289 }
290 while (nodeIterator.hasNext()) {
291 Node sibling = nodeIterator.nextNode();
292 if (sibling.isNodeType(thisNodeType)) {
293 siblings.add(sibling.getUUID());
294 }
295 }
296 } catch (RepositoryException re) {
297 // do not throw this exception, if it fails simply do not add any ordering info
298 log.error("Failed to get Ordering info", re);
299 }
300 return siblings;
301 }
302
303 /**
304 * @return the recursive
305 */
306 public boolean isRecursive() {
307 return recursive;
308 }
309
310 /**
311 * @param recursive the recursive to set
312 */
313 public void setRecursive(boolean recursive) {
314 this.recursive = recursive;
315 }
316
317 /**
318 * @param number version number to be set for activation
319 * */
320 public void setVersion(String number) {
321 this.versionNumber = number;
322 }
323
324 /**
325 * @return version number
326 * */
327 public String getVersion() {
328 return this.versionNumber;
329 }
330
331 /**
332 * @param versionMap version map to be set for activation
333 * */
334 public void setVersionMap(List versionMap) {
335 this.versionMap = versionMap;
336 }
337
338 /**
339 * @return version map
340 * */
341 public List getVersionMap() {
342 return this.versionMap;
343 }
344
345 @Override
346 public void release() {
347 super.release();
348 this.versionMap = null;
349 this.recursive = false;
350 this.versionNumber = null;
351 }
352
353 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision Author

Please contact the developer's list in case of issues or questions.

ViewVC Help
Powered by ViewVC 1.1.13