View Javadoc
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  import java.net.URL;
21  
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.jcr.ArgeoJcrException;
30  import org.argeo.jcr.JcrCallback;
31  import org.argeo.jcr.JcrUtils;
32  
33  /** Migrate the data in a Jackrabbit repository. */
34  @Deprecated
35  public class JackrabbitDataModelMigration implements
36  		Comparable<JackrabbitDataModelMigration> {
37  	private final static Log log = LogFactory
38  			.getLog(JackrabbitDataModelMigration.class);
39  
40  	private String dataModelNodePath;
41  	private String targetVersion;
42  	private URL migrationCnd;
43  	private JcrCallback dataModification;
44  
45  	/**
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).
48  	 * 
49  	 * @return true if a migration was performed and the repository needs to be
50  	 *         restarted and its caches cleared.
51  	 */
52  	public Boolean migrate(Session session) {
53  		long begin = System.currentTimeMillis();
54  		Reader reader = null;
55  		try {
56  			// check if already migrated
57  			if (!session.itemExists(dataModelNodePath)) {
58  				log.warn("Node " + dataModelNodePath
59  						+ " does not exist: nothing to migrate.");
60  				return false;
61  			}
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.");
69  //					return false;
70  //				}
71  //			}
72  
73  			// apply transitional CND
74  			if (migrationCnd != null) {
75  				reader = new InputStreamReader(migrationCnd.openStream());
76  				CndImporter.registerNodeTypes(reader, session, true);
77  				session.save();
78  				log.info("Registered migration node types from " + migrationCnd);
79  			}
80  
81  			// modify data
82  			dataModification.execute(session);
83  
84  			// apply changes
85  			session.save();
86  
87  			long duration = System.currentTimeMillis() - begin;
88  			log.info("Migration of data model " + dataModelNodePath + " to "
89  					+ targetVersion + " performed in " + duration + "ms");
90  			return true;
91  		} catch (Exception e) {
92  			JcrUtils.discardQuietly(session);
93  			throw new ArgeoJcrException("Migration of data model "
94  					+ dataModelNodePath + " to " + targetVersion + " failed.",
95  					e);
96  		} finally {
97  			JcrUtils.logoutQuietly(session);
98  			IOUtils.closeQuietly(reader);
99  		}
100 	}
101 
102 	protected static int compareVersions(String version1, String version2) {
103 		// TODO do a proper version analysis and comparison
104 		return version1.compareTo(version2);
105 	}
106 
107 	/** To be called on a stopped repository. */
108 	public static void clearRepositoryCaches(RepositoryConfig repositoryConfig) {
109 		try {
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);
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(URL 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 }