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