001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.provider; 017 018import java.util.List; 019import java.util.Map; 020 021import javax.jcr.RepositoryException; 022 023import org.apache.jackrabbit.core.cluster.UpdateEventChannel; 024import org.apache.jackrabbit.core.id.NodeId; 025import org.apache.jackrabbit.core.id.PropertyId; 026import org.apache.jackrabbit.core.persistence.PMContext; 027import org.apache.jackrabbit.core.persistence.PersistenceManager; 028import org.apache.jackrabbit.core.persistence.check.ConsistencyCheckListener; 029import org.apache.jackrabbit.core.persistence.check.ConsistencyReport; 030import org.apache.jackrabbit.core.persistence.pool.BundleDbPersistenceManager; 031import org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager; 032import org.apache.jackrabbit.core.persistence.pool.MySqlPersistenceManager; 033import org.apache.jackrabbit.core.persistence.pool.OraclePersistenceManager; 034import org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager; 035import org.apache.jackrabbit.core.persistence.util.NodeInfo; 036import org.apache.jackrabbit.core.state.ChangeLog; 037import org.apache.jackrabbit.core.state.ItemStateException; 038import org.apache.jackrabbit.core.state.NoSuchItemStateException; 039import org.apache.jackrabbit.core.state.NodeReferences; 040import org.apache.jackrabbit.core.state.NodeState; 041import org.apache.jackrabbit.core.state.PropertyState; 042import org.apache.jackrabbit.core.util.db.ConnectionFactory; 043 044import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition; 045import org.ametys.core.datasource.ConnectionHelper; 046import org.ametys.runtime.config.Config; 047 048/** 049 * Ametys implementation of Jackrabbit's {@link PersistenceManager}. 050 * This implementation is only a wrapper to an actual {@link BundleDbPersistenceManager}, depending on the config parameter. 051 */ 052public class AmetysPersistenceManager extends BundleDbPersistenceManager 053{ 054 /** 055 * Config parameter's name to use default Jackrabbit behaviour. 056 */ 057 public static final String CONFIG_USE_DEFAULT = "org.ametys.plugins.repository.default-datasource"; 058 059 /** 060 * Config parameter's name referencing the datasource to use. 061 */ 062 public static final String CONFIG_PM_DATASOURCE = "org.ametys.plugins.repository.datasource"; 063 064 private BundleDbPersistenceManager _wrappedPM; 065 private boolean _useDefault; 066 private String _workspace; 067 068 /** 069 * Constructor. 070 */ 071 public AmetysPersistenceManager() 072 { 073 _useDefault = Config.getInstance().getValue(CONFIG_USE_DEFAULT); 074 075 if (_useDefault) 076 { 077 _wrappedPM = new DerbyPersistenceManager(); 078 _wrappedPM.setSchemaObjectPrefix(""); 079 _wrappedPM.setExternalBLOBs(true); 080 } 081 else 082 { 083 String datasource = Config.getInstance().getValue(CONFIG_PM_DATASOURCE); 084 085 DataSourceDefinition dsDefinition = ConnectionHelper.getDataSourceDefinition(datasource); 086 087 Map<String, Object> parameters = dsDefinition.getParameters(); 088 String defUrl = (String) parameters.get("url"); 089 String defDriver = (String) parameters.get("driver"); 090 String defUser = (String) parameters.get("user"); 091 String defPassword = (String) parameters.get("password"); 092 093 String dbType = ConnectionHelper.getDatabaseType(defUrl); 094 switch (dbType) 095 { 096 case ConnectionHelper.DATABASE_DERBY: 097 _wrappedPM = new DerbyPersistenceManager(); 098 break; 099 case ConnectionHelper.DATABASE_MYSQL: 100 _wrappedPM = new MySqlPersistenceManager(); 101 break; 102 case ConnectionHelper.DATABASE_ORACLE: 103 _wrappedPM = new OraclePersistenceManager(); 104 break; 105 case ConnectionHelper.DATABASE_POSTGRES: 106 _wrappedPM = new PostgreSQLPersistenceManager(); 107 break; 108 default: 109 throw new IllegalArgumentException("Datasource URL " + defUrl + " is not supported for Jackrabbit PersistenceManagers."); 110 } 111 112 _wrappedPM.setUrl(defUrl); 113 _wrappedPM.setDriver(defDriver); 114 _wrappedPM.setUser(defUser); 115 _wrappedPM.setPassword(defPassword); 116 } 117 } 118 119 /** 120 * Get the wrapped persistence manager 121 * @return the persistence manager 122 */ 123 public BundleDbPersistenceManager getWrappedPM() 124 { 125 return _wrappedPM; 126 } 127 128 /** 129 * Indicates the current JCR workspace. 130 * @param workspace the JCR workspace. 131 */ 132 public void setWorkspace(String workspace) 133 { 134 _workspace = workspace; 135 } 136 137 // Unsupported methods 138 139 @Override 140 public void setUrl(String newUrl) 141 { 142 throw new UnsupportedOperationException("setUrl() method is not supported for AmetysPersistenceManager."); 143 } 144 145 @Override 146 public void setUser(String unused) 147 { 148 throw new UnsupportedOperationException("setUser() method is not supported for AmetysPersistenceManager."); 149 } 150 151 @Override 152 public void setPassword(String unused) 153 { 154 throw new UnsupportedOperationException("setPassword() method is not supported for AmetysPersistenceManager."); 155 } 156 157 @Override 158 public void setDriver(String unused) 159 { 160 throw new UnsupportedOperationException("setDriver() method is not supported for AmetysPersistenceManager."); 161 } 162 163 // PersistenceManager methods 164 165 @Override 166 public void init(PMContext ctx) throws Exception 167 { 168 if (_useDefault) 169 { 170 String dbUrl = "jdbc:derby:" + ctx.getHomeDir().getCanonicalPath() + "/db;create=true"; 171 _wrappedPM.setUrl(dbUrl); 172 } 173 else 174 { 175 String prefix = _workspace == null ? "version_" : _workspace + "_"; 176 _wrappedPM.setSchemaObjectPrefix(prefix); 177 } 178 179 _wrappedPM.init(ctx); 180 } 181 182 @Override 183 public void close() throws Exception 184 { 185 _wrappedPM.close(); 186 } 187 188 @Override 189 public NodeState createNew(NodeId id) 190 { 191 return _wrappedPM.createNew(id); 192 } 193 194 @Override 195 public PropertyState createNew(PropertyId id) 196 { 197 return _wrappedPM.createNew(id); 198 } 199 200 @Override 201 public NodeState load(NodeId id) throws NoSuchItemStateException, ItemStateException 202 { 203 return _wrappedPM.load(id); 204 } 205 206 @Override 207 public PropertyState load(PropertyId id) throws NoSuchItemStateException, ItemStateException 208 { 209 return _wrappedPM.load(id); 210 } 211 212 @Override 213 public NodeReferences loadReferencesTo(NodeId id) throws NoSuchItemStateException, ItemStateException 214 { 215 return _wrappedPM.loadReferencesTo(id); 216 } 217 218 @Override 219 public boolean exists(NodeId id) throws ItemStateException 220 { 221 return _wrappedPM.exists(id); 222 } 223 224 @Override 225 public boolean exists(PropertyId id) throws ItemStateException 226 { 227 return _wrappedPM.exists(id); 228 } 229 230 @Override 231 public boolean existsReferencesTo(NodeId targetId) throws ItemStateException 232 { 233 return _wrappedPM.existsReferencesTo(targetId); 234 } 235 236 @Override 237 public void store(ChangeLog changeLog) throws ItemStateException 238 { 239 _wrappedPM.store(changeLog); 240 } 241 242 @Override 243 public ConsistencyReport check(String[] uuids, boolean recursive, boolean fix, String lostNFoundId, ConsistencyCheckListener listener) throws RepositoryException 244 { 245 return _wrappedPM.check(uuids, recursive, fix, lostNFoundId, listener); 246 } 247 248 @Override 249 public void checkConsistency(String[] uuids, boolean recursive, boolean fix) 250 { 251 _wrappedPM.checkConsistency(uuids, recursive, fix); 252 } 253 254 // BundleDBPersistenceManager methods 255 256 @Override 257 public synchronized List<NodeId> getAllNodeIds(NodeId bigger, int maxCount) throws ItemStateException, RepositoryException 258 { 259 return _wrappedPM.getAllNodeIds(bigger, maxCount); 260 } 261 262 @Override 263 public synchronized void destroy(NodeReferences refs) throws ItemStateException 264 { 265 _wrappedPM.destroy(refs); 266 } 267 268 @Override 269 public synchronized Map<NodeId, NodeInfo> getAllNodeInfos(NodeId bigger, int maxCount) throws ItemStateException 270 { 271 return _wrappedPM.getAllNodeInfos(bigger, maxCount); 272 } 273 274 @Override 275 public void setBlockOnConnectionLoss(String block) 276 { 277 _wrappedPM.setBlockOnConnectionLoss(block); 278 } 279 280 @Override 281 public void setBundleCacheSize(String bundleCacheSize) 282 { 283 _wrappedPM.setBundleCacheSize(bundleCacheSize); 284 } 285 286 @Override 287 public void setConnectionFactory(ConnectionFactory connectionFactory) 288 { 289 _wrappedPM.setConnectionFactory(connectionFactory); 290 } 291 292 @Override 293 public void setConsistencyCheck(String check) 294 { 295 _wrappedPM.setConsistencyCheck(check); 296 } 297 298 @Override 299 public void setConsistencyFix(String fix) 300 { 301 _wrappedPM.setConsistencyFix(fix); 302 } 303 304 @Override 305 public void setErrorHandling(String errHandling) 306 { 307 _wrappedPM.setErrorHandling(errHandling); 308 } 309 310 @Override 311 public void setEventChannel(UpdateEventChannel eventChannel) 312 { 313 _wrappedPM.setEventChannel(eventChannel); 314 } 315 316 @Override 317 public void setExternalBLOBs(boolean externalBlobs) 318 { 319 _wrappedPM.setExternalBLOBs(externalBlobs); 320 } 321 322 @Override 323 public void setMinBlobSize(String minBlobSize) 324 { 325 _wrappedPM.setMinBlobSize(minBlobSize); 326 } 327 328 @Override 329 public void setSchemaObjectPrefix(String schemaPrefix) 330 { 331 _wrappedPM.setSchemaObjectPrefix(schemaPrefix); 332 } 333 334 @Override 335 public String toString() 336 { 337 return _wrappedPM.toString(); 338 } 339}