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