001/* 002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. 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 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.test; 020 021import static org.junit.Assert.assertNotNull; 022 023import java.net.URL; 024import java.net.UnknownHostException; 025import java.sql.SQLException; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.nuxeo.ecm.core.api.NuxeoException; 030import org.nuxeo.ecm.core.event.EventService; 031import org.nuxeo.ecm.core.storage.mongodb.MongoDBRepository; 032import org.nuxeo.ecm.core.storage.mongodb.MongoDBRepositoryDescriptor; 033import org.nuxeo.ecm.core.storage.sql.DatabaseDB2; 034import org.nuxeo.ecm.core.storage.sql.DatabaseDerby; 035import org.nuxeo.ecm.core.storage.sql.DatabaseH2; 036import org.nuxeo.ecm.core.storage.sql.DatabaseHelper; 037import org.nuxeo.ecm.core.storage.sql.DatabaseMySQL; 038import org.nuxeo.ecm.core.storage.sql.DatabaseOracle; 039import org.nuxeo.ecm.core.storage.sql.DatabasePostgreSQL; 040import org.nuxeo.ecm.core.storage.sql.DatabaseSQLServer; 041import org.nuxeo.runtime.api.Framework; 042import org.nuxeo.runtime.test.runner.FeaturesRunner; 043import org.nuxeo.runtime.test.runner.RuntimeFeature; 044import org.nuxeo.runtime.test.runner.RuntimeHarness; 045import org.osgi.framework.Bundle; 046 047import com.mongodb.BasicDBObject; 048import com.mongodb.DBCollection; 049import com.mongodb.MongoClient; 050 051/** 052 * Description of the specific capabilities of a repository for tests, and helper methods. 053 * 054 * @since 7.3 055 */ 056public class StorageConfiguration { 057 058 private static final Log log = LogFactory.getLog(StorageConfiguration.class); 059 060 public static final String CORE_PROPERTY = "nuxeo.test.core"; 061 062 public static final String CORE_VCS = "vcs"; 063 064 public static final String CORE_MEM = "mem"; 065 066 public static final String CORE_MONGODB = "mongodb"; 067 068 public static final String DEFAULT_CORE = CORE_VCS; 069 070 private static final String MONGODB_SERVER_PROPERTY = "nuxeo.test.mongodb.server"; 071 072 private static final String MONGODB_DBNAME_PROPERTY = "nuxeo.test.mongodb.dbname"; 073 074 private static final String DEFAULT_MONGODB_SERVER = "localhost:27017"; 075 076 private static final String DEFAULT_MONGODB_DBNAME = "unittests"; 077 078 private String coreType; 079 080 private boolean isVCS; 081 082 private boolean isDBS; 083 084 private DatabaseHelper databaseHelper; 085 086 public StorageConfiguration() { 087 initJDBC(); 088 coreType = defaultSystemProperty(CORE_PROPERTY, DEFAULT_CORE); 089 switch (coreType) { 090 case CORE_VCS: 091 isVCS = true; 092 break; 093 case CORE_MEM: 094 isDBS = true; 095 break; 096 case CORE_MONGODB: 097 isDBS = true; 098 initMongoDB(); 099 break; 100 default: 101 throw new ExceptionInInitializerError("Unknown test core mode: " + coreType); 102 } 103 } 104 105 protected static String defaultSystemProperty(String name, String def) { 106 String value = System.getProperty(name); 107 if (value == null || value.equals("") || value.equals("${" + name + "}")) { 108 System.setProperty(name, value = def); 109 } 110 return value; 111 } 112 113 protected static String defaultProperty(String name, String def) { 114 String value = System.getProperty(name); 115 if (value == null || value.equals("") || value.equals("${" + name + "}")) { 116 value = def; 117 } 118 Framework.getProperties().setProperty(name, value); 119 return value; 120 } 121 122 protected void initJDBC() { 123 databaseHelper = DatabaseHelper.DATABASE; 124 125 String msg = "Deploying JDBC using " + databaseHelper.getClass().getSimpleName(); 126 // System.out used on purpose, don't remove 127 System.out.println(getClass().getSimpleName() + ": " + msg); 128 log.info(msg); 129 130 // setup system properties for generic XML extension points 131 // this is used both for VCS (org.nuxeo.ecm.core.storage.sql.RepositoryService) 132 // and DataSources (org.nuxeo.runtime.datasource) extension points 133 try { 134 databaseHelper.setUp(); 135 } catch (SQLException e) { 136 throw new NuxeoException(e); 137 } 138 } 139 140 protected void initMongoDB() { 141 String server = defaultProperty(MONGODB_SERVER_PROPERTY, DEFAULT_MONGODB_SERVER); 142 String dbname = defaultProperty(MONGODB_DBNAME_PROPERTY, DEFAULT_MONGODB_DBNAME); 143 MongoDBRepositoryDescriptor descriptor = new MongoDBRepositoryDescriptor(); 144 descriptor.name = getRepositoryName(); 145 descriptor.server = server; 146 descriptor.dbname = dbname; 147 try { 148 clearMongoDB(descriptor); 149 } catch (UnknownHostException e) { 150 throw new NuxeoException(e); 151 } 152 } 153 154 protected void clearMongoDB(MongoDBRepositoryDescriptor descriptor) throws UnknownHostException { 155 MongoClient mongoClient = MongoDBRepository.newMongoClient(descriptor); 156 try { 157 DBCollection coll = MongoDBRepository.getCollection(descriptor, mongoClient); 158 coll.dropIndexes(); 159 coll.remove(new BasicDBObject()); 160 coll = MongoDBRepository.getCountersCollection(descriptor, mongoClient); 161 coll.dropIndexes(); 162 coll.remove(new BasicDBObject()); 163 } finally { 164 mongoClient.close(); 165 } 166 } 167 168 public boolean isVCS() { 169 return isVCS; 170 } 171 172 public boolean isVCSH2() { 173 return isVCS && databaseHelper instanceof DatabaseH2; 174 } 175 176 public boolean isVCSDerby() { 177 return isVCS && databaseHelper instanceof DatabaseDerby; 178 } 179 180 public boolean isVCSPostgreSQL() { 181 return isVCS && databaseHelper instanceof DatabasePostgreSQL; 182 } 183 184 public boolean isVCSMySQL() { 185 return isVCS && databaseHelper instanceof DatabaseMySQL; 186 } 187 188 public boolean isVCSOracle() { 189 return isVCS && databaseHelper instanceof DatabaseOracle; 190 } 191 192 public boolean isVCSSQLServer() { 193 return isVCS && databaseHelper instanceof DatabaseSQLServer; 194 } 195 196 public boolean isVCSDB2() { 197 return isVCS && databaseHelper instanceof DatabaseDB2; 198 } 199 200 public boolean isDBS() { 201 return isDBS; 202 } 203 204 public boolean isDBSMem() { 205 return isDBS && CORE_MEM.equals(coreType); 206 } 207 208 public boolean isDBSMongoDB() { 209 return isDBS && CORE_MONGODB.equals(coreType); 210 } 211 212 public String getRepositoryName() { 213 return "test"; 214 } 215 216 /** 217 * For databases that do asynchronous fulltext indexing, sleep a bit. 218 */ 219 public void sleepForFulltext() { 220 if (isVCS()) { 221 databaseHelper.sleepForFulltext(); 222 } else { 223 // DBS 224 } 225 } 226 227 /** 228 * For databases that don't have sub-second resolution, sleep a bit to get to the next second. 229 */ 230 public void maybeSleepToNextSecond() { 231 if (isVCS()) { 232 databaseHelper.maybeSleepToNextSecond(); 233 } else { 234 // DBS 235 } 236 // sleep 1 ms nevertheless to have different timestamps 237 try { 238 Thread.sleep(1); 239 } catch (InterruptedException e) { 240 Thread.currentThread().interrupt(); // restore interrupted status 241 throw new RuntimeException(e); 242 } 243 } 244 245 /** 246 * Checks if the database has sub-second resolution. 247 */ 248 public boolean hasSubSecondResolution() { 249 if (isVCS()) { 250 return databaseHelper.hasSubSecondResolution(); 251 } else { 252 return true; // DBS 253 } 254 } 255 256 public void waitForAsyncCompletion() { 257 Framework.getService(EventService.class).waitForAsyncCompletion(); 258 } 259 260 public void waitForFulltextIndexing() { 261 waitForAsyncCompletion(); 262 sleepForFulltext(); 263 } 264 265 /** 266 * Checks if the database supports multiple fulltext indexes. 267 */ 268 public boolean supportsMultipleFulltextIndexes() { 269 if (isVCS()) { 270 return databaseHelper.supportsMultipleFulltextIndexes(); 271 } else { 272 return false; // DBS 273 } 274 } 275 276 public URL getBlobManagerContrib(FeaturesRunner runner) { 277 String bundleName = "org.nuxeo.ecm.core.test"; 278 String contribPath = "OSGI-INF/test-storage-blob-contrib.xml"; 279 RuntimeHarness harness = runner.getFeature(RuntimeFeature.class).getHarness(); 280 Bundle bundle = harness.getOSGiAdapter().getRegistry().getBundle(bundleName); 281 URL contribURL = bundle.getEntry(contribPath); 282 assertNotNull("deployment contrib " + contribPath + " not found", contribURL); 283 return contribURL; 284 } 285 286 public URL getRepositoryContrib(FeaturesRunner runner) { 287 String msg; 288 if (isVCS()) { 289 msg = "Deploying a VCS repository"; 290 } else if (isDBS()) { 291 msg = "Deploying a DBS repository using " + coreType; 292 } else { 293 throw new NuxeoException("Unkown test configuration (not vcs/dbs)"); 294 } 295 // System.out used on purpose, don't remove 296 System.out.println(getClass().getSimpleName() + ": " + msg); 297 log.info(msg); 298 299 String contribPath; 300 String bundleName; 301 if (isVCS()) { 302 bundleName = "org.nuxeo.ecm.core.storage.sql.test"; 303 contribPath = databaseHelper.getDeploymentContrib(); 304 } else { 305 bundleName = "org.nuxeo.ecm.core.test"; 306 if (isDBSMem()) { 307 contribPath = "OSGI-INF/test-storage-repo-mem-contrib.xml"; 308 } else if (isDBSMongoDB()) { 309 contribPath = "OSGI-INF/test-storage-repo-mongodb-contrib.xml"; 310 } else { 311 throw new NuxeoException("Unkown DBS test configuration (not mem/mongodb)"); 312 } 313 } 314 RuntimeHarness harness = runner.getFeature(RuntimeFeature.class).getHarness(); 315 Bundle bundle = harness.getOSGiAdapter().getRegistry().getBundle(bundleName); 316 URL contribURL = bundle.getEntry(contribPath); 317 assertNotNull("deployment contrib " + contribPath + " not found", contribURL); 318 return contribURL; 319 } 320 321}