]> git.argeo.org Git - lgpl/argeo-commons.git/blob - jackrabbit/JackrabbitDataModelMigration.java
Prepare next development cycle
[lgpl/argeo-commons.git] / jackrabbit / JackrabbitDataModelMigration.java
1 package org.argeo.jackrabbit;
2
3 import java.io.InputStreamReader;
4 import java.io.Reader;
5
6 import javax.jcr.Node;
7 import javax.jcr.Session;
8
9 import org.apache.commons.io.IOUtils;
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.apache.jackrabbit.commons.cnd.CndImporter;
13 import org.apache.jackrabbit.core.config.RepositoryConfig;
14 import org.argeo.ArgeoException;
15 import org.argeo.jcr.ArgeoNames;
16 import org.argeo.jcr.JcrCallback;
17 import org.argeo.jcr.JcrUtils;
18 import org.springframework.core.io.Resource;
19
20 /** Migrate the data in a Jackrabbit repository. */
21 public class JackrabbitDataModelMigration implements
22 Comparable<JackrabbitDataModelMigration> {
23 private final static Log log = LogFactory
24 .getLog(JackrabbitDataModelMigration.class);
25
26 private String dataModelNodePath;
27 private String targetVersion;
28 private Resource migrationCnd;
29 private JcrCallback dataModification;
30
31 /**
32 * Expects an already started repository with the old data model to migrate.
33 * Expects to be run with admin rights (Repository.login() will be used).
34 *
35 * @return true if a migration was performed and the repository needs to be
36 * restarted and its caches cleared.
37 */
38 public Boolean migrate(Session session) {
39 long begin = System.currentTimeMillis();
40 Reader reader = null;
41 try {
42 // check if already migrated
43 if (!session.itemExists(dataModelNodePath)) {
44 log.warn("Node " + dataModelNodePath
45 + " does not exist: nothing to migrate.");
46 return false;
47 }
48 Node dataModelNode = session.getNode(dataModelNodePath);
49 if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) {
50 String currentVersion = dataModelNode.getProperty(
51 ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
52 if (compareVersions(currentVersion, targetVersion) >= 0) {
53 log.info("Data model at version " + currentVersion
54 + ", no need to migrate.");
55 return false;
56 }
57 }
58
59 // apply transitional CND
60 if (migrationCnd != null) {
61 reader = new InputStreamReader(migrationCnd.getInputStream());
62 CndImporter.registerNodeTypes(reader, session, true);
63 session.save();
64 log.info("Registered migration node types from " + migrationCnd);
65 }
66
67 // modify data
68 dataModification.execute(session);
69
70 // apply changes
71 session.save();
72
73 long duration = System.currentTimeMillis() - begin;
74 log.info("Migration of data model " + dataModelNodePath + " to "
75 + targetVersion + " performed in " + duration + "ms");
76 return true;
77 } catch (Exception e) {
78 JcrUtils.discardQuietly(session);
79 throw new ArgeoException("Migration of data model "
80 + dataModelNodePath + " to " + targetVersion + " failed.",
81 e);
82 } finally {
83 JcrUtils.logoutQuietly(session);
84 IOUtils.closeQuietly(reader);
85 }
86 }
87
88 protected static int compareVersions(String version1, String version2) {
89 // TODO do a proper version analysis and comparison
90 return version1.compareTo(version2);
91 }
92
93 /** To be called on a stopped repository. */
94 public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) {
95 try {
96 String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml";
97 repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
98 if (log.isDebugEnabled())
99 log.debug("Cleared " + customeNodeTypesPath);
100 } catch (Exception e) {
101 throw new ArgeoException("Cannot clear caches", e);
102 }
103
104 // File customNodeTypes = new File(home.getPath()
105 // + "/repository/nodetypes/custom_nodetypes.xml");
106 // if (customNodeTypes.exists()) {
107 // customNodeTypes.delete();
108 // if (log.isDebugEnabled())
109 // log.debug("Cleared " + customNodeTypes);
110 // } else {
111 // log.warn("File " + customNodeTypes + " not found.");
112 // }
113 }
114
115 /*
116 * FOR USE IN (SORTED) SETS
117 */
118
119 public int compareTo(JackrabbitDataModelMigration dataModelMigration) {
120 // TODO make ordering smarter
121 if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath))
122 return compareVersions(targetVersion,
123 dataModelMigration.targetVersion);
124 else
125 return dataModelNodePath
126 .compareTo(dataModelMigration.dataModelNodePath);
127 }
128
129 @Override
130 public boolean equals(Object obj) {
131 if (!(obj instanceof JackrabbitDataModelMigration))
132 return false;
133 JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj;
134 return dataModelNodePath.equals(dataModelMigration.dataModelNodePath)
135 && targetVersion.equals(dataModelMigration.targetVersion);
136 }
137
138 @Override
139 public int hashCode() {
140 return targetVersion.hashCode();
141 }
142
143 public void setDataModelNodePath(String dataModelNodePath) {
144 this.dataModelNodePath = dataModelNodePath;
145 }
146
147 public void setTargetVersion(String targetVersion) {
148 this.targetVersion = targetVersion;
149 }
150
151 public void setMigrationCnd(Resource migrationCnd) {
152 this.migrationCnd = migrationCnd;
153 }
154
155 public void setDataModification(JcrCallback dataModification) {
156 this.dataModification = dataModification;
157 }
158
159 public String getDataModelNodePath() {
160 return dataModelNodePath;
161 }
162
163 public String getTargetVersion() {
164 return targetVersion;
165 }
166
167 }