001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.sql; 019 020import java.beans.Introspector; 021import java.beans.PropertyDescriptor; 022import java.beans.PropertyEditor; 023import java.beans.PropertyEditorManager; 024import java.util.AbstractMap; 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.HashMap; 028import java.util.LinkedList; 029import java.util.List; 030import java.util.Map; 031import java.util.concurrent.ConcurrentHashMap; 032import java.util.concurrent.ConcurrentMap; 033import java.util.concurrent.Executors; 034import java.util.concurrent.ThreadFactory; 035 036import javax.xml.bind.annotation.XmlAttribute; 037import javax.xml.bind.annotation.XmlElement; 038import javax.xml.bind.annotation.XmlID; 039import javax.xml.bind.annotation.XmlIDREF; 040import javax.xml.bind.annotation.XmlType; 041import javax.xml.bind.annotation.XmlValue; 042import javax.xml.bind.annotation.adapters.XmlAdapter; 043import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 044 045import net.sf.hajdbc.Database; 046import net.sf.hajdbc.DatabaseClusterConfiguration; 047import net.sf.hajdbc.DatabaseFactory; 048import net.sf.hajdbc.ExecutorServiceProvider; 049import net.sf.hajdbc.Identifiable; 050import net.sf.hajdbc.IdentifiableMatcher; 051import net.sf.hajdbc.Messages; 052import net.sf.hajdbc.SynchronizationStrategy; 053import net.sf.hajdbc.TransactionMode; 054import net.sf.hajdbc.balancer.BalancerFactory; 055import net.sf.hajdbc.cache.DatabaseMetaDataCacheFactory; 056import net.sf.hajdbc.codec.DecoderFactory; 057import net.sf.hajdbc.codec.MultiplexingDecoderFactory; 058import net.sf.hajdbc.dialect.DialectFactory; 059import net.sf.hajdbc.distributed.CommandDispatcherFactory; 060import net.sf.hajdbc.durability.DurabilityFactory; 061import net.sf.hajdbc.io.InputSinkProvider; 062import net.sf.hajdbc.lock.LockManagerFactory; 063import net.sf.hajdbc.management.DefaultMBeanRegistrar; 064import net.sf.hajdbc.management.MBeanRegistrar; 065import net.sf.hajdbc.state.StateManagerFactory; 066import net.sf.hajdbc.tx.SimpleTransactionIdentifierFactory; 067import net.sf.hajdbc.tx.TransactionIdentifierFactory; 068import net.sf.hajdbc.tx.UUIDTransactionIdentifierFactory; 069import net.sf.hajdbc.util.ServiceLoaders; 070import net.sf.hajdbc.util.concurrent.cron.CronExpression; 071 072/** 073 * @author Paul Ferraro 074 */ 075@XmlType(propOrder = { "commandDispatcherFactoryDescriptor", "synchronizationStrategyDescriptors", "stateManagerFactoryDescriptor", "lockManagerFactoryDescriptor" }) 076public abstract class AbstractDatabaseClusterConfiguration<Z, D extends Database<Z>> implements DatabaseClusterConfiguration<Z, D> 077{ 078 private static final long serialVersionUID = -2808296483725374829L; 079 080 private CommandDispatcherFactory dispatcherFactory; 081 private Map<String, SynchronizationStrategy> synchronizationStrategies = new HashMap<String, SynchronizationStrategy>(); 082 private StateManagerFactory stateManagerFactory = ServiceLoaders.findRequiredService(StateManagerFactory.class); 083 private LockManagerFactory lockManagerFactory = ServiceLoaders.findRequiredService(LockManagerFactory.class); 084 085 protected abstract NestedConfiguration<Z, D> getNestedConfiguration(); 086 087 @Override 088 public DatabaseFactory<Z, D> getDatabaseFactory() 089 { 090 return this.getNestedConfiguration().getDatabaseFactory(); 091 } 092 093 @XmlElement(name = "distributable") 094 private CommandDispatcherFactoryDescriptor getCommandDispatcherFactoryDescriptor() throws Exception 095 { 096 return (this.dispatcherFactory != null) ? new CommandDispatcherFactoryDescriptorAdapter().marshal(this.dispatcherFactory) : null; 097 } 098 099 @SuppressWarnings("unused") 100 private void setCommandDispatcherFactoryDescriptor(CommandDispatcherFactoryDescriptor descriptor) throws Exception 101 { 102 this.dispatcherFactory = (descriptor != null) ? new CommandDispatcherFactoryDescriptorAdapter().unmarshal(descriptor) : null; 103 } 104 105 @XmlElement(name = "sync") 106 private SynchronizationStrategyDescriptor[] getSynchronizationStrategyDescriptors() throws Exception 107 { 108 List<SynchronizationStrategyDescriptor> results = new ArrayList<SynchronizationStrategyDescriptor>(this.synchronizationStrategies.size()); 109 SynchronizationStrategyDescriptorAdapter adapter = new SynchronizationStrategyDescriptorAdapter(); 110 111 for (Map.Entry<String, SynchronizationStrategy> entry: this.synchronizationStrategies.entrySet()) 112 { 113 SynchronizationStrategyDescriptor result = adapter.marshal(entry.getValue()); 114 115 result.setId(entry.getKey()); 116 117 results.add(result); 118 } 119 120 return results.toArray(new SynchronizationStrategyDescriptor[results.size()]); 121 } 122 123 @SuppressWarnings("unused") 124 private void setSynchronizationStrategyDescriptors(SynchronizationStrategyDescriptor[] entries) throws Exception 125 { 126 SynchronizationStrategyDescriptorAdapter adapter = new SynchronizationStrategyDescriptorAdapter(); 127 128 for (SynchronizationStrategyDescriptor entry: entries) 129 { 130 SynchronizationStrategy strategy = adapter.unmarshal(entry); 131 132 this.synchronizationStrategies.put(entry.getId(), strategy); 133 } 134 } 135 136 @XmlElement(name = "state") 137 private StateManagerFactoryDescriptor getStateManagerFactoryDescriptor() throws Exception 138 { 139 return new StateManagerFactoryDescriptorAdapter().marshal(this.stateManagerFactory); 140 } 141 142 @SuppressWarnings("unused") 143 private void setStateManagerFactoryDescriptor(StateManagerFactoryDescriptor descriptor) throws Exception 144 { 145 this.stateManagerFactory = new StateManagerFactoryDescriptorAdapter().unmarshal(descriptor); 146 } 147 148 @XmlElement(name = "lock") 149 private LockManagerFactoryDescriptor getLockManagerFactoryDescriptor() throws Exception 150 { 151 return new LockManagerFactoryDescriptorAdapter().marshal(this.lockManagerFactory); 152 } 153 154 @SuppressWarnings("unused") 155 private void setLockManagerFactoryDescriptor(LockManagerFactoryDescriptor descriptor) throws Exception 156 { 157 this.lockManagerFactory = new LockManagerFactoryDescriptorAdapter().unmarshal(descriptor); 158 } 159 160 /** 161 * {@inheritDoc} 162 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getAutoActivationExpression() 163 */ 164 @Override 165 public CronExpression getAutoActivationExpression() 166 { 167 return this.getNestedConfiguration().getAutoActivationExpression(); 168 } 169 170 public void setAutoActivationExpression(CronExpression expression) 171 { 172 this.getNestedConfiguration().setAutoActivationExpression(expression); 173 } 174 175 /** 176 * {@inheritDoc} 177 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getBalancerFactory() 178 */ 179 @Override 180 public BalancerFactory getBalancerFactory() 181 { 182 return this.getNestedConfiguration().getBalancerFactory(); 183 } 184 185 public void setBalancerFactory(BalancerFactory factory) 186 { 187 this.getNestedConfiguration().setBalancerFactory(factory); 188 } 189 190 /** 191 * {@inheritDoc} 192 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDispatcherFactory() 193 */ 194 @Override 195 public CommandDispatcherFactory getDispatcherFactory() 196 { 197 return this.dispatcherFactory; 198 } 199 200 public void setDispatcherFactory(CommandDispatcherFactory factory) 201 { 202 this.dispatcherFactory = factory; 203 } 204 205 /** 206 * {@inheritDoc} 207 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDatabaseMap() 208 */ 209 @Override 210 public ConcurrentMap<String, D> getDatabaseMap() 211 { 212 return this.getNestedConfiguration().getDatabaseMap(); 213 } 214 215 public void setDatabases(Collection<D> databases) 216 { 217 Map<String, D> map = this.getDatabaseMap(); 218 219 for (D database: databases) 220 { 221 map.put(database.getId(), database); 222 } 223 } 224 225 /** 226 * {@inheritDoc} 227 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDatabaseMetaDataCacheFactory() 228 */ 229 @Override 230 public DatabaseMetaDataCacheFactory getDatabaseMetaDataCacheFactory() 231 { 232 return this.getNestedConfiguration().getDatabaseMetaDataCacheFactory(); 233 } 234 235 public void setDatabaseMetaDataCacheFactory(DatabaseMetaDataCacheFactory factory) 236 { 237 this.getNestedConfiguration().setDatabaseMetaDataCacheFactory(factory); 238 } 239 240 /** 241 * {@inheritDoc} 242 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDefaultSynchronizationStrategy() 243 */ 244 @Override 245 public String getDefaultSynchronizationStrategy() 246 { 247 return this.getNestedConfiguration().getDefaultSynchronizationStrategy(); 248 } 249 250 public void setDefaultSynchronizationStrategy(String strategy) 251 { 252 this.getNestedConfiguration().setDefaultSynchronizationStrategy(strategy); 253 } 254 255 /** 256 * {@inheritDoc} 257 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDialectFactory() 258 */ 259 @Override 260 public DialectFactory getDialectFactory() 261 { 262 return this.getNestedConfiguration().getDialectFactory(); 263 } 264 265 public void setDialectFactory(DialectFactory factory) 266 { 267 this.getNestedConfiguration().setDialectFactory(factory); 268 } 269 270 /** 271 * {@inheritDoc} 272 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDurabilityFactory() 273 */ 274 @Override 275 public DurabilityFactory getDurabilityFactory() 276 { 277 return this.getNestedConfiguration().getDurabilityFactory(); 278 } 279 280 public void setDurabilityFactory(DurabilityFactory factory) 281 { 282 this.getNestedConfiguration().setDurabilityFactory(factory); 283 } 284 285 /** 286 * {@inheritDoc} 287 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getExecutorProvider() 288 */ 289 @Override 290 public ExecutorServiceProvider getExecutorProvider() 291 { 292 return this.getNestedConfiguration().getExecutorProvider(); 293 } 294 295 public void setExecutorProvider(ExecutorServiceProvider provider) 296 { 297 this.getNestedConfiguration().setExecutorProvider(provider); 298 } 299 300 /** 301 * {@inheritDoc} 302 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getThreadFactory() 303 */ 304 @Override 305 public ThreadFactory getThreadFactory() 306 { 307 return this.getNestedConfiguration().getThreadFactory(); 308 } 309 310 public void setThreadFactory(ThreadFactory factory) 311 { 312 this.getNestedConfiguration().setThreadFactory(factory); 313 } 314 315 /** 316 * {@inheritDoc} 317 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getDecoderFactory() 318 */ 319 @Override 320 public DecoderFactory getDecoderFactory() 321 { 322 return this.getNestedConfiguration().getDecoderFactory(); 323 } 324 325 public void setCodecFactory(DecoderFactory factory) 326 { 327 this.getNestedConfiguration().setDecoderFactory(factory); 328 } 329 330 /** 331 * {@inheritDoc} 332 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getFailureDetectionExpression() 333 */ 334 @Override 335 public CronExpression getFailureDetectionExpression() 336 { 337 return this.getNestedConfiguration().getFailureDetectionExpression(); 338 } 339 340 public void setFailureDetectionExpression(CronExpression expression) 341 { 342 this.getNestedConfiguration().setFailureDetectionExpression(expression); 343 } 344 345 /** 346 * {@inheritDoc} 347 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getStateManagerFactory() 348 */ 349 @Override 350 public StateManagerFactory getStateManagerFactory() 351 { 352 return this.stateManagerFactory; 353 } 354 355 public void setStateManagerFactory(StateManagerFactory factory) 356 { 357 this.stateManagerFactory = factory; 358 } 359 360 @Override 361 public LockManagerFactory getLockManagerFactory() 362 { 363 return this.lockManagerFactory; 364 } 365 366 public void setLockManagerFactory(LockManagerFactory factory) 367 { 368 this.lockManagerFactory = factory; 369 } 370 371 /** 372 * {@inheritDoc} 373 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getSynchronizationStrategyMap() 374 */ 375 @Override 376 public Map<String, SynchronizationStrategy> getSynchronizationStrategyMap() 377 { 378 return this.synchronizationStrategies; 379 } 380 381 public void setSynchronizationStrategyMap(Map<String, SynchronizationStrategy> strategies) 382 { 383 this.synchronizationStrategies = strategies; 384 } 385 386 /** 387 * {@inheritDoc} 388 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getTransactionMode() 389 */ 390 @Override 391 public TransactionMode getTransactionMode() 392 { 393 return this.getNestedConfiguration().getTransactionMode(); 394 } 395 396 public void setTransactionMode(TransactionMode mode) 397 { 398 this.getNestedConfiguration().setTransactionMode(mode); 399 } 400 401 @Override 402 public InputSinkProvider getInputSinkProvider() 403 { 404 return this.getNestedConfiguration().getInputSinkProvider(); 405 } 406 407 public void setInputSinkFactoryProvider(InputSinkProvider provider) 408 { 409 this.getNestedConfiguration().setSinkSourceProvider(provider); 410 } 411 412 /** 413 * {@inheritDoc} 414 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentDateEvaluationEnabled() 415 */ 416 @Override 417 public boolean isCurrentDateEvaluationEnabled() 418 { 419 return this.getNestedConfiguration().isCurrentDateEvaluationEnabled(); 420 } 421 422 public void setCurrentDateEvaluationEnabled(boolean enabled) 423 { 424 this.getNestedConfiguration().setCurrentDateEvaluationEnabled(enabled); 425 } 426 427 /** 428 * {@inheritDoc} 429 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentTimeEvaluationEnabled() 430 */ 431 @Override 432 public boolean isCurrentTimeEvaluationEnabled() 433 { 434 return this.getNestedConfiguration().isCurrentTimeEvaluationEnabled(); 435 } 436 437 public void setCurrentTimeEvaluationEnabled(boolean enabled) 438 { 439 this.getNestedConfiguration().setCurrentTimeEvaluationEnabled(enabled); 440 } 441 442 /** 443 * {@inheritDoc} 444 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isCurrentTimestampEvaluationEnabled() 445 */ 446 @Override 447 public boolean isCurrentTimestampEvaluationEnabled() 448 { 449 return this.getNestedConfiguration().isCurrentTimestampEvaluationEnabled(); 450 } 451 452 public void setCurrentTimestampEvaluationEnabled(boolean enabled) 453 { 454 this.getNestedConfiguration().setCurrentTimestampEvaluationEnabled(enabled); 455 } 456 457 /** 458 * {@inheritDoc} 459 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isIdentityColumnDetectionEnabled() 460 */ 461 @Override 462 public boolean isIdentityColumnDetectionEnabled() 463 { 464 return this.getNestedConfiguration().isIdentityColumnDetectionEnabled(); 465 } 466 467 public void setIdentityColumnDetectionEnabled(boolean enabled) 468 { 469 this.getNestedConfiguration().setIdentityColumnDetectionEnabled(enabled); 470 } 471 472 /** 473 * {@inheritDoc} 474 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isRandEvaluationEnabled() 475 */ 476 @Override 477 public boolean isRandEvaluationEnabled() 478 { 479 return this.getNestedConfiguration().isRandEvaluationEnabled(); 480 } 481 482 public void setRandEvaluationEnabled(boolean enabled) 483 { 484 this.getNestedConfiguration().setRandEvaluationEnabled(enabled); 485 } 486 487 /** 488 * {@inheritDoc} 489 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isSequenceDetectionEnabled() 490 */ 491 @Override 492 public boolean isSequenceDetectionEnabled() 493 { 494 return this.getNestedConfiguration().isSequenceDetectionEnabled(); 495 } 496 497 public void setSequenceDetectionEnabled(boolean enabled) 498 { 499 this.getNestedConfiguration().setSequenceDetectionEnabled(enabled); 500 } 501 502 static Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> findDescriptors(Class<?> targetClass) throws Exception 503 { 504 Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> map = new HashMap<String, Map.Entry<PropertyDescriptor, PropertyEditor>>(); 505 506 for (PropertyDescriptor descriptor: Introspector.getBeanInfo(targetClass).getPropertyDescriptors()) 507 { 508 if ((descriptor.getReadMethod() != null) && (descriptor.getWriteMethod() != null)) 509 { 510 PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); 511 512 if (editor != null) 513 { 514 map.put(descriptor.getName(), new AbstractMap.SimpleImmutableEntry<PropertyDescriptor, PropertyEditor>(descriptor, editor)); 515 } 516 } 517 } 518 519 return map; 520 } 521 522 /** 523 * {@inheritDoc} 524 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getMBeanRegistrar() 525 */ 526 @Override 527 public MBeanRegistrar<Z, D> getMBeanRegistrar() 528 { 529 return this.getNestedConfiguration().getMBeanRegistrar(); 530 } 531 532 public void setMBeanRegistrar(MBeanRegistrar<Z, D> registrar) 533 { 534 this.getNestedConfiguration().setMBeanRegistrar(registrar); 535 } 536 537 /** 538 * {@inheritDoc} 539 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isEmptyClusterAllowed() 540 */ 541 @Override 542 public boolean isEmptyClusterAllowed() 543 { 544 return this.getNestedConfiguration().isEmptyClusterAllowed(); 545 } 546 547 public void setEmptyClusterAllowed(boolean emptyClusterAllowed) 548 { 549 this.getNestedConfiguration().setEmptyClusterAllowed(emptyClusterAllowed); 550 } 551 552 /** 553 * {@inheritDoc} 554 * @see net.sf.hajdbc.DatabaseClusterConfiguration#getTransactionIdentifierFactory() 555 */ 556 @Override 557 public TransactionIdentifierFactory<? extends Object> getTransactionIdentifierFactory() 558 { 559 return (this.dispatcherFactory != null) ? new UUIDTransactionIdentifierFactory() : new SimpleTransactionIdentifierFactory(); 560 } 561 562 @XmlType(name = "abstractNestedConfiguration") 563 protected static abstract class NestedConfiguration<Z, D extends Database<Z>> implements DatabaseClusterConfiguration<Z, D>, DatabaseFactory<Z, D> 564 { 565 private static final long serialVersionUID = -5674156614205147546L; 566 567 @XmlJavaTypeAdapter(BalancerFactoryAdapter.class) 568 @XmlAttribute(name = "balancer") 569 private BalancerFactory balancerFactory = ServiceLoaders.findService(BalancerFactory.class); 570 571 @XmlJavaTypeAdapter(DatabaseMetaDataCacheFactoryAdapter.class) 572 @XmlAttribute(name = "meta-data-cache") 573 private DatabaseMetaDataCacheFactory databaseMetaDataCacheFactory = ServiceLoaders.findService(DatabaseMetaDataCacheFactory.class); 574 575 @XmlJavaTypeAdapter(DialectFactoryAdapter.class) 576 @XmlAttribute(name = "dialect") 577 private DialectFactory dialectFactory = ServiceLoaders.findService(DialectFactory.class); 578 579 @XmlJavaTypeAdapter(DurabilityFactoryAdapter.class) 580 @XmlAttribute(name = "durability") 581 private DurabilityFactory durabilityFactory = ServiceLoaders.findService(DurabilityFactory.class); 582 583 @XmlJavaTypeAdapter(SinkSourceProviderAdapter.class) 584 @XmlAttribute(name = "input-sink") 585 private InputSinkProvider sinkSourceProvider = ServiceLoaders.findService(InputSinkProvider.class); 586 587 private ExecutorServiceProvider executorProvider = new DefaultExecutorServiceProvider(); 588 private ThreadFactory threadFactory = Executors.defaultThreadFactory(); 589 private DecoderFactory decoderFactory = new MultiplexingDecoderFactory(); 590 private MBeanRegistrar<Z, D> registrar = new DefaultMBeanRegistrar<Z, D>(); 591 592 @XmlJavaTypeAdapter(TransactionModeAdapter.class) 593 @XmlAttribute(name = "transaction-mode") 594 private TransactionMode transactionMode = TransactionModeEnum.SERIAL; 595 596 @XmlJavaTypeAdapter(CronExpressionAdapter.class) 597 @XmlAttribute(name = "auto-activate-schedule") 598 private CronExpression autoActivationExpression; 599 @XmlJavaTypeAdapter(CronExpressionAdapter.class) 600 @XmlAttribute(name = "failure-detect-schedule") 601 private CronExpression failureDetectionExpression; 602 603 @XmlAttribute(name = "eval-current-date") 604 private Boolean currentDateEvaluationEnabled = false; 605 @XmlAttribute(name = "eval-current-time") 606 private Boolean currentTimeEvaluationEnabled = false; 607 @XmlAttribute(name = "eval-current-timestamp") 608 private Boolean currentTimestampEvaluationEnabled = false; 609 @XmlAttribute(name = "eval-rand") 610 private Boolean randEvaluationEnabled = false; 611 612 @XmlAttribute(name = "detect-identity-columns") 613 private Boolean identityColumnDetectionEnabled = false; 614 @XmlAttribute(name = "detect-sequences") 615 private Boolean sequenceDetectionEnabled = false; 616 617 @XmlAttribute(name = "allow-empty-cluster") 618 private Boolean emptyClusterAllowed = false; 619 620 private String defaultSynchronizationStrategy; 621 622 private ConcurrentMap<String, D> databases = new ConcurrentHashMap<String, D>(); 623 624 @Override 625 public DatabaseFactory<Z, D> getDatabaseFactory() 626 { 627 return this; 628 } 629 630 @XmlIDREF 631 @XmlAttribute(name = "default-sync", required = true) 632 private SynchronizationStrategyDescriptor getDefaultSynchronizationStrategyDescriptor() 633 { 634 SynchronizationStrategyDescriptor descriptor = new SynchronizationStrategyDescriptor(); 635 descriptor.setId(this.defaultSynchronizationStrategy); 636 return descriptor; 637 } 638 639 @SuppressWarnings("unused") 640 private void setDefaultSynchronizationStrategyDescriptor(SynchronizationStrategyDescriptor descriptor) 641 { 642 this.defaultSynchronizationStrategy = descriptor.getId(); 643 } 644 645 @Override 646 public ConcurrentMap<String, D> getDatabaseMap() 647 { 648 return this.databases; 649 } 650 651 @Override 652 public CronExpression getAutoActivationExpression() 653 { 654 return this.autoActivationExpression; 655 } 656 657 void setAutoActivationExpression(CronExpression expression) 658 { 659 this.autoActivationExpression = expression; 660 } 661 662 @Override 663 public BalancerFactory getBalancerFactory() 664 { 665 return this.balancerFactory; 666 } 667 668 void setBalancerFactory(BalancerFactory factory) 669 { 670 this.balancerFactory = factory; 671 } 672 673 @Override 674 public CommandDispatcherFactory getDispatcherFactory() 675 { 676 throw new IllegalStateException(); 677 } 678 679 @Override 680 public DatabaseMetaDataCacheFactory getDatabaseMetaDataCacheFactory() 681 { 682 return this.databaseMetaDataCacheFactory; 683 } 684 685 void setDatabaseMetaDataCacheFactory(DatabaseMetaDataCacheFactory factory) 686 { 687 this.databaseMetaDataCacheFactory = factory; 688 } 689 690 @Override 691 public String getDefaultSynchronizationStrategy() 692 { 693 return this.defaultSynchronizationStrategy; 694 } 695 696 void setDefaultSynchronizationStrategy(String strategy) 697 { 698 this.defaultSynchronizationStrategy = strategy; 699 } 700 701 @Override 702 public DialectFactory getDialectFactory() 703 { 704 return this.dialectFactory; 705 } 706 707 void setDialectFactory(DialectFactory factory) 708 { 709 this.dialectFactory = factory; 710 } 711 712 @Override 713 public DurabilityFactory getDurabilityFactory() 714 { 715 return this.durabilityFactory; 716 } 717 718 void setDurabilityFactory(DurabilityFactory factory) 719 { 720 this.durabilityFactory = factory; 721 } 722 723 @Override 724 public ExecutorServiceProvider getExecutorProvider() 725 { 726 return this.executorProvider; 727 } 728 729 void setExecutorProvider(ExecutorServiceProvider provider) 730 { 731 this.executorProvider = provider; 732 } 733 734 @Override 735 public ThreadFactory getThreadFactory() 736 { 737 return this.threadFactory; 738 } 739 740 void setThreadFactory(ThreadFactory factory) 741 { 742 this.threadFactory = factory; 743 } 744 745 @Override 746 public DecoderFactory getDecoderFactory() 747 { 748 return this.decoderFactory; 749 } 750 751 void setDecoderFactory(DecoderFactory factory) 752 { 753 this.decoderFactory = factory; 754 } 755 756 @Override 757 public MBeanRegistrar<Z, D> getMBeanRegistrar() 758 { 759 return this.registrar; 760 } 761 762 void setMBeanRegistrar(MBeanRegistrar<Z, D> registrar) 763 { 764 this.registrar = registrar; 765 } 766 767 @Override 768 public CronExpression getFailureDetectionExpression() 769 { 770 return this.failureDetectionExpression; 771 } 772 773 void setFailureDetectionExpression(CronExpression expression) 774 { 775 this.failureDetectionExpression = expression; 776 } 777 778 @Override 779 public StateManagerFactory getStateManagerFactory() 780 { 781 throw new IllegalStateException(); 782 } 783 784 @Override 785 public LockManagerFactory getLockManagerFactory() 786 { 787 throw new IllegalStateException(); 788 } 789 790 @Override 791 public Map<String, SynchronizationStrategy> getSynchronizationStrategyMap() 792 { 793 throw new IllegalStateException(); 794 } 795 796 @Override 797 public TransactionMode getTransactionMode() 798 { 799 return this.transactionMode; 800 } 801 802 void setTransactionMode(TransactionMode mode) 803 { 804 this.transactionMode = mode; 805 } 806 807 @Override 808 public InputSinkProvider getInputSinkProvider() 809 { 810 return this.sinkSourceProvider; 811 } 812 813 void setSinkSourceProvider(InputSinkProvider provider) 814 { 815 this.sinkSourceProvider = provider; 816 } 817 818 @Override 819 public boolean isCurrentDateEvaluationEnabled() 820 { 821 return this.currentDateEvaluationEnabled; 822 } 823 824 void setCurrentDateEvaluationEnabled(boolean enabled) 825 { 826 this.currentDateEvaluationEnabled = enabled; 827 } 828 829 @Override 830 public boolean isCurrentTimeEvaluationEnabled() 831 { 832 return this.currentTimeEvaluationEnabled; 833 } 834 835 void setCurrentTimeEvaluationEnabled(boolean enabled) 836 { 837 this.currentTimeEvaluationEnabled = enabled; 838 } 839 840 @Override 841 public boolean isCurrentTimestampEvaluationEnabled() 842 { 843 return this.currentTimestampEvaluationEnabled; 844 } 845 846 void setCurrentTimestampEvaluationEnabled(boolean enabled) 847 { 848 this.currentTimestampEvaluationEnabled = enabled; 849 } 850 851 @Override 852 public boolean isIdentityColumnDetectionEnabled() 853 { 854 return this.identityColumnDetectionEnabled; 855 } 856 857 void setIdentityColumnDetectionEnabled(boolean enabled) 858 { 859 this.identityColumnDetectionEnabled = enabled; 860 } 861 862 @Override 863 public boolean isRandEvaluationEnabled() 864 { 865 return this.randEvaluationEnabled; 866 } 867 868 void setRandEvaluationEnabled(boolean enabled) 869 { 870 this.randEvaluationEnabled = enabled; 871 } 872 873 @Override 874 public boolean isSequenceDetectionEnabled() 875 { 876 return this.sequenceDetectionEnabled; 877 } 878 879 void setSequenceDetectionEnabled(boolean enabled) 880 { 881 this.sequenceDetectionEnabled = enabled; 882 } 883 884 @Override 885 public TransactionIdentifierFactory<? extends Object> getTransactionIdentifierFactory() 886 { 887 throw new IllegalStateException(); 888 } 889 890 /* (non-Javadoc) 891 * @see net.sf.hajdbc.DatabaseClusterConfiguration#isEmptyClusterAllowed() 892 */ 893 @Override 894 public boolean isEmptyClusterAllowed() 895 { 896 return this.emptyClusterAllowed; 897 } 898 899 void setEmptyClusterAllowed(boolean emptyClusterAllowed) 900 { 901 this.emptyClusterAllowed = emptyClusterAllowed; 902 } 903 } 904 905 static class IdentifiableServiceAdapter<T extends Identifiable> extends XmlAdapter<String, T> 906 { 907 private final Class<T> serviceClass; 908 909 IdentifiableServiceAdapter(Class<T> serviceClass) 910 { 911 this.serviceClass = serviceClass; 912 } 913 914 @Override 915 public T unmarshal(final String value) 916 { 917 return ServiceLoaders.findRequiredService(new IdentifiableMatcher<T>(value), this.serviceClass); 918 } 919 920 @Override 921 public String marshal(T service) 922 { 923 return service.getId(); 924 } 925 } 926 927 static class BalancerFactoryAdapter extends IdentifiableServiceAdapter<BalancerFactory> 928 { 929 BalancerFactoryAdapter() 930 { 931 super(BalancerFactory.class); 932 } 933 } 934 935 static class DatabaseMetaDataCacheFactoryAdapter extends IdentifiableServiceAdapter<DatabaseMetaDataCacheFactory> 936 { 937 DatabaseMetaDataCacheFactoryAdapter() 938 { 939 super(DatabaseMetaDataCacheFactory.class); 940 } 941 } 942 943 static class DurabilityFactoryAdapter extends IdentifiableServiceAdapter<DurabilityFactory> 944 { 945 DurabilityFactoryAdapter() 946 { 947 super(DurabilityFactory.class); 948 } 949 } 950 951 static class TransactionModeAdapter extends EnumAdapter<TransactionMode, TransactionModeEnum> 952 { 953 @Override 954 protected Class<TransactionModeEnum> getTargetClass() 955 { 956 return TransactionModeEnum.class; 957 } 958 } 959 960 static abstract class EnumAdapter<I, E extends I> extends XmlAdapter<E, I> 961 { 962 @Override 963 public I unmarshal(E enumerated) 964 { 965 return enumerated; 966 } 967 968 @Override 969 public E marshal(I object) 970 { 971 return this.getTargetClass().cast(object); 972 } 973 974 protected abstract Class<E> getTargetClass(); 975 } 976 977 static class DialectFactoryAdapter extends IdentifiableServiceAdapter<DialectFactory> 978 { 979 DialectFactoryAdapter() 980 { 981 super(DialectFactory.class); 982 } 983 } 984 985 static class SinkSourceProviderAdapter extends IdentifiableServiceAdapter<InputSinkProvider> 986 { 987 SinkSourceProviderAdapter() 988 { 989 super(InputSinkProvider.class); 990 } 991 } 992 993 static class CronExpressionAdapter extends XmlAdapter<String, CronExpression> 994 { 995 @Override 996 public String marshal(CronExpression expression) 997 { 998 return (expression != null) ? expression.getCronExpression() : null; 999 } 1000 1001 @Override 1002 public CronExpression unmarshal(String value) throws Exception 1003 { 1004 return (value != null) ? new CronExpression(value) : null; 1005 } 1006 } 1007 1008 @XmlType 1009 static class CommandDispatcherFactoryDescriptor extends IdentifiableServiceDescriptor 1010 { 1011 @XmlAttribute(name = "id", required = false) 1012 private String id = "jgroups"; 1013 1014 @Override 1015 public String getId() 1016 { 1017 return this.id; 1018 } 1019 1020 @Override 1021 public void setId(String id) 1022 { 1023 this.id = id; 1024 } 1025 } 1026 1027 static class CommandDispatcherFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter<CommandDispatcherFactory, CommandDispatcherFactoryDescriptor> 1028 { 1029 CommandDispatcherFactoryDescriptorAdapter() 1030 { 1031 super(CommandDispatcherFactory.class, CommandDispatcherFactoryDescriptor.class); 1032 } 1033 } 1034 1035 @XmlType 1036 static class SynchronizationStrategyDescriptor extends IdentifiableServiceDescriptor 1037 { 1038 @XmlID 1039 @XmlAttribute(name = "id", required = true) 1040 private String id; 1041 1042 @Override 1043 public String getId() 1044 { 1045 return this.id; 1046 } 1047 1048 @Override 1049 public void setId(String id) 1050 { 1051 this.id = id; 1052 } 1053 } 1054 1055 static class SynchronizationStrategyDescriptorAdapter extends IdentifiableServiceDescriptorAdapter<SynchronizationStrategy, SynchronizationStrategyDescriptor> 1056 { 1057 SynchronizationStrategyDescriptorAdapter() 1058 { 1059 super(SynchronizationStrategy.class, SynchronizationStrategyDescriptor.class); 1060 } 1061 } 1062 1063 @XmlType 1064 static class StateManagerFactoryDescriptor extends IdentifiableServiceDescriptor 1065 { 1066 @XmlAttribute(name = "id", required = true) 1067 private String id; 1068 1069 @Override 1070 public String getId() 1071 { 1072 return this.id; 1073 } 1074 1075 @Override 1076 public void setId(String id) 1077 { 1078 this.id = id; 1079 } 1080 } 1081 1082 static class StateManagerFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter<StateManagerFactory, StateManagerFactoryDescriptor> 1083 { 1084 StateManagerFactoryDescriptorAdapter() 1085 { 1086 super(StateManagerFactory.class, StateManagerFactoryDescriptor.class); 1087 } 1088 } 1089 1090 @XmlType 1091 static class LockManagerFactoryDescriptor extends IdentifiableServiceDescriptor 1092 { 1093 @XmlAttribute(name = "id", required = true) 1094 private String id; 1095 1096 @Override 1097 public String getId() 1098 { 1099 return this.id; 1100 } 1101 1102 @Override 1103 public void setId(String id) 1104 { 1105 this.id = id; 1106 } 1107 } 1108 1109 static class LockManagerFactoryDescriptorAdapter extends IdentifiableServiceDescriptorAdapter<LockManagerFactory, LockManagerFactoryDescriptor> 1110 { 1111 LockManagerFactoryDescriptorAdapter() 1112 { 1113 super(LockManagerFactory.class, LockManagerFactoryDescriptor.class); 1114 } 1115 } 1116 1117 static abstract class IdentifiableServiceDescriptor implements Identifiable 1118 { 1119 @XmlElement(name = "property") 1120 private List<Property> properties; 1121 1122 public List<Property> getProperties() 1123 { 1124 return this.properties; 1125 } 1126 1127 public void setProperties(List<Property> properties) 1128 { 1129 this.properties = properties; 1130 } 1131 1132 public abstract void setId(String id); 1133 } 1134 1135 static class IdentifiableServiceDescriptorAdapter<T extends Identifiable, D extends IdentifiableServiceDescriptor> extends XmlAdapter<D, T> 1136 { 1137 private final Class<T> serviceClass; 1138 private final Class<D> descriptorClass; 1139 1140 IdentifiableServiceDescriptorAdapter(Class<T> serviceClass, Class<D> descriptorClass) 1141 { 1142 this.serviceClass = serviceClass; 1143 this.descriptorClass = descriptorClass; 1144 } 1145 1146 @Override 1147 public D marshal(T object) throws Exception 1148 { 1149 D result = this.descriptorClass.newInstance(); 1150 List<Property> properties = new LinkedList<Property>(); 1151 1152 result.setId(object.getId()); 1153 result.setProperties(properties); 1154 1155 for (Map.Entry<PropertyDescriptor, PropertyEditor> entry: findDescriptors(object.getClass()).values()) 1156 { 1157 PropertyDescriptor descriptor = entry.getKey(); 1158 PropertyEditor editor = entry.getValue(); 1159 1160 Object value = descriptor.getReadMethod().invoke(object); 1161 if (value != null) 1162 { 1163 editor.setValue(value); 1164 1165 Property property = new Property(); 1166 property.setName(descriptor.getName()); 1167 property.setValue(editor.getAsText()); 1168 1169 properties.add(property); 1170 } 1171 } 1172 1173 return result; 1174 } 1175 1176 @Override 1177 public T unmarshal(D target) throws Exception 1178 { 1179 T result = ServiceLoaders.findRequiredService(new IdentifiableMatcher<T>(target.getId()), this.serviceClass); 1180 List<Property> properties = target.getProperties(); 1181 1182 if (properties != null) 1183 { 1184 Map<String, Map.Entry<PropertyDescriptor, PropertyEditor>> descriptors = findDescriptors(result.getClass()); 1185 1186 for (Property property: properties) 1187 { 1188 String name = property.getName(); 1189 Map.Entry<PropertyDescriptor, PropertyEditor> entry = descriptors.get(name); 1190 1191 if (entry == null) 1192 { 1193 throw new IllegalArgumentException(Messages.INVALID_PROPERTY.getMessage(name, result.getClass().getName())); 1194 } 1195 1196 PropertyDescriptor descriptor = entry.getKey(); 1197 PropertyEditor editor = entry.getValue(); 1198 1199 String textValue = property.getValue(); 1200 1201 try 1202 { 1203 editor.setAsText(textValue); 1204 } 1205 catch (Exception e) 1206 { 1207 throw new IllegalArgumentException(Messages.INVALID_PROPERTY_VALUE.getMessage(textValue, name, result.getClass().getName())); 1208 } 1209 descriptor.getWriteMethod().invoke(result, editor.getValue()); 1210 } 1211 } 1212 return result; 1213 } 1214 } 1215 1216 @XmlType 1217 protected static class Property 1218 { 1219 @XmlAttribute(required = true) 1220 private String name; 1221 @XmlValue 1222 private String value; 1223 1224 public String getName() 1225 { 1226 return this.name; 1227 } 1228 1229 public void setName(String name) 1230 { 1231 this.name = name; 1232 } 1233 1234 public String getValue() 1235 { 1236 return this.value; 1237 } 1238 1239 public void setValue(String value) 1240 { 1241 this.value = value; 1242 } 1243 } 1244}