]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.server.jackrabbit/src/org/argeo/jackrabbit/JackrabbitDataModelMigration.java
New project conventions (builds)
[lgpl/argeo-commons.git] / org.argeo.server.jackrabbit / src / org / argeo / jackrabbit / 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 repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
113 if (log.isDebugEnabled())
114 log.debug("Cleared " + customeNodeTypesPath);
115 } catch (Exception e) {
116 throw new ArgeoException("Cannot clear caches", e);
117 }
118
119 // File customNodeTypes = new File(home.getPath()
120 // + "/repository/nodetypes/custom_nodetypes.xml");
121 // if (customNodeTypes.exists()) {
122 // customNodeTypes.delete();
123 // if (log.isDebugEnabled())
124 // log.debug("Cleared " + customNodeTypes);
125 // } else {
126 // log.warn("File " + customNodeTypes + " not found.");
127 // }
128 }
129
130 /*
131 * FOR USE IN (SORTED) SETS
132 */
133
134 public int compareTo(JackrabbitDataModelMigration dataModelMigration) {
135 // TODO make ordering smarter
136 if (dataModelNodePath.equals(dataModelMigration.dataModelNodePath))
137 return compareVersions(targetVersion,
138 dataModelMigration.targetVersion);
139 else
140 return dataModelNodePath
141 .compareTo(dataModelMigration.dataModelNodePath);
142 }
143
144 @Override
145 public boolean equals(Object obj) {
146 if (!(obj instanceof JackrabbitDataModelMigration))
147 return false;
148 JackrabbitDataModelMigration dataModelMigration = (JackrabbitDataModelMigration) obj;
149 return dataModelNodePath.equals(dataModelMigration.dataModelNodePath)
150 && targetVersion.equals(dataModelMigration.targetVersion);
151 }
152
153 @Override
154 public int hashCode() {
155 return targetVersion.hashCode();
156 }
157
158 public void setDataModelNodePath(String dataModelNodePath) {
159 this.dataModelNodePath = dataModelNodePath;
160 }
161
162 public void setTargetVersion(String targetVersion) {
163 this.targetVersion = targetVersion;
164 }
165
166 public void setMigrationCnd(Resource migrationCnd) {
167 this.migrationCnd = migrationCnd;
168 }
169
170 public void setDataModification(JcrCallback dataModification) {
171 this.dataModification = dataModification;
172 }
173
174 public String getDataModelNodePath() {
175 return dataModelNodePath;
176 }
177
178 public String getTargetVersion() {
179 return targetVersion;
180 }
181
182 }