View Javadoc
1   /**
2    * This file Copyright (c) 2003-2015 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.commands.impl;
35  
36  import info.magnolia.cms.core.version.VersionManager;
37  import info.magnolia.cms.util.ExclusiveWrite;
38  import info.magnolia.context.Context;
39  import info.magnolia.jcr.util.NodeTypes;
40  import info.magnolia.jcr.util.PropertyUtil;
41  import info.magnolia.objectfactory.Components;
42  
43  import java.util.ArrayList;
44  import java.util.HashMap;
45  import java.util.List;
46  import java.util.Map;
47  
48  import javax.inject.Inject;
49  import javax.jcr.Node;
50  import javax.jcr.NodeIterator;
51  import javax.jcr.RepositoryException;
52  import javax.jcr.version.Version;
53  
54  import org.apache.commons.lang3.StringUtils;
55  
56  /**
57   * Creates a version for the passed path in the website repository.
58   */
59  public class VersionCommand extends RuleBasedCommand {
60  
61      private boolean recursive;
62      private String comment;
63      private String userName;
64  
65      private final VersionManager versionManager;
66  
67      @Inject
68      public VersionCommand(final VersionManager versionManager) {
69          this.versionManager = versionManager;
70      }
71  
72      /**
73       * @deprecated since 5.4.4, use {@link #VersionCommand(VersionManager)}.
74       */
75      @Deprecated
76      public VersionCommand() {
77          this.versionManager = Components.getComponent(VersionManager.class);
78      }
79  
80      /**
81       * @see info.magnolia.commands.MgnlCommand#execute(info.magnolia.context.Context)
82       */
83      @Override
84      public boolean execute(Context ctx) throws Exception {
85          final Node node = getJCRNode(ctx);
86          if (isRecursive()) {
87              // set versionMap and version name for this node
88              List versionMap = new ArrayList();
89              versionRecursively(node, ctx, versionMap);
90              ctx.setAttribute(Context.ATTRIBUTE_VERSION_MAP, versionMap, Context.LOCAL_SCOPE);
91          } else {
92              addComment(node);
93              Version version;
94              if (StringUtils.isEmpty(getUserName())) {
95                  version = versionManager.addVersion(node, getRule());
96              } else {
97                  version = versionManager.addVersion(node, getRule(), getUserName());
98              }
99  
100             if (version != null) {
101                 ctx.setAttribute(Context.ATTRIBUTE_VERSION, version.getName(), Context.LOCAL_SCOPE);
102             }
103             cleanComment(node);
104         }
105 
106         return true;
107     }
108 
109     protected void addComment(final Node node) throws RepositoryException {
110         synchronized (ExclusiveWrite.getInstance()) {
111             PropertyUtil.setProperty(node, NodeTypes.Versionable.COMMENT, getComment() != null ? getComment() : "");
112             node.getSession().save();
113         }
114     }
115 
116     protected void cleanComment(final Node node) throws RepositoryException {
117         synchronized (ExclusiveWrite.getInstance()) {
118             if (node.hasProperty(NodeTypes.Versionable.COMMENT)
119                     && !StringUtils.EMPTY.equals(node.getProperty(NodeTypes.Versionable.COMMENT).getString())) {
120                 node.getProperty(NodeTypes.Versionable.COMMENT).remove();
121                 node.getSession().save();
122             }
123         }
124     }
125 
126     /**
127      * Recursive version the descendant nodes in the tree. Uses the reversed {@link #rule} to filter the nodes meant to be versioned.
128      * {@link info.magnolia.cms.util.Rule#isAllowed} is used to composite the child nodes into one version - node types defined in the
129      * {@link info.magnolia.cms.util.Rule#allowedTypes} will not be versioned.
130      *
131      * @param versionMap keeps tack of the versioned nodes and gets passed to the context.
132      */
133     private void versionRecursively(Node node, Context ctx, List versionMap) throws RepositoryException {
134         addComment(node);
135         Version version;
136         if (StringUtils.isEmpty(getUserName())) {
137             version = versionManager.addVersion(node, getRule());
138         } else {
139             version = versionManager.addVersion(node, getRule(), getUserName());
140         }
141 
142         Map entry = new HashMap();
143         entry.put("uuid", node.getIdentifier());
144         if (version != null) {
145             entry.put("version", version.getName());
146             if (StringUtils.isEmpty((String) ctx.getAttribute(Context.ATTRIBUTE_VERSION))) {
147                 ctx.setAttribute(Context.ATTRIBUTE_VERSION, version.getName(), Context.LOCAL_SCOPE);
148             }
149         }
150         versionMap.add(entry);
151 
152         cleanComment(node);
153 
154         NodeIterator children = node.getNodes();
155         while (children.hasNext()) {
156             Node child = children.nextNode();
157             if (!getRule().isAllowed(child)) {
158                 versionRecursively(child, ctx, versionMap);
159             }
160         }
161     }
162 
163     /**
164      * @return is recursive versioning
165      */
166     public boolean isRecursive() {
167         return recursive;
168     }
169 
170     public void setRecursive(boolean recursive) {
171         this.recursive = recursive;
172     }
173 
174     public String getComment() {
175         return comment;
176     }
177 
178     public void setComment(String comment) {
179         this.comment = comment;
180     }
181 
182     @Override
183     public void release() {
184         super.release();
185         this.recursive = false;
186         this.userName = null;
187     }
188 
189     public String getUserName() {
190         return userName;
191     }
192 
193     public void setUserName(final String userName) {
194         this.userName = userName;
195     }
196 }