| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| MetadataManager |
|
| 2.3333333333333335;2.333 |
| 1 | package org.apache.ojb.broker.metadata; | |
| 2 | ||
| 3 | /* Copyright 2002-2005 The Apache Software Foundation | |
| 4 | * | |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 | * you may not use this file except in compliance with the License. | |
| 7 | * You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | ||
| 18 | import java.io.FileNotFoundException; | |
| 19 | import java.io.InputStream; | |
| 20 | import java.util.Hashtable; | |
| 21 | import java.util.Iterator; | |
| 22 | import java.util.List; | |
| 23 | ||
| 24 | import org.apache.commons.lang.SerializationUtils; | |
| 25 | import org.apache.ojb.broker.PBKey; | |
| 26 | import org.apache.ojb.broker.core.PersistenceBrokerConfiguration; | |
| 27 | import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator; | |
| 28 | import org.apache.ojb.broker.util.logging.Logger; | |
| 29 | import org.apache.ojb.broker.util.logging.LoggerFactory; | |
| 30 | ||
| 31 | /** | |
| 32 | * Central class for metadata operations/manipulations - manages OJB's | |
| 33 | * metadata objects, in particular: | |
| 34 | * <ul> | |
| 35 | * <li>{@link org.apache.ojb.broker.metadata.DescriptorRepository} contains | |
| 36 | * metadata of persistent objects</li> | |
| 37 | * <li>{@link org.apache.ojb.broker.metadata.ConnectionRepository} contains | |
| 38 | * all connection metadata information</li> | |
| 39 | * </ul> | |
| 40 | * | |
| 41 | * This class allows transparent flexible metadata loading/manipulation at runtime. | |
| 42 | * | |
| 43 | * <p> | |
| 44 | * <b>How to read/merge metadata</b><br/> | |
| 45 | * Per default OJB loads default {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 46 | * and {@link org.apache.ojb.broker.metadata.ConnectionRepository} instances, by reading the | |
| 47 | * specified repository file. This is done first time the <code>MetadataManager</code> instance | |
| 48 | * was used. | |
| 49 | * <br/> | |
| 50 | * To read metadata information at runtime use | |
| 51 | * {@link #readDescriptorRepository readDescriptorRepository} and | |
| 52 | * {@link #readConnectionRepository readConnectionRepository} | |
| 53 | * methods. | |
| 54 | * <br/> | |
| 55 | * It is also possible to merge different repositories using | |
| 56 | * {@link #mergeDescriptorRepository mergeDescriptorRepository} | |
| 57 | * and {@link #mergeConnectionRepository mergeConnectionRepository} | |
| 58 | * | |
| 59 | * </p> | |
| 60 | * | |
| 61 | * <a name="perThread"/> | |
| 62 | * <h3>Per thread handling of metadata</h3> | |
| 63 | * <p> | |
| 64 | * Per default the manager handle one global {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 65 | * for all calling threads, but it is ditto possible to use different metadata <i>profiles</i> in a per thread | |
| 66 | * manner - <i>profiles</i> means different copies of {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 67 | * objects. | |
| 68 | * <p/> | |
| 69 | * | |
| 70 | * <p> | |
| 71 | * <a name="enablePerThreadMode"/> | |
| 72 | * <b>Enable the per thread mode</b><br/> | |
| 73 | * To enable the 'per thread' mode for {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 74 | * instances: | |
| 75 | * <pre> | |
| 76 | * MetadataManager mm = MetadataManager.getInstance(); | |
| 77 | * // tell the manager to use per thread mode | |
| 78 | * mm.setEnablePerThreadChanges(true); | |
| 79 | * ... | |
| 80 | * </pre> | |
| 81 | * This could be done e.g. at start up.<br/> | |
| 82 | * Now it's possible to use dedicated <code>DescriptorRepository</code> instances | |
| 83 | * per thread: | |
| 84 | * <pre> | |
| 85 | * // e.g we get a coppy of the global repository | |
| 86 | * DescriptorRepository dr = mm.copyOfGlobalRepository(); | |
| 87 | * // now we can manipulate the persistent object metadata of the copy | |
| 88 | * ...... | |
| 89 | * | |
| 90 | * // set the changed repository for this thread | |
| 91 | * mm.setDescriptor(dr); | |
| 92 | * | |
| 93 | * // now let this thread lookup a PersistenceBroker instance | |
| 94 | * // with the modified metadata | |
| 95 | * // all other threads use the global metadata | |
| 96 | * PersistenceBroker broker = Persis...... | |
| 97 | * </pre> | |
| 98 | * Note: Change metadata <i>before</i> lookup the {@link org.apache.ojb.broker.PersistenceBroker} | |
| 99 | * instance for current thread, because the metadata was bound to the PB at lookup. | |
| 100 | * </p> | |
| 101 | * | |
| 102 | * <p> | |
| 103 | * <b>How to use different metadata profiles</b><br/> | |
| 104 | * MetadataManager was shipped with a simple mechanism to | |
| 105 | * add, remove and load different persistent objects metadata | |
| 106 | * profiles (different {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 107 | * instances) in a per thread manner. Use | |
| 108 | * <ul> | |
| 109 | * <li>{@link #addProfile addProfile} add different persistent object metadata profiles</li> | |
| 110 | * <li>{@link #removeProfile removeProfile} remove a persistent object metadata profiles</li> | |
| 111 | * <li>{@link #loadProfile loadProfile} load a profile for the current thread</li> | |
| 112 | * </ul> | |
| 113 | * Note: method {@link #loadProfile loadProfile} only works if | |
| 114 | * the <a href="#enablePerThreadMode">per thread mode</a> is enabled. | |
| 115 | * </p> | |
| 116 | * | |
| 117 | * | |
| 118 | * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a> | |
| 119 | * @version $Id: MetadataManager.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $ | |
| 120 | */ | |
| 121 | public class MetadataManager | |
| 122 | { | |
| 123 | private static Logger log = LoggerFactory.getLogger(MetadataManager.class); | |
| 124 | ||
| 125 | private static final String MSG_STR = "* Can't find DescriptorRepository for current thread, use default one *"; | |
| 126 | private static ThreadLocal threadedRepository = new ThreadLocal(); | |
| 127 | private static ThreadLocal currentProfileKey = new ThreadLocal(); | |
| 128 | private static MetadataManager singleton; | |
| 129 | ||
| 130 | private Hashtable metadataProfiles; | |
| 131 | private DescriptorRepository globalRepository; | |
| 132 | private ConnectionRepository connectionRepository; | |
| 133 | private boolean enablePerThreadChanges; | |
| 134 | private PBKey defaultPBKey; | |
| 135 | ||
| 136 | // singleton | |
| 137 | private MetadataManager() | |
| 138 | { | |
| 139 | init(); | |
| 140 | } | |
| 141 | ||
| 142 | private void init() | |
| 143 | { | |
| 144 | metadataProfiles = new Hashtable(); | |
| 145 | final String repository = ((PersistenceBrokerConfiguration) OjbConfigurator.getInstance() | |
| 146 | .getConfigurationFor(null)).getRepositoryFilename(); | |
| 147 | try | |
| 148 | { | |
| 149 | globalRepository = new RepositoryPersistor().readDescriptorRepository(repository); | |
| 150 | connectionRepository = new RepositoryPersistor().readConnectionRepository(repository); | |
| 151 | } | |
| 152 | catch (FileNotFoundException ex) | |
| 153 | { | |
| 154 | log.warn("Could not access '" + repository + "' or a DOCTYPE/DTD-dependency. " | |
| 155 | + "(Check letter case for file names and HTTP-access if using DOCTYPE PUBLIC)" | |
| 156 | + " Starting with empty metadata and connection configurations.", ex); | |
| 157 | globalRepository = new DescriptorRepository(); | |
| 158 | connectionRepository = new ConnectionRepository(); | |
| 159 | } | |
| 160 | catch (Exception ex) | |
| 161 | { | |
| 162 | throw new MetadataException("Can't read repository file '" + repository + "'", ex); | |
| 163 | } | |
| 164 | } | |
| 165 | ||
| 166 | public void shutdown() | |
| 167 | { | |
| 168 | threadedRepository = null; | |
| 169 | currentProfileKey = null; | |
| 170 | globalRepository = null; | |
| 171 | metadataProfiles = null; | |
| 172 | singleton = null; | |
| 173 | } | |
| 174 | ||
| 175 | /** | |
| 176 | * Returns an instance of this class. | |
| 177 | */ | |
| 178 | public static synchronized MetadataManager getInstance() | |
| 179 | { | |
| 180 | // lazy initialization | |
| 181 | if (singleton == null) | |
| 182 | { | |
| 183 | singleton = new MetadataManager(); | |
| 184 | } | |
| 185 | return singleton; | |
| 186 | } | |
| 187 | ||
| 188 | /** | |
| 189 | * Returns the current valid {@link org.apache.ojb.broker.metadata.DescriptorRepository} for | |
| 190 | * the caller. This is the provided way to obtain the | |
| 191 | * {@link org.apache.ojb.broker.metadata.DescriptorRepository}. | |
| 192 | * <br> | |
| 193 | * When {@link #isEnablePerThreadChanges per thread descriptor handling} is enabled | |
| 194 | * it search for a specific {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 195 | * for the calling thread, if none can be found the global descriptor was returned. | |
| 196 | * | |
| 197 | * @see MetadataManager#getGlobalRepository | |
| 198 | * @see MetadataManager#copyOfGlobalRepository | |
| 199 | */ | |
| 200 | public DescriptorRepository getRepository() | |
| 201 | { | |
| 202 | DescriptorRepository repository; | |
| 203 | if (enablePerThreadChanges) | |
| 204 | { | |
| 205 | repository = (DescriptorRepository) threadedRepository.get(); | |
| 206 | if (repository == null) | |
| 207 | { | |
| 208 | repository = getGlobalRepository(); | |
| 209 | log.info(MSG_STR); | |
| 210 | } | |
| 211 | // arminw: | |
| 212 | // TODO: Be more strict in per thread mode and throw a exception when not find descriptor for calling thread? | |
| 213 | // if (repository == null) | |
| 214 | // { | |
| 215 | // throw new MetadataException("Can't find a DescriptorRepository for current thread, don't forget" + | |
| 216 | // " to set a DescriptorRepository if enable per thread changes before perform other action"); | |
| 217 | // } | |
| 218 | return repository; | |
| 219 | } | |
| 220 | else | |
| 221 | { | |
| 222 | return globalRepository; | |
| 223 | } | |
| 224 | } | |
| 225 | ||
| 226 | /** | |
| 227 | * Returns explicit the global {@link org.apache.ojb.broker.metadata.DescriptorRepository} - use with | |
| 228 | * care, because it ignores the {@link #isEnablePerThreadChanges per thread mode}. | |
| 229 | * | |
| 230 | * @see MetadataManager#getRepository | |
| 231 | * @see MetadataManager#copyOfGlobalRepository | |
| 232 | */ | |
| 233 | public DescriptorRepository getGlobalRepository() | |
| 234 | { | |
| 235 | return globalRepository; | |
| 236 | } | |
| 237 | ||
| 238 | /** | |
| 239 | * Returns the {@link ConnectionRepository}. | |
| 240 | */ | |
| 241 | public ConnectionRepository connectionRepository() | |
| 242 | { | |
| 243 | return connectionRepository; | |
| 244 | } | |
| 245 | ||
| 246 | /** | |
| 247 | * Merge the given {@link ConnectionRepository} with the existing one (without making | |
| 248 | * a deep copy of the containing connection descriptors). | |
| 249 | * @see #mergeConnectionRepository(ConnectionRepository targetRepository, ConnectionRepository sourceRepository, boolean deep) | |
| 250 | */ | |
| 251 | public void mergeConnectionRepository(ConnectionRepository repository) | |
| 252 | { | |
| 253 | mergeConnectionRepository(connectionRepository(), repository, false); | |
| 254 | } | |
| 255 | ||
| 256 | /** | |
| 257 | * Merge the given source {@link ConnectionRepository} with the | |
| 258 | * existing target. If parameter | |
| 259 | * <tt>deep</tt> is set <code>true</code> deep copies of source objects were made. | |
| 260 | * <br/> | |
| 261 | * Note: Using <tt>deep copy mode</tt> all descriptors will be serialized | |
| 262 | * by using the default class loader to resolve classes. This can be problematic | |
| 263 | * when classes are loaded by a context class loader. | |
| 264 | * <p> | |
| 265 | * Note: All classes within the repository structure have to implement | |
| 266 | * <code>java.io.Serializable</code> to be able to create a cloned copy. | |
| 267 | */ | |
| 268 | public void mergeConnectionRepository( | |
| 269 | ConnectionRepository targetRepository, ConnectionRepository sourceRepository, boolean deep) | |
| 270 | { | |
| 271 | List list = sourceRepository.getAllDescriptor(); | |
| 272 | for (Iterator iterator = list.iterator(); iterator.hasNext();) | |
| 273 | { | |
| 274 | JdbcConnectionDescriptor jcd = (JdbcConnectionDescriptor) iterator.next(); | |
| 275 | if (deep) | |
| 276 | { | |
| 277 | //TODO: adopt copy/clone methods for metadata classes? | |
| 278 | jcd = (JdbcConnectionDescriptor) SerializationUtils.clone(jcd); | |
| 279 | } | |
| 280 | targetRepository.addDescriptor(jcd); | |
| 281 | } | |
| 282 | } | |
| 283 | ||
| 284 | /** | |
| 285 | * Merge the given {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 286 | * (without making a deep copy of containing class-descriptor objects) with the | |
| 287 | * global one, returned by method {@link #getRepository()} - keep | |
| 288 | * in mind if running in <a href="#perThread">per thread mode</a> | |
| 289 | * merge maybe only takes effect on current thread. | |
| 290 | * | |
| 291 | * @see #mergeDescriptorRepository(DescriptorRepository targetRepository, DescriptorRepository sourceRepository, boolean deep) | |
| 292 | */ | |
| 293 | public void mergeDescriptorRepository(DescriptorRepository repository) | |
| 294 | { | |
| 295 | mergeDescriptorRepository(getRepository(), repository, false); | |
| 296 | } | |
| 297 | ||
| 298 | /** | |
| 299 | * Merge the given {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 300 | * files, the source objects will be pushed to the target repository. If parameter | |
| 301 | * <tt>deep</tt> is set <code>true</code> deep copies of source objects were made. | |
| 302 | * <br/> | |
| 303 | * Note: Using <tt>deep copy mode</tt> all descriptors will be serialized | |
| 304 | * by using the default class loader to resolve classes. This can be problematic | |
| 305 | * when classes are loaded by a context class loader. | |
| 306 | * <p> | |
| 307 | * Note: All classes within the repository structure have to implement | |
| 308 | * <code>java.io.Serializable</code> to be able to create a cloned copy. | |
| 309 | * | |
| 310 | * @see #isEnablePerThreadChanges | |
| 311 | * @see #setEnablePerThreadChanges | |
| 312 | */ | |
| 313 | public void mergeDescriptorRepository( | |
| 314 | DescriptorRepository targetRepository, DescriptorRepository sourceRepository, boolean deep) | |
| 315 | { | |
| 316 | Iterator it = sourceRepository.iterator(); | |
| 317 | while (it.hasNext()) | |
| 318 | { | |
| 319 | ClassDescriptor cld = (ClassDescriptor) it.next(); | |
| 320 | if (deep) | |
| 321 | { | |
| 322 | //TODO: adopt copy/clone methods for metadata classes? | |
| 323 | cld = (ClassDescriptor) SerializationUtils.clone(cld); | |
| 324 | } | |
| 325 | targetRepository.put(cld.getClassOfObject(), cld); | |
| 326 | cld.setRepository(targetRepository); | |
| 327 | } | |
| 328 | } | |
| 329 | ||
| 330 | /** | |
| 331 | * Read ClassDescriptors from the given repository file. | |
| 332 | * @see #mergeDescriptorRepository | |
| 333 | */ | |
| 334 | public DescriptorRepository readDescriptorRepository(String fileName) | |
| 335 | { | |
| 336 | try | |
| 337 | { | |
| 338 | RepositoryPersistor persistor = new RepositoryPersistor(); | |
| 339 | return persistor.readDescriptorRepository(fileName); | |
| 340 | } | |
| 341 | catch (Exception e) | |
| 342 | { | |
| 343 | throw new MetadataException("Can not read repository " + fileName, e); | |
| 344 | } | |
| 345 | } | |
| 346 | ||
| 347 | /** | |
| 348 | * Read ClassDescriptors from the given InputStream. | |
| 349 | * @see #mergeDescriptorRepository | |
| 350 | */ | |
| 351 | public DescriptorRepository readDescriptorRepository(InputStream inst) | |
| 352 | { | |
| 353 | try | |
| 354 | { | |
| 355 | RepositoryPersistor persistor = new RepositoryPersistor(); | |
| 356 | return persistor.readDescriptorRepository(inst); | |
| 357 | } | |
| 358 | catch (Exception e) | |
| 359 | { | |
| 360 | throw new MetadataException("Can not read repository " + inst, e); | |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | /** | |
| 365 | * Read JdbcConnectionDescriptors from the given repository file. | |
| 366 | * | |
| 367 | * @see #mergeConnectionRepository | |
| 368 | */ | |
| 369 | public ConnectionRepository readConnectionRepository(String fileName) | |
| 370 | { | |
| 371 | try | |
| 372 | { | |
| 373 | RepositoryPersistor persistor = new RepositoryPersistor(); | |
| 374 | return persistor.readConnectionRepository(fileName); | |
| 375 | } | |
| 376 | catch (Exception e) | |
| 377 | { | |
| 378 | throw new MetadataException("Can not read repository " + fileName, e); | |
| 379 | } | |
| 380 | } | |
| 381 | ||
| 382 | /** | |
| 383 | * Read JdbcConnectionDescriptors from this InputStream. | |
| 384 | * | |
| 385 | * @see #mergeConnectionRepository | |
| 386 | */ | |
| 387 | public ConnectionRepository readConnectionRepository(InputStream inst) | |
| 388 | { | |
| 389 | try | |
| 390 | { | |
| 391 | RepositoryPersistor persistor = new RepositoryPersistor(); | |
| 392 | return persistor.readConnectionRepository(inst); | |
| 393 | } | |
| 394 | catch (Exception e) | |
| 395 | { | |
| 396 | throw new MetadataException("Can not read repository from " + inst, e); | |
| 397 | } | |
| 398 | } | |
| 399 | ||
| 400 | /** | |
| 401 | * Set the {@link org.apache.ojb.broker.metadata.DescriptorRepository} - if <i>global</i> was true, the | |
| 402 | * given descriptor aquire global availability (<i>use with care!</i>), | |
| 403 | * else the given descriptor was associated with the calling thread. | |
| 404 | * | |
| 405 | * @see #isEnablePerThreadChanges | |
| 406 | * @see #setEnablePerThreadChanges | |
| 407 | */ | |
| 408 | public void setDescriptor(DescriptorRepository repository, boolean global) | |
| 409 | { | |
| 410 | if (global) | |
| 411 | { | |
| 412 | if (log.isDebugEnabled()) log.debug("Set new global repository: " + repository); | |
| 413 | globalRepository = repository; | |
| 414 | } | |
| 415 | else | |
| 416 | { | |
| 417 | if (log.isDebugEnabled()) log.debug("Set new threaded repository: " + repository); | |
| 418 | threadedRepository.set(repository); | |
| 419 | } | |
| 420 | } | |
| 421 | ||
| 422 | /** | |
| 423 | * Set {@link DescriptorRepository} for the current thread. | |
| 424 | * Convenience method for | |
| 425 | * {@link #setDescriptor(DescriptorRepository repository, boolean global) setDescriptor(repository, false)}. | |
| 426 | */ | |
| 427 | public void setDescriptor(DescriptorRepository repository) | |
| 428 | { | |
| 429 | setDescriptor(repository, false); | |
| 430 | } | |
| 431 | ||
| 432 | /** | |
| 433 | * Convenience method for | |
| 434 | * {@link #setDescriptor setDescriptor(repository, false)}. | |
| 435 | * @deprecated use {@link #setDescriptor} | |
| 436 | */ | |
| 437 | public void setPerThreadDescriptor(DescriptorRepository repository) | |
| 438 | { | |
| 439 | setDescriptor(repository, false); | |
| 440 | } | |
| 441 | ||
| 442 | /** | |
| 443 | * Returns a copy of the current global | |
| 444 | * {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 445 | * <p> | |
| 446 | * Note: All classes within the repository structure have to implement | |
| 447 | * <code>java.io.Serializable</code> to be able to create a cloned copy. | |
| 448 | * | |
| 449 | * @see MetadataManager#getGlobalRepository | |
| 450 | * @see MetadataManager#getRepository | |
| 451 | */ | |
| 452 | public DescriptorRepository copyOfGlobalRepository() | |
| 453 | { | |
| 454 | return (DescriptorRepository) SerializationUtils.clone(globalRepository); | |
| 455 | } | |
| 456 | ||
| 457 | /** | |
| 458 | * If returns <i>true</i> if <a href="#perThread">per thread</a> runtime | |
| 459 | * changes of the {@link org.apache.ojb.broker.metadata.DescriptorRepository} | |
| 460 | * is enabled and the {@link #getRepository} method returns a threaded | |
| 461 | * repository file if set, or the global if no threaded was found. | |
| 462 | * <br> | |
| 463 | * If returns <i>false</i> the {@link #getRepository} method return | |
| 464 | * always the {@link #getGlobalRepository() global} repository. | |
| 465 | * | |
| 466 | * @see #setEnablePerThreadChanges | |
| 467 | */ | |
| 468 | public boolean isEnablePerThreadChanges() | |
| 469 | { | |
| 470 | return enablePerThreadChanges; | |
| 471 | } | |
| 472 | ||
| 473 | /** | |
| 474 | * Enable the possibility of making <a href="#perThread">per thread</a> runtime changes | |
| 475 | * of the {@link org.apache.ojb.broker.metadata.DescriptorRepository}. | |
| 476 | * | |
| 477 | * @see #isEnablePerThreadChanges | |
| 478 | */ | |
| 479 | public void setEnablePerThreadChanges(boolean enablePerThreadChanges) | |
| 480 | { | |
| 481 | this.enablePerThreadChanges = enablePerThreadChanges; | |
| 482 | } | |
| 483 | ||
| 484 | /** | |
| 485 | * Add a metadata profile. | |
| 486 | * @see #loadProfile | |
| 487 | */ | |
| 488 | public void addProfile(Object key, DescriptorRepository repository) | |
| 489 | { | |
| 490 | if (metadataProfiles.contains(key)) | |
| 491 | { | |
| 492 | throw new MetadataException("Duplicate profile key. Key '" + key + "' already exists."); | |
| 493 | } | |
| 494 | metadataProfiles.put(key, repository); | |
| 495 | } | |
| 496 | ||
| 497 | /** | |
| 498 | * Load the given metadata profile for the current thread. | |
| 499 | * | |
| 500 | */ | |
| 501 | public void loadProfile(Object key) | |
| 502 | { | |
| 503 | if (!isEnablePerThreadChanges()) | |
| 504 | { | |
| 505 | throw new MetadataException("Can not load profile with disabled per thread mode"); | |
| 506 | } | |
| 507 | DescriptorRepository rep = (DescriptorRepository) metadataProfiles.get(key); | |
| 508 | if (rep == null) | |
| 509 | { | |
| 510 | throw new MetadataException("Can not find profile for key '" + key + "'"); | |
| 511 | } | |
| 512 | currentProfileKey.set(key); | |
| 513 | setDescriptor(rep); | |
| 514 | } | |
| 515 | ||
| 516 | /** | |
| 517 | * Returns the last activated profile key. | |
| 518 | * @return the last activated profile key or null if no profile has been loaded | |
| 519 | * @throws MetadataException if per-thread changes has not been activated | |
| 520 | * @see #loadProfile(Object) | |
| 521 | */ | |
| 522 | public Object getCurrentProfileKey() throws MetadataException | |
| 523 | { | |
| 524 | if (!isEnablePerThreadChanges()) | |
| 525 | { | |
| 526 | throw new MetadataException("Call to this method is undefined, since per-thread mode is disabled."); | |
| 527 | } | |
| 528 | return currentProfileKey.get(); | |
| 529 | } | |
| 530 | ||
| 531 | /** | |
| 532 | * Remove the given metadata profile. | |
| 533 | */ | |
| 534 | public DescriptorRepository removeProfile(Object key) | |
| 535 | { | |
| 536 | return (DescriptorRepository) metadataProfiles.remove(key); | |
| 537 | } | |
| 538 | ||
| 539 | /** | |
| 540 | * Remove all metadata profiles. | |
| 541 | */ | |
| 542 | public void clearProfiles() | |
| 543 | { | |
| 544 | metadataProfiles.clear(); | |
| 545 | currentProfileKey.set(null); | |
| 546 | } | |
| 547 | ||
| 548 | /** | |
| 549 | * Remove all profiles | |
| 550 | * | |
| 551 | * @see #removeProfile | |
| 552 | * @see #addProfile | |
| 553 | */ | |
| 554 | public void removeAllProfiles() | |
| 555 | { | |
| 556 | metadataProfiles.clear(); | |
| 557 | currentProfileKey.set(null); | |
| 558 | } | |
| 559 | ||
| 560 | /** | |
| 561 | * Return the default {@link PBKey} used in convinience method | |
| 562 | * {@link org.apache.ojb.broker.PersistenceBrokerFactory#defaultPersistenceBroker}. | |
| 563 | * <br/> | |
| 564 | * If in {@link JdbcConnectionDescriptor} the | |
| 565 | * {@link JdbcConnectionDescriptor#isDefaultConnection() default connection} | |
| 566 | * is enabled, OJB will detect the default {@link org.apache.ojb.broker.PBKey} by itself. | |
| 567 | * | |
| 568 | * @see #setDefaultPBKey | |
| 569 | */ | |
| 570 | public PBKey getDefaultPBKey() | |
| 571 | { | |
| 572 | if(defaultPBKey == null) | |
| 573 | { | |
| 574 | defaultPBKey = buildDefaultKey(); | |
| 575 | } | |
| 576 | return defaultPBKey; | |
| 577 | } | |
| 578 | ||
| 579 | /** | |
| 580 | * Set the {@link PBKey} used in convinience method | |
| 581 | * {@link org.apache.ojb.broker.PersistenceBrokerFactory#defaultPersistenceBroker}. | |
| 582 | * <br/> | |
| 583 | * It's only allowed to use one {@link JdbcConnectionDescriptor} with enabled | |
| 584 | * {@link JdbcConnectionDescriptor#isDefaultConnection() default connection}. In this case | |
| 585 | * OJB will automatically set the default key. | |
| 586 | * <br/> | |
| 587 | * Note: It's recommended to set this key only once and not to change at runtime | |
| 588 | * of OJB to avoid side-effects. | |
| 589 | * If set more then one time a warning will be logged. | |
| 590 | * @throws MetadataException if key was set more than one time | |
| 591 | */ | |
| 592 | public void setDefaultPBKey(PBKey defaultPBKey) | |
| 593 | { | |
| 594 | if(this.defaultPBKey != null) | |
| 595 | { | |
| 596 | log.warn("The used default PBKey change. Current key is " + this.defaultPBKey + ", new key will be " + defaultPBKey); | |
| 597 | } | |
| 598 | this.defaultPBKey = defaultPBKey; | |
| 599 | log.info("Set default PBKey for convenience broker creation: " + defaultPBKey); | |
| 600 | } | |
| 601 | ||
| 602 | /** | |
| 603 | * Try to build an default PBKey for convenience PB create method. | |
| 604 | * | |
| 605 | * @return PBKey or <code>null</code> if default key was not declared in | |
| 606 | * metadata | |
| 607 | */ | |
| 608 | private PBKey buildDefaultKey() | |
| 609 | { | |
| 610 | List descriptors = connectionRepository().getAllDescriptor(); | |
| 611 | JdbcConnectionDescriptor descriptor; | |
| 612 | PBKey result = null; | |
| 613 | for (Iterator iterator = descriptors.iterator(); iterator.hasNext();) | |
| 614 | { | |
| 615 | descriptor = (JdbcConnectionDescriptor) iterator.next(); | |
| 616 | if (descriptor.isDefaultConnection()) | |
| 617 | { | |
| 618 | if(result != null) | |
| 619 | { | |
| 620 | log.error("Found additional connection descriptor with enabled 'default-connection' " | |
| 621 | + descriptor.getPBKey() + ". This is NOT allowed. Will use the first found descriptor " + result | |
| 622 | + " as default connection"); | |
| 623 | } | |
| 624 | else | |
| 625 | { | |
| 626 | result = descriptor.getPBKey(); | |
| 627 | } | |
| 628 | } | |
| 629 | } | |
| 630 | ||
| 631 | if(result == null) | |
| 632 | { | |
| 633 | log.info("No 'default-connection' attribute set in jdbc-connection-descriptors," + | |
| 634 | " thus it's currently not possible to use 'defaultPersistenceBroker()' " + | |
| 635 | " convenience method to lookup PersistenceBroker instances. But it's possible"+ | |
| 636 | " to enable this at runtime using 'setDefaultKey' method."); | |
| 637 | } | |
| 638 | return result; | |
| 639 | } | |
| 640 | } |