2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.jackrabbit
;
18 import java
.io
.InputStreamReader
;
19 import java
.io
.Reader
;
22 import javax
.jcr
.Session
;
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
.jcr
.ArgeoJcrException
;
30 import org
.argeo
.jcr
.JcrCallback
;
31 import org
.argeo
.jcr
.JcrUtils
;
33 /** Migrate the data in a Jackrabbit repository. */
35 public class JackrabbitDataModelMigration
implements
36 Comparable
<JackrabbitDataModelMigration
> {
37 private final static Log log
= LogFactory
38 .getLog(JackrabbitDataModelMigration
.class);
40 private String dataModelNodePath
;
41 private String targetVersion
;
42 private URL migrationCnd
;
43 private JcrCallback dataModification
;
46 * Expects an already started repository with the old data model to migrate.
47 * Expects to be run with admin rights (Repository.login() will be used).
49 * @return true if a migration was performed and the repository needs to be
50 * restarted and its caches cleared.
52 public Boolean
migrate(Session session
) {
53 long begin
= System
.currentTimeMillis();
56 // check if already migrated
57 if (!session
.itemExists(dataModelNodePath
)) {
58 log
.warn("Node " + dataModelNodePath
59 + " does not exist: nothing to migrate.");
62 // Node dataModelNode = session.getNode(dataModelNodePath);
63 // if (dataModelNode.hasProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION)) {
64 // String currentVersion = dataModelNode.getProperty(
65 // ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
66 // if (compareVersions(currentVersion, targetVersion) >= 0) {
67 // log.info("Data model at version " + currentVersion
68 // + ", no need to migrate.");
73 // apply transitional CND
74 if (migrationCnd
!= null) {
75 reader
= new InputStreamReader(migrationCnd
.openStream());
76 CndImporter
.registerNodeTypes(reader
, session
, true);
78 log
.info("Registered migration node types from " + migrationCnd
);
82 dataModification
.execute(session
);
87 long duration
= System
.currentTimeMillis() - begin
;
88 log
.info("Migration of data model " + dataModelNodePath
+ " to "
89 + targetVersion
+ " performed in " + duration
+ "ms");
91 } catch (Exception e
) {
92 JcrUtils
.discardQuietly(session
);
93 throw new ArgeoJcrException("Migration of data model "
94 + dataModelNodePath
+ " to " + targetVersion
+ " failed.",
97 JcrUtils
.logoutQuietly(session
);
98 IOUtils
.closeQuietly(reader
);
102 protected static int compareVersions(String version1
, String version2
) {
103 // TODO do a proper version analysis and comparison
104 return version1
.compareTo(version2
);
107 /** To be called on a stopped repository. */
108 public static void clearRepositoryCaches(RepositoryConfig repositoryConfig
) {
110 String customeNodeTypesPath
= "/nodetypes/custom_nodetypes.xml";
111 // FIXME causes weird error in Eclipse
112 //repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
113 if (log
.isDebugEnabled())
114 log
.debug("Cleared " + customeNodeTypesPath
);
115 } catch (Exception e
) {
116 throw new ArgeoJcrException("Cannot clear caches", e
);
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);
126 // log.warn("File " + customNodeTypes + " not found.");
131 * FOR USE IN (SORTED) SETS
134 public int compareTo(JackrabbitDataModelMigration dataModelMigration
) {
135 // TODO make ordering smarter
136 if (dataModelNodePath
.equals(dataModelMigration
.dataModelNodePath
))
137 return compareVersions(targetVersion
,
138 dataModelMigration
.targetVersion
);
140 return dataModelNodePath
141 .compareTo(dataModelMigration
.dataModelNodePath
);
145 public boolean equals(Object obj
) {
146 if (!(obj
instanceof JackrabbitDataModelMigration
))
148 JackrabbitDataModelMigration dataModelMigration
= (JackrabbitDataModelMigration
) obj
;
149 return dataModelNodePath
.equals(dataModelMigration
.dataModelNodePath
)
150 && targetVersion
.equals(dataModelMigration
.targetVersion
);
154 public int hashCode() {
155 return targetVersion
.hashCode();
158 public void setDataModelNodePath(String dataModelNodePath
) {
159 this.dataModelNodePath
= dataModelNodePath
;
162 public void setTargetVersion(String targetVersion
) {
163 this.targetVersion
= targetVersion
;
166 public void setMigrationCnd(URL migrationCnd
) {
167 this.migrationCnd
= migrationCnd
;
170 public void setDataModification(JcrCallback dataModification
) {
171 this.dataModification
= dataModification
;
174 public String
getDataModelNodePath() {
175 return dataModelNodePath
;
178 public String
getTargetVersion() {
179 return targetVersion
;