1 package org
.argeo
.jackrabbit
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStreamReader
;
8 import javax
.jcr
.RepositoryException
;
9 import javax
.jcr
.Session
;
11 import org
.apache
.commons
.io
.IOUtils
;
12 import org
.apache
.commons
.logging
.Log
;
13 import org
.apache
.commons
.logging
.LogFactory
;
14 import org
.apache
.jackrabbit
.commons
.cnd
.CndImporter
;
15 import org
.apache
.jackrabbit
.commons
.cnd
.ParseException
;
16 import org
.apache
.jackrabbit
.core
.config
.RepositoryConfig
;
17 import org
.apache
.jackrabbit
.core
.fs
.FileSystemException
;
18 import org
.argeo
.jcr
.JcrCallback
;
19 import org
.argeo
.jcr
.JcrException
;
20 import org
.argeo
.jcr
.JcrUtils
;
22 /** Migrate the data in a Jackrabbit repository. */
24 public class JackrabbitDataModelMigration
implements Comparable
<JackrabbitDataModelMigration
> {
25 private final static Log log
= LogFactory
.getLog(JackrabbitDataModelMigration
.class);
27 private String dataModelNodePath
;
28 private String targetVersion
;
29 private URL migrationCnd
;
30 private JcrCallback dataModification
;
33 * Expects an already started repository with the old data model to migrate.
34 * Expects to be run with admin rights (Repository.login() will be used).
36 * @return true if a migration was performed and the repository needs to be
37 * restarted and its caches cleared.
39 public Boolean
migrate(Session session
) {
40 long begin
= System
.currentTimeMillis();
43 // check if already migrated
44 if (!session
.itemExists(dataModelNodePath
)) {
45 // log.warn("Node " + dataModelNodePath + " does not exist: nothing to migrate.");
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.");
59 // apply transitional CND
60 if (migrationCnd
!= null) {
61 reader
= new InputStreamReader(migrationCnd
.openStream());
62 CndImporter
.registerNodeTypes(reader
, session
, true);
64 // log.info("Registered migration node types from " + migrationCnd);
68 dataModification
.execute(session
);
73 long duration
= System
.currentTimeMillis() - begin
;
74 // log.info("Migration of data model " + dataModelNodePath + " to " + targetVersion + " performed in "
75 // + duration + "ms");
77 } catch (RepositoryException e
) {
78 JcrUtils
.discardQuietly(session
);
79 throw new JcrException("Migration of data model " + dataModelNodePath
+ " to " + targetVersion
+ " failed.",
81 } catch (ParseException
| IOException e
) {
82 JcrUtils
.discardQuietly(session
);
83 throw new RuntimeException(
84 "Migration of data model " + dataModelNodePath
+ " to " + targetVersion
+ " failed.", e
);
86 JcrUtils
.logoutQuietly(session
);
87 IOUtils
.closeQuietly(reader
);
91 protected static int compareVersions(String version1
, String version2
) {
92 // TODO do a proper version analysis and comparison
93 return version1
.compareTo(version2
);
96 /** To be called on a stopped repository. */
97 public static void clearRepositoryCaches(RepositoryConfig repositoryConfig
) {
99 String customeNodeTypesPath
= "/nodetypes/custom_nodetypes.xml";
100 // FIXME causes weird error in Eclipse
101 repositoryConfig
.getFileSystem().deleteFile(customeNodeTypesPath
);
102 if (log
.isDebugEnabled())
103 log
.debug("Cleared " + customeNodeTypesPath
);
104 } catch (RuntimeException e
) {
106 } catch (RepositoryException e
) {
107 throw new JcrException(e
);
108 } catch (FileSystemException e
) {
109 throw new RuntimeException("Cannot clear node types cache.",e
);
112 // File customNodeTypes = new File(home.getPath()
113 // + "/repository/nodetypes/custom_nodetypes.xml");
114 // if (customNodeTypes.exists()) {
115 // customNodeTypes.delete();
116 // if (log.isDebugEnabled())
117 // log.debug("Cleared " + customNodeTypes);
119 // log.warn("File " + customNodeTypes + " not found.");
124 * FOR USE IN (SORTED) SETS
127 public int compareTo(JackrabbitDataModelMigration dataModelMigration
) {
128 // TODO make ordering smarter
129 if (dataModelNodePath
.equals(dataModelMigration
.dataModelNodePath
))
130 return compareVersions(targetVersion
, dataModelMigration
.targetVersion
);
132 return dataModelNodePath
.compareTo(dataModelMigration
.dataModelNodePath
);
136 public boolean equals(Object obj
) {
137 if (!(obj
instanceof JackrabbitDataModelMigration
))
139 JackrabbitDataModelMigration dataModelMigration
= (JackrabbitDataModelMigration
) obj
;
140 return dataModelNodePath
.equals(dataModelMigration
.dataModelNodePath
)
141 && targetVersion
.equals(dataModelMigration
.targetVersion
);
145 public int hashCode() {
146 return targetVersion
.hashCode();
149 public void setDataModelNodePath(String dataModelNodePath
) {
150 this.dataModelNodePath
= dataModelNodePath
;
153 public void setTargetVersion(String targetVersion
) {
154 this.targetVersion
= targetVersion
;
157 public void setMigrationCnd(URL migrationCnd
) {
158 this.migrationCnd
= migrationCnd
;
161 public void setDataModification(JcrCallback dataModification
) {
162 this.dataModification
= dataModification
;
165 public String
getDataModelNodePath() {
166 return dataModelNodePath
;
169 public String
getTargetVersion() {
170 return targetVersion
;