View Javadoc
1   /**
2    * This file Copyright (c) 2011-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.jcr.util;
35  
36  import info.magnolia.cms.core.version.ContentVersion;
37  import info.magnolia.cms.core.version.VersionInfo;
38  import info.magnolia.cms.core.version.VersionManager;
39  import info.magnolia.cms.core.version.VersionedNode;
40  import info.magnolia.cms.util.ContentUtil;
41  import info.magnolia.jcr.decoration.ContentDecoratorVersionWrapper;
42  import info.magnolia.jcr.wrapper.JCRPropertiesFilteringNodeWrapper;
43  import info.magnolia.objectfactory.Components;
44  import info.magnolia.repository.RepositoryConstants;
45  import info.magnolia.repository.RepositoryManager;
46  
47  import java.util.ArrayList;
48  import java.util.Collections;
49  import java.util.List;
50  
51  import javax.jcr.Node;
52  import javax.jcr.RepositoryException;
53  import javax.jcr.UnsupportedRepositoryOperationException;
54  import javax.jcr.version.Version;
55  import javax.jcr.version.VersionException;
56  import javax.jcr.version.VersionHistory;
57  import javax.jcr.version.VersionIterator;
58  
59  import org.apache.commons.lang3.StringUtils;
60  import org.apache.jackrabbit.JcrConstants;
61  import org.slf4j.Logger;
62  import org.slf4j.LoggerFactory;
63  
64  /**
65   * Various utility methods useful for JCR-Versioning.
66   */
67  public class VersionUtil {
68  
69      private static final Logger log = LoggerFactory.getLogger(VersionUtil.class);
70  
71      /**
72       * Return the NodeType-name for the provided Node. It it's a JCPropertiesFilteringNodeWrapper the unwrapped node will be used for retrieving the property from.
73       * As it's about versioning, the frozen primary type if existing (else primary type) will be returned.
74       */
75      public static String getNodeTypeName(Node node) throws RepositoryException {
76          node = NodeUtil.deepUnwrap(node, JCRPropertiesFilteringNodeWrapper.class);
77  
78          if (node.hasProperty(JcrConstants.JCR_FROZENPRIMARYTYPE)) {
79              return node.getProperty(JcrConstants.JCR_FROZENPRIMARYTYPE).getString();
80          }
81          return node.getProperty(JcrConstants.JCR_PRIMARYTYPE).getString();
82      }
83  
84      /**
85       * Returns version history of a content as a List of {@link info.magnolia.cms.core.version.VersionInfo}s.
86       *
87       * @param node Node
88       * @return list of version info
89       * @see info.magnolia.cms.core.version.VersionInfo
90       */
91      public static List<VersionInfo> getVersionInfoList(Node node) {
92          List<VersionInfo> versionList = new ArrayList<VersionInfo>();
93          VersionManager versionManager = Components.getComponent(VersionManager.class);
94  
95          try {
96              VersionHistory versionHistory = versionManager.getVersionHistory(node);
97  
98              if (versionHistory != null) {
99                  VersionIterator versionIterator = versionHistory.getAllVersions();
100                 while (versionIterator.hasNext()) {
101                     final Version version = versionIterator.nextVersion();
102                     final String versionName = version.getName();
103 
104                     // We do not want to read the version user from system root node
105                     if (StringUtils.isNotBlank(versionName) && !StringUtils.equals(versionName, "jcr:rootVersion")) {
106                         final String versionComment = NodeTypes.Versionable.getComment(version.getFrozenNode());
107                         final ContentVersion contentVersion = new ContentVersion(version, ContentUtil.asContent(node));
108                         final String versionUser = contentVersion.getUserName();
109 
110                         versionList.add(new VersionInfo(versionName, version.getCreated().getTime(), versionUser, versionComment));
111                     }
112                 }
113             }
114         } catch (RepositoryException e) {
115             log.warn("Unable to get version history of node [{}].", new Object[]{node, e});
116         }
117 
118         Collections.reverse(versionList);
119 
120         return versionList;
121     }
122 
123     /**
124      * Returns the version object of a labelled version.
125      *
126      * @return version object or null if the requested version doesn't exist.
127      */
128     public static Version getVersion(Node node, String versionLabel) throws RepositoryException {
129         if (StringUtils.isEmpty(versionLabel)) {
130             return null;
131         }
132 
133         VersionManager versionManager = Components.getComponent(VersionManager.class);
134 
135         try {
136             VersionHistory versionHistory = versionManager.getVersionHistory(node);
137             if (versionHistory == null) {
138                 return null;
139             }
140             return versionHistory.getVersion(versionLabel);
141         } catch (VersionException e) {
142             log.warn("The version '{}' of the node '{}' doesn't exists.", versionLabel, node, e);
143             return null;
144         } catch (UnsupportedRepositoryOperationException e) {
145             return null;
146         }
147     }
148 
149     /**
150      * @return the label of the first predecessor version or null if no previous version exists.
151      */
152     public static String getPreviousVersionLabel(Node node, String versionLabel) throws RepositoryException {
153         if (node == null) {
154             return null;
155         }
156         Version previousVersion = getPreviousVersion(getVersion(node, versionLabel));
157         if (previousVersion != null) {
158             return previousVersion.getName();
159         }
160         return null;
161     }
162 
163     /**
164      * Checks if a version label of a {@link Node} has a previous version.
165      */
166     public static boolean hasPreviousVersion(Node node, String versionLabel) {
167         Version previousVersion;
168         String previousVersionName;
169 
170         try {
171             previousVersion = getPreviousVersion(getVersion(node, versionLabel));
172             previousVersionName = previousVersion.getName();
173         } catch (RepositoryException e) {
174             return false;
175         }
176 
177         return !StringUtils.equals(previousVersionName, "jcr:rootVersion");
178     }
179 
180     /**
181      * @return Latest version or null if not found.
182      */
183     public static Version getLatestVersion(Node node) throws RepositoryException {
184         VersionManager versionManager = Components.getComponent(VersionManager.class);
185         VersionIterator versionIterator = versionManager.getAllVersions(node);
186 
187         Version latest = null;
188         // Check.
189         if (versionIterator == null) {
190             return latest;
191         }
192         // Get last Version.
193         while (versionIterator.hasNext()) {
194             latest = versionIterator.nextVersion();
195         }
196         return latest;
197     }
198 
199     /**
200      * @return the first predecessor or null if no previous version exists.
201      */
202     public static Version getPreviousVersion(Version version) throws RepositoryException {
203         if (version == null) {
204             return null;
205         }
206         Version[] predecessors = version.getPredecessors();
207         if (predecessors.length > 0) {
208             return predecessors[0];
209         }
210         return null;
211     }
212 
213     /**
214      * @return the label of the next successor version or null if no next version exists.
215      */
216     public static String getNextVersionLabel(Node node, String versionLabel) throws RepositoryException {
217         if (node == null) {
218             return null;
219         }
220         Version nextVersion = getNextVersion(getVersion(node, versionLabel));
221         if (nextVersion != null) {
222             return nextVersion.getName();
223         }
224         return null;
225     }
226 
227     /**
228      * @return the first successor or null if no next version exists.
229      */
230     public static Version getNextVersion(Version version) throws RepositoryException {
231         if (version == null) {
232             return null;
233         }
234         Version[] successors = version.getSuccessors();
235         if (successors.length > 0) {
236             return successors[0];
237         }
238         return null;
239     }
240 
241     /**
242      * Get version store session.
243      */
244     public static String getVersionWorkspaceForNode(RepositoryManager repositoryManager, Node node) throws RepositoryException {
245         String workspaceName = node.getSession().getWorkspace().getName();
246         String repositoryId = repositoryManager.getRepositoryNameForWorkspace(workspaceName);
247         return repositoryId + "-" + RepositoryConstants.VERSION_STORE;
248     }
249 
250     public static Version unwrap(Version version) throws RepositoryException {
251         Version unwrappedVersion = version;
252         if (unwrappedVersion instanceof VersionedNode) {
253             unwrappedVersion = ((VersionedNode) version).unwrap();
254         }
255         while (unwrappedVersion instanceof ContentDecoratorVersionWrapper) {
256             unwrappedVersion = ((ContentDecoratorVersionWrapper) unwrappedVersion).getWrappedVersion();
257         }
258         return unwrappedVersion;
259     }
260 
261 }