Browse Source

KERNEL-753 增加对LDAP的支持,将Spring的LDAP模块编译到third中

research/11.0
andrew.asa 5 years ago
parent
commit
145bd139ed
  1. BIN
      fine-spring/lib/connector-api-1.5.jar
  2. BIN
      fine-spring/lib/javax.transaction-api-1.2.jar
  3. 685
      fine-spring/resources/META-INF/com/fr/third/springframework/ldap/config/spring-ldap-2.0.xsd
  4. 198
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-2.0.xsd
  5. 244
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-2.5.xsd
  6. 244
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.0.xsd
  7. 247
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.1.xsd
  8. 247
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.2.xsd
  9. 247
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-4.0.xsd
  10. BIN
      fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx.gif
  11. 3
      fine-spring/resources/META-INF/fine-spring.handlers
  12. 11
      fine-spring/resources/META-INF/fine-spring.schemas
  13. 6
      fine-spring/resources/META-INF/fine-spring.tooling
  14. 212
      fine-spring/src/com/fr/third/springframework/LdapDataEntry.java
  15. 45
      fine-spring/src/com/fr/third/springframework/dao/CannotAcquireLockException.java
  16. 45
      fine-spring/src/com/fr/third/springframework/dao/CannotSerializeTransactionException.java
  17. 45
      fine-spring/src/com/fr/third/springframework/dao/CleanupFailureDataAccessException.java
  18. 52
      fine-spring/src/com/fr/third/springframework/dao/ConcurrencyFailureException.java
  19. 59
      fine-spring/src/com/fr/third/springframework/dao/DataAccessException.java
  20. 46
      fine-spring/src/com/fr/third/springframework/dao/DataAccessResourceFailureException.java
  21. 47
      fine-spring/src/com/fr/third/springframework/dao/DataIntegrityViolationException.java
  22. 47
      fine-spring/src/com/fr/third/springframework/dao/DataRetrievalFailureException.java
  23. 37
      fine-spring/src/com/fr/third/springframework/dao/DeadlockLoserDataAccessException.java
  24. 47
      fine-spring/src/com/fr/third/springframework/dao/DuplicateKeyException.java
  25. 57
      fine-spring/src/com/fr/third/springframework/dao/EmptyResultDataAccessException.java
  26. 120
      fine-spring/src/com/fr/third/springframework/dao/IncorrectResultSizeDataAccessException.java
  27. 57
      fine-spring/src/com/fr/third/springframework/dao/IncorrectUpdateSemanticsDataAccessException.java
  28. 48
      fine-spring/src/com/fr/third/springframework/dao/InvalidDataAccessApiUsageException.java
  29. 46
      fine-spring/src/com/fr/third/springframework/dao/InvalidDataAccessResourceUsageException.java
  30. 49
      fine-spring/src/com/fr/third/springframework/dao/NonTransientDataAccessException.java
  31. 46
      fine-spring/src/com/fr/third/springframework/dao/NonTransientDataAccessResourceException.java
  32. 49
      fine-spring/src/com/fr/third/springframework/dao/OptimisticLockingFailureException.java
  33. 39
      fine-spring/src/com/fr/third/springframework/dao/PermissionDeniedDataAccessException.java
  34. 53
      fine-spring/src/com/fr/third/springframework/dao/PessimisticLockingFailureException.java
  35. 50
      fine-spring/src/com/fr/third/springframework/dao/QueryTimeoutException.java
  36. 51
      fine-spring/src/com/fr/third/springframework/dao/RecoverableDataAccessException.java
  37. 49
      fine-spring/src/com/fr/third/springframework/dao/TransientDataAccessException.java
  38. 47
      fine-spring/src/com/fr/third/springframework/dao/TransientDataAccessResourceException.java
  39. 46
      fine-spring/src/com/fr/third/springframework/dao/TypeMismatchDataAccessException.java
  40. 38
      fine-spring/src/com/fr/third/springframework/dao/UncategorizedDataAccessException.java
  41. 86
      fine-spring/src/com/fr/third/springframework/dao/annotation/PersistenceExceptionTranslationAdvisor.java
  42. 89
      fine-spring/src/com/fr/third/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.java
  43. 9
      fine-spring/src/com/fr/third/springframework/dao/annotation/package-info.java
  44. 20
      fine-spring/src/com/fr/third/springframework/dao/package-info.java
  45. 67
      fine-spring/src/com/fr/third/springframework/dao/support/ChainedPersistenceExceptionTranslator.java
  46. 73
      fine-spring/src/com/fr/third/springframework/dao/support/DaoSupport.java
  47. 217
      fine-spring/src/com/fr/third/springframework/dao/support/DataAccessUtils.java
  48. 171
      fine-spring/src/com/fr/third/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java
  49. 55
      fine-spring/src/com/fr/third/springframework/dao/support/PersistenceExceptionTranslator.java
  50. 9
      fine-spring/src/com/fr/third/springframework/dao/support/package-info.java
  51. 42
      fine-spring/src/com/fr/third/springframework/jca/cci/CannotCreateRecordException.java
  52. 42
      fine-spring/src/com/fr/third/springframework/jca/cci/CannotGetCciConnectionException.java
  53. 41
      fine-spring/src/com/fr/third/springframework/jca/cci/CciOperationNotSupportedException.java
  54. 46
      fine-spring/src/com/fr/third/springframework/jca/cci/InvalidResultSetAccessException.java
  55. 42
      fine-spring/src/com/fr/third/springframework/jca/cci/RecordTypeNotSupportedException.java
  56. 274
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/CciLocalTransactionManager.java
  57. 214
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionFactoryUtils.java
  58. 49
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionHolder.java
  59. 143
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionSpecConnectionFactoryAdapter.java
  60. 101
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/DelegatingConnectionFactory.java
  61. 54
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/NotSupportedRecordFactory.java
  62. 255
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/SingleConnectionFactory.java
  63. 165
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java
  64. 10
      fine-spring/src/com/fr/third/springframework/jca/cci/connection/package-info.java
  65. 121
      fine-spring/src/com/fr/third/springframework/jca/cci/core/CciOperations.java
  66. 439
      fine-spring/src/com/fr/third/springframework/jca/cci/core/CciTemplate.java
  67. 79
      fine-spring/src/com/fr/third/springframework/jca/cci/core/ConnectionCallback.java
  68. 80
      fine-spring/src/com/fr/third/springframework/jca/cci/core/InteractionCallback.java
  69. 64
      fine-spring/src/com/fr/third/springframework/jca/cci/core/RecordCreator.java
  70. 63
      fine-spring/src/com/fr/third/springframework/jca/cci/core/RecordExtractor.java
  71. 9
      fine-spring/src/com/fr/third/springframework/jca/cci/core/package-info.java
  72. 138
      fine-spring/src/com/fr/third/springframework/jca/cci/core/support/CciDaoSupport.java
  73. 104
      fine-spring/src/com/fr/third/springframework/jca/cci/core/support/CommAreaRecord.java
  74. 8
      fine-spring/src/com/fr/third/springframework/jca/cci/core/support/package-info.java
  75. 94
      fine-spring/src/com/fr/third/springframework/jca/cci/object/EisOperation.java
  76. 97
      fine-spring/src/com/fr/third/springframework/jca/cci/object/MappingCommAreaOperation.java
  77. 151
      fine-spring/src/com/fr/third/springframework/jca/cci/object/MappingRecordOperation.java
  78. 76
      fine-spring/src/com/fr/third/springframework/jca/cci/object/SimpleRecordOperation.java
  79. 11
      fine-spring/src/com/fr/third/springframework/jca/cci/object/package-info.java
  80. 10
      fine-spring/src/com/fr/third/springframework/jca/cci/package-info.java
  81. 47
      fine-spring/src/com/fr/third/springframework/jca/context/BootstrapContextAware.java
  82. 62
      fine-spring/src/com/fr/third/springframework/jca/context/BootstrapContextAwareProcessor.java
  83. 70
      fine-spring/src/com/fr/third/springframework/jca/context/ResourceAdapterApplicationContext.java
  84. 250
      fine-spring/src/com/fr/third/springframework/jca/context/SpringContextResourceAdapter.java
  85. 9
      fine-spring/src/com/fr/third/springframework/jca/context/package-info.java
  86. 17
      fine-spring/src/com/fr/third/springframework/jca/context/ra.xml
  87. 341
      fine-spring/src/com/fr/third/springframework/jca/endpoint/AbstractMessageEndpointFactory.java
  88. 160
      fine-spring/src/com/fr/third/springframework/jca/endpoint/GenericMessageEndpointFactory.java
  89. 334
      fine-spring/src/com/fr/third/springframework/jca/endpoint/GenericMessageEndpointManager.java
  90. 8
      fine-spring/src/com/fr/third/springframework/jca/endpoint/package-info.java
  91. 141
      fine-spring/src/com/fr/third/springframework/jca/support/LocalConnectionFactoryBean.java
  92. 153
      fine-spring/src/com/fr/third/springframework/jca/support/ResourceAdapterFactoryBean.java
  93. 83
      fine-spring/src/com/fr/third/springframework/jca/support/SimpleBootstrapContext.java
  94. 9
      fine-spring/src/com/fr/third/springframework/jca/support/package-info.java
  95. 69
      fine-spring/src/com/fr/third/springframework/jca/work/DelegatingWork.java
  96. 260
      fine-spring/src/com/fr/third/springframework/jca/work/SimpleTaskWorkManager.java
  97. 319
      fine-spring/src/com/fr/third/springframework/jca/work/WorkManagerTaskExecutor.java
  98. 81
      fine-spring/src/com/fr/third/springframework/jca/work/glassfish/GlassFishWorkManagerTaskExecutor.java
  99. 9
      fine-spring/src/com/fr/third/springframework/jca/work/glassfish/package-info.java
  100. 67
      fine-spring/src/com/fr/third/springframework/jca/work/jboss/JBossWorkManagerTaskExecutor.java
  101. Some files were not shown because too many files have changed in this diff Show More

BIN
fine-spring/lib/connector-api-1.5.jar

Binary file not shown.

BIN
fine-spring/lib/javax.transaction-api-1.2.jar

Binary file not shown.

685
fine-spring/resources/META-INF/com/fr/third/springframework/ldap/config/spring-ldap-2.0.xsd

@ -0,0 +1,685 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ldap="http://www.springframework.org/schema/ldap"
xmlns:repository="http://www.springframework.org/schema/data/repository"
elementFormDefault="qualified"
targetNamespace="http://www.springframework.org/schema/ldap">
<xs:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
<xs:attributeGroup name="context-source.attlist">
<xs:attribute name="id" type="xs:token">
<xs:annotation>
<xs:documentation>
A bean identifier, used for referring to the bean elsewhere in the context.
&quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="anonymous-read-only" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Defines whether read-only operations will be performed using an anonymous (unauthenticated) context.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="authentication-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the AuthenticationSource instance to use. If not specified, a SimpleAuthenticationSource will
be used.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="authentication-strategy-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the DirContextAuthenticationStrategy instance to use. If not specified, a SimpleDirContextAuthenticationStrategy
will be used.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="base" type="xs:string">
<xs:annotation>
<xs:documentation>
The base DN. If configured, all LDAP operations on contexts retrieved from this ContextSource will
be relative to this DN. Default is an empty distinguished name (i.e. all operations will be
relative to the directory root).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="password" type="xs:string">
<xs:annotation>
<xs:documentation>
The password to use for authentication.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="native-pooling" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specify whether native Java LDAP connection pooling should be used. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="referral">
<xs:annotation>
<xs:documentation>
Defines the strategy to handle referrals, as described on http://docs.oracle.com/javase/jndi/tutorial/ldap/referral/jndi.html.
Default is null.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="ignore" />
<xs:enumeration value="follow" />
<xs:enumeration value="throw" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="url" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
URL of the LDAP server to use. If fail-over functionality is desired, more than one URL can
be specified, separated using comma (,).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="username" type="xs:string">
<xs:annotation>
<xs:documentation>
The username (principal) to use for authentication. This will normally be the distinguished name
of an admin user.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="base-env-props-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Reference to a Map of custom environment properties that should supplied with the environment
sent to the DirContext on construction.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="pooling.attlist">
<xs:attribute name="max-active" type="xs:string">
<xs:annotation>
<xs:documentation>
The maximum number of active connections of each type (read-only|read-write)
that can be allocated from the pool at the same time, or non-positive for no limit.
Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-total" type="xs:string">
<xs:annotation>
<xs:documentation>
The overall maximum number of active connections (for all types) that can be allocated from
this pool at the same time, or non-positive for no limit. Default is -1 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-idle" type="xs:string">
<xs:annotation>
<xs:documentation>
The maximum number of active connections of each type (read-only|read-write) that can remain idle in the pool,
without extra ones being released, or non-positive for no limit. Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-idle" type="xs:string">
<xs:annotation>
<xs:documentation>
The minimum number of active connections of each type (read-only|read-write) that can remain
idle in the pool, without extra ones being created, or zero to create none. Default is 0.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-wait" type="xs:string">
<xs:annotation>
<xs:documentation>
The maximum number of milliseconds that the pool will wait (when there are no available connections)
for a connection to be returned before throwing an exception, or non-positive to wait indefinitely.
Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="when-exhausted">
<xs:annotation>
<xs:documentation>
Specifies the behaviour when the pool is exhausted.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="FAIL">
<xs:annotation>
<xs:documentation>
Throw a NoSuchElementException when the pool is exhausted
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="BLOCK">
<xs:annotation>
<xs:documentation>
Wait until a new object is available. If max-wait is positive a NoSuchElementException
is thrown if no new object is available after the maxWait time expires.
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="GROW">
<xs:annotation>
<xs:documentation>
Create and return a new object (essentially making maxActive meaningless).
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="test-on-borrow" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being borrowed from the pool.
If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-on-return" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being returned to the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-while-idle" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated by the idle object evictor (if any).
If an object fails to validate, it will be dropped from the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eviction-run-interval-millis" type="xs:string">
<xs:annotation>
<xs:documentation>
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive,
no idle object evictor thread will be run. Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="tests-per-eviction-run" type="xs:string">
<xs:annotation>
<xs:documentation>
The number of objects to examine during each run of the idle object evictor thread (if any).
Default is 3.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-evictable-time-millis" type="xs:string">
<xs:annotation>
<xs:documentation>
The minimum amount of time an object may sit idle in the pool before it is eligible
for eviction by the idle object evictor (if any). Default is 1000 * 60 * 30.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-base" type="xs:string">
<xs:annotation>
<xs:documentation>
The base dn to use for validation searches. Default is LdapUtils.emptyPath().
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-filter" type="xs:string">
<xs:annotation>
<xs:documentation>
The filter to use for validation queries. Default is (objectclass=*).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-search-controls-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE;
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass].
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="non-transient-exceptions" type="xs:string">
<xs:annotation>
<xs:documentation>
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE;
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass].
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:attributeGroup name="pooling2.attlist">
<xs:attribute name="max-total" type="xs:string">
<xs:annotation>
<xs:documentation>
The overall maximum number of active connections (for all types) that can be allocated from
this pool at the same time, or non-positive for no limit. Default is -1 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-total-per-key" type="xs:string">
<xs:annotation>
<xs:documentation>
The limit on the number of object instances allocated by the pool (checked out or idle),
per key. When the limit is reached, the sub-pool is said to be exhausted. A negative value
indicates no limit. Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-idle-per-key" type="xs:string">
<xs:annotation>
<xs:documentation>
The maximum number of active connections per type (read-only|read-write) that can remain idle in the pool,
without extra ones being released, or non-positive for no limit. Default is 8.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-idle-per-key" type="xs:string">
<xs:annotation>
<xs:documentation>
The minimum number of active connections per type (read-only|read-write) that can remain
idle in the pool, without extra ones being created, or zero to create none. Default is 0.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max-wait" type="xs:string">
<xs:annotation>
<xs:documentation>
The maximum number of milliseconds that the pool will wait (when there are no available connections)
for a connection to be returned before throwing an exception, or non-positive to wait indefinitely.
Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="block-when-exhausted" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Sets to wait until a new object is available. If max-wait is positive a NoSuchElementException
is thrown if no new object is available after the maxWait time expires..
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-on-create" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Sets whether objects created for the pool will be validated before borrowing. If the object
fails to validate, then borrowing will fail. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-on-borrow" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being borrowed from the pool.
If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-on-return" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated before being returned to the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="test-while-idle" type="xs:boolean">
<xs:annotation>
<xs:documentation>
The indication of whether objects will be validated by the idle object evictor (if any).
If an object fails to validate, it will be dropped from the pool.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eviction-run-interval-millis" type="xs:string">
<xs:annotation>
<xs:documentation>
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive,
no idle object evictor thread will be run. Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="tests-per-eviction-run" type="xs:string">
<xs:annotation>
<xs:documentation>
The number of objects to examine during each run of the idle object evictor thread (if any).
Default is 3.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min-evictable-time-millis" type="xs:string">
<xs:annotation>
<xs:documentation>
The minimum amount of time an object may sit idle in the pool before it is eligible
for eviction by the idle object evictor (if any). Default is 1000 * 60 * 30.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="soft-min-evictable-idle-time-millis" type="xs:string">
<xs:annotation>
<xs:documentation>
The minimum amount of time an object may sit idle in the pool before it is eligible for
eviction by the idle object evictor, with the extra condition that at least minimum number
of object instances per key remain in the pool. This settings is overridden by min-evictable-time-millis if
it is set to a positive value. Default is -1.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eviction-policy-class" type="xs:string">
<xs:annotation>
<xs:documentation>
The name of the eviction policy implementation that is used by this pool. The Pool will
attempt to load the class using the thread context class loader. If that fails, the Pool
will attempt to load the class using the class loader that loaded this class. Default is
com.fr.third.org.apache.commons.pool2.impl.DefaultEvictionPolicy.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="fairness" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Sets whether or not the pool serves threads waiting to borrow connections fairly.
True means that waiting threads are served as if waiting in a FIFO queue. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="jmx-enable" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Sets whether JMX will be enabled with the platform MBean server for the pool. Default
is true.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="jmx-name-base" type="xs:string">
<xs:annotation>
<xs:documentation>
The value of the JMX name base that will be used as part of the name assigned
to JMX enabled pools. Default is null.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="jmx-name-prefix" type="xs:string">
<xs:annotation>
<xs:documentation>
The value of the JMX name prefix that will be used as part of the name assigned
to JMX enabled pools. Default value is pool.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="lifo" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Sets whether the pool has LIFO (last in, first out) behaviour with
respect to idle objects - always returning the most recently used object
from the pool, or as a FIFO (first in, first out) queue, where the pool
always returns the oldest object in the idle object pool. Default is true.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-base" type="xs:string">
<xs:annotation>
<xs:documentation>
The base dn to use for validation searches. Default is LdapUtils.emptyPath().
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-filter" type="xs:string">
<xs:annotation>
<xs:documentation>
The filter to use for validation queries. Default is (objectclass=*).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="validation-query-search-controls-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE;
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass].
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="non-transient-exceptions" type="xs:string">
<xs:annotation>
<xs:documentation>
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE;
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass].
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="context-source">
<xs:annotation>
<xs:documentation>
Creates a ContextSource instance to be used to get LdapContexts for communicating with an LDAP server.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="1">
<xs:sequence>
<xs:element name="pooling">
<xs:annotation>
<xs:documentation>
Defines the settings to use for the Spring LDAP connection pooling support.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="ldap:pooling.attlist" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:sequence>
<xs:element name="pooling2">
<xs:annotation>
<xs:documentation>
Defines the settings to use for the Spring LDAP connection pooling support based on commons-pool2 library.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="ldap:pooling2.attlist" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:choice>
<xs:attributeGroup ref="ldap:context-source.attlist" />
</xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-template.attlist">
<xs:attribute name="id" type="xs:token">
<xs:annotation>
<xs:documentation>
A bean identifier, used for referring to the bean elsewhere in the context.
Default is &quot;ldapTemplate&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="context-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ContextSource instance to use. Default is &quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="count-limit" type="xs:integer">
<xs:annotation>
<xs:documentation>
The default count limit for searches. Default is 0 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="time-limit" type="xs:integer">
<xs:annotation>
<xs:documentation>
The default time limit for searches. Default is 0 (no limit).
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="search-scope">
<xs:annotation>
<xs:documentation>
The default search scope for searches. Default is SUBTREE.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="OBJECT" />
<xs:enumeration value="ONELEVEL" />
<xs:enumeration value="SUBTREE" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ignore-name-not-found" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specifies whether NameNotFoundException should be ignored in searches. Setting this
attribute to true will cause errors caused by invalid search base to be silently swallowed.
Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ignore-partial-result" type="xs:boolean">
<xs:annotation>
<xs:documentation>
Specifies whether PartialResultException should be ignored in searches. Some LDAP servers
have problems with referrals; these should normally be followed automatically, but if this
doesn't work it will manifest itself with a PartialResultException. Setting this attribute
to true presents a work-around to this problem. Default is false.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="odm-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ObjectDirectoryMapper instance to use. Default is a default-configured DefaultObjectDirectoryMapper.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="ldap-template">
<xs:annotation>
<xs:documentation>
Creates an LdapTemplate instance.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attributeGroup ref="ldap:ldap-template.attlist" />
</xs:complexType>
</xs:element>
<xs:attributeGroup name="transaction-manager.attlist">
<xs:attribute name="id" type="xs:string">
<xs:annotation>
<xs:documentation>
Id of this instance. Default is &quot;transactionManager&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="context-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the ContextSource instance to use. &quot;contextSource&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="data-source-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the DataSource instance to use.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="session-factory-ref" type="xs:token">
<xs:annotation>
<xs:documentation>
Id of the Hibernate SessionFactory instance to use.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="transaction-manager">
<xs:annotation>
<xs:documentation>
Creates an ContextSourceTransactionManager. If data-source-ref or session-factory-ref is specified,
a DataSourceAndContextSourceTransactionManager/HibernateAndContextSourceTransactionManager will be
created.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="1">
<xs:element name="default-renaming-strategy">
<xs:annotation>
<xs:documentation>
The default (simplistic) TempEntryRenamingStrategy. Please note that this
strategy will not work for more advanced scenarios. See reference documentation
for details.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="temp-suffix" type="xs:string">
<xs:annotation>
<xs:documentation>
The default suffix that will be added to modified entries.
Default is &quot;_temp&quot;.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="different-subtree-renaming-strategy">
<xs:annotation>
<xs:documentation>
TempEntryRenamingStrategy that moves the entry to a different subtree than
the original entry.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:attribute name="subtree-node" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>
The subtree base where changed entries should be moved.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attributeGroup ref="ldap:transaction-manager.attlist" />
</xs:complexType>
</xs:element>
<xs:element name="repositories">
<xs:complexType>
<xs:complexContent>
<xs:extension base="repository:repositories">
<xs:attribute name="ldap-template-ref">
<xs:annotation>
<xs:documentation>
The reference to an LdapTemplate. Will default to 'ldapTemplate'.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>

198
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-2.0.xsd

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.0.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotation supported is Spring's @Transactional.
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:integer" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

244
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-2.5.xsd

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.5.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotations supported are Spring's @Transactional
and EJB3's @TransactionAttribute (if available).
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
Should annotated beans be proxied using Spring's AOP framework,
or should they rather be weaved with an AspectJ transaction aspect?
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
Note: The weaving-based aspect requires the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="proxy"/>
<xsd:enumeration value="aspectj"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
Note: Class-based proxies require the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jta-transaction-manager">
<xsd:annotation>
<xsd:documentation><![CDATA[
Creates a default JtaTransactionManager bean with name "transactionManager",
matching the default bean name expected by the "annotation-driven" tag.
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager,
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively.
For customization needs, consider defining a JtaTransactionManager bean as a regular
Spring bean definition with name "transactionManager", replacing this element.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', 'on*Event', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:integer" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

244
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.0.xsd

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.0.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotations supported are Spring's @Transactional
and EJB3's @TransactionAttribute (if available).
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
Should annotated beans be proxied using Spring's AOP framework,
or should they rather be weaved with an AspectJ transaction aspect?
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
Note: The weaving-based aspect requires the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="proxy"/>
<xsd:enumeration value="aspectj"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
Note: Class-based proxies require the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jta-transaction-manager">
<xsd:annotation>
<xsd:documentation><![CDATA[
Creates a default JtaTransactionManager bean with name "transactionManager",
matching the default bean name expected by the "annotation-driven" tag.
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager,
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively.
For customization needs, consider defining a JtaTransactionManager bean as a regular
Spring bean definition with name "transactionManager", replacing this element.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', 'on*Event', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:integer" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

247
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.1.xsd

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotations supported are Spring's @Transactional
and EJB3's @TransactionAttribute (if available).
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc
for information on code-based alternatives to this XML element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
Should annotated beans be proxied using Spring's AOP framework,
or should they rather be weaved with an AspectJ transaction aspect?
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
Note: The weaving-based aspect requires the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="proxy"/>
<xsd:enumeration value="aspectj"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
Note: Class-based proxies require the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jta-transaction-manager">
<xsd:annotation>
<xsd:documentation><![CDATA[
Creates a default JtaTransactionManager bean with name "transactionManager",
matching the default bean name expected by the "annotation-driven" tag.
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager,
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively.
For customization needs, consider defining a JtaTransactionManager bean as a regular
Spring bean definition with name "transactionManager", replacing this element.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', 'on*Event', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:integer" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

247
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-3.2.xsd

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.2.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotations supported are Spring's @Transactional
and EJB3's @TransactionAttribute (if available).
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc
for information on code-based alternatives to this XML element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
Should annotated beans be proxied using Spring's AOP framework,
or should they rather be weaved with an AspectJ transaction aspect?
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
Note: The weaving-based aspect requires the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="proxy"/>
<xsd:enumeration value="aspectj"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
Note: Class-based proxies require the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jta-transaction-manager">
<xsd:annotation>
<xsd:documentation><![CDATA[
Creates a default JtaTransactionManager bean with name "transactionManager",
matching the default bean name expected by the "annotation-driven" tag.
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager,
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively.
For customization needs, consider defining a JtaTransactionManager bean as a regular
Spring bean definition with name "transactionManager", replacing this element.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', 'on*Event', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:integer" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

247
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx-4.0.xsd

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/tx"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/tx"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.0.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the elements used in the Spring Framework's declarative
transaction management infrastructure.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="advice">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[
Defines the transactional semantics of the AOP advice that is to be
executed.
That is, this advice element is where the transactional semantics of
any number of methods are defined (where transactional semantics
includes the propagation settings, the isolation level, the rollback
rules, and suchlike).
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:sequence>
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="annotation-driven">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[
Indicates that transaction configuration is defined by Java 5
annotations on bean classes, and that proxies are automatically
to be created for the relevant annotated beans.
The default annotations supported are Spring's @Transactional
and EJB3's @TransactionAttribute (if available).
Transaction semantics such as propagation settings, the isolation level,
the rollback rules, etc are all defined in the annotation metadata.
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc
for information on code-based alternatives to this XML element.
]]></xsd:documentation>
</xsd:annotation>
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[
The bean name of the PlatformTransactionManager that is to be used
to drive transactions.
This attribute is not required, and only needs to be specified
explicitly if the bean name of the desired PlatformTransactionManager
is not 'transactionManager'.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mode" default="proxy">
<xsd:annotation>
<xsd:documentation><![CDATA[
Should annotated beans be proxied using Spring's AOP framework,
or should they rather be weaved with an AspectJ transaction aspect?
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
Note: The weaving-based aspect requires the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="proxy"/>
<xsd:enumeration value="aspectj"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are class-based (CGLIB) proxies to be created? By default, standard
Java interface-based proxies are created.
Note: Class-based proxies require the @Transactional annotation to be
defined on the concrete class. Annotations in interfaces will not work
in that case (they will rather only work with interface-based proxies)!
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:token">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of the transaction advisor
when multiple advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jta-transaction-manager">
<xsd:annotation>
<xsd:documentation><![CDATA[
Creates a default JtaTransactionManager bean with name "transactionManager",
matching the default bean name expected by the "annotation-driven" tag.
Automatically detects WebLogic and WebSphere: creating a WebLogicJtaTransactionManager
or WebSphereUowTransactionManager, respectively.
For customization needs, consider defining a JtaTransactionManager bean as a regular
Spring bean definition with name "transactionManager", replacing this element.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:complexType name="attributesType">
<xsd:sequence>
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The method name(s) with which the transaction attributes are to be
associated. The wildcard (*) character can be used to associate the
same transaction attribute settings with a number of methods; for
example, 'get*', 'handle*', '*Order', 'on*Event', etc.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="propagation" default="REQUIRED">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[
The transaction propagation behavior.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REQUIRED"/>
<xsd:enumeration value="SUPPORTS"/>
<xsd:enumeration value="MANDATORY"/>
<xsd:enumeration value="REQUIRES_NEW"/>
<xsd:enumeration value="NOT_SUPPORTED"/>
<xsd:enumeration value="NEVER"/>
<xsd:enumeration value="NESTED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="isolation" default="DEFAULT">
<xsd:annotation>
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[
The transaction isolation level.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="DEFAULT"/>
<xsd:enumeration value="READ_UNCOMMITTED"/>
<xsd:enumeration value="READ_COMMITTED"/>
<xsd:enumeration value="REPEATABLE_READ"/>
<xsd:enumeration value="SERIALIZABLE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:int" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction timeout value (in seconds).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="read-only" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Is this transaction read-only?
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="no-rollback-for" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
The Exception(s) that will *not* trigger rollback; comma-delimited.
For example, 'com.foo.MyBusinessException,ServletException'
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

BIN
fine-spring/resources/META-INF/com/fr/third/springframework/transaction/config/spring-tx.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

3
fine-spring/resources/META-INF/fine-spring.handlers

@ -5,3 +5,6 @@ http\://www.springframework.org/schema/task=com.fr.third.springframework.schedul
http\://www.springframework.org/schema/cache=com.fr.third.springframework.cache.config.CacheNamespaceHandler http\://www.springframework.org/schema/cache=com.fr.third.springframework.cache.config.CacheNamespaceHandler
http\://www.springframework.org/schema/mvc=com.fr.third.springframework.web.servlet.config.MvcNamespaceHandler http\://www.springframework.org/schema/mvc=com.fr.third.springframework.web.servlet.config.MvcNamespaceHandler
http\://www.springframework.org/schema/tx=com.fr.third.springframework.transaction.config.TxNamespaceHandler
http\://www.springframework.org/schema/ldap=com.fr.third.springframework.ldap.config.LdapNamespaceHandler

11
fine-spring/resources/META-INF/fine-spring.schemas

@ -53,3 +53,14 @@ http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=com/fr/third/spr
http\://www.springframework.org/schema/tool/spring-tool-3.2.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-3.2.xsd http\://www.springframework.org/schema/tool/spring-tool-3.2.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-3.2.xsd
http\://www.springframework.org/schema/tool/spring-tool-4.0.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-4.0.xsd http\://www.springframework.org/schema/tool/spring-tool-4.0.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-4.0.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-4.0.xsd http\://www.springframework.org/schema/tool/spring-tool.xsd=com/fr/third/springframework/beans/factory/xml/spring-tool-4.0.xsd
http\://www.springframework.org/schema/tx/spring-tx-2.0.xsd=com/fr/third/springframework/transaction/config/spring-tx-2.0.xsd
http\://www.springframework.org/schema/tx/spring-tx-2.5.xsd=com/fr/third/springframework/transaction/config/spring-tx-2.5.xsd
http\://www.springframework.org/schema/tx/spring-tx-3.0.xsd=com/fr/third/springframework/transaction/config/spring-tx-3.0.xsd
http\://www.springframework.org/schema/tx/spring-tx-3.1.xsd=com/fr/third/springframework/transaction/config/spring-tx-3.1.xsd
http\://www.springframework.org/schema/tx/spring-tx-3.2.xsd=com/fr/third/springframework/transaction/config/spring-tx-3.2.xsd
http\://www.springframework.org/schema/tx/spring-tx-4.0.xsd=com/fr/third/springframework/transaction/config/spring-tx-4.0.xsd
http\://www.springframework.org/schema/tx/spring-tx.xsd=com/fr/third/springframework/transaction/config/spring-tx-4.0.xsd
http\://www.springframework.org/schema/ldap/spring-ldap.xsd=com/fr/third/springframework/ldap/config/spring-ldap-2.0.xsd
http\://www.springframework.org/schema/ldap/spring-ldap-2.0.xsd=com/fr/third/springframework/ldap/config/spring-ldap-2.0.xsd

6
fine-spring/resources/META-INF/fine-spring.tooling

@ -22,3 +22,9 @@ http\://www.springframework.org/schema/lang@icon=org/springframework/scripting/c
http\://www.springframework.org/schema/cache@name=cache Namespace http\://www.springframework.org/schema/cache@name=cache Namespace
http\://www.springframework.org/schema/cache@prefix=cache http\://www.springframework.org/schema/cache@prefix=cache
http\://www.springframework.org/schema/cache@icon=org/springframework/cache/config/spring-cache.gif http\://www.springframework.org/schema/cache@icon=org/springframework/cache/config/spring-cache.gif
# Tooling related information for the tx namespace
http\://www.springframework.org/schema/tx@name=tx Namespace
http\://www.springframework.org/schema/tx@prefix=tx
http\://www.springframework.org/schema/tx@icon=org/springframework/transaction/config/spring-tx.gif

212
fine-spring/src/com/fr/third/springframework/LdapDataEntry.java

@ -0,0 +1,212 @@
package com.fr.third.springframework;
import javax.naming.Name;
import javax.naming.directory.Attributes;
import java.util.SortedSet;
/**
* Common data access methods for entries in an LDAP tree.
*
* @author Mattias Hellborg Arthursson
* @since 2.0
*/
public interface LdapDataEntry {
/**
* Get the value of a String attribute. If more than one attribute value
* exists for the specified attribute, only the first one will be returned.
* If an attribute has no value, <code>null</code> will be returned.
*
* @param name name of the attribute.
* @return the value of the attribute if it exists, or <code>null</code> if
* the attribute doesn't exist or if it exists but with no value.
* @throws ClassCastException if the value of the entry is not a String.
*/
String getStringAttribute(String name);
/**
* Get the value of an Object attribute. If more than one attribute value
* exists for the specified attribute, only the first one will be returned.
* If an attribute has no value, <code>null</code> will be returned.
*
* @param name name of the attribute.
* @return the attribute value as an object if it exists, or
* <code>null</code> if the attribute doesn't exist or if it exists but with
* no value.
*/
Object getObjectAttribute(String name);
/**
* Check if an Object attribute exists, regardless of whether it has a value
* or not.
*
* @param name name of the attribute
* @return <code>true</code> if the attribute exists, <code>false</code>
* otherwise
*/
boolean attributeExists(String name);
/**
* Set the with the name <code>name</code> to the <code>value</code>.
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name name of the attribute.
* @param value value to set the attribute to.
* @throws IllegalArgumentException if the value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValue(String name, Object value);
/**
* Sets a multivalue attribute, disregarding the order of the values.
*
* If value is null or value.length == 0 then the attribute will be removed.
*
* If update mode, changes will be made only if the array has more or less
* objects or if one or more object has changed. Reordering the objects will
* not cause an update.
*
* If the values are {@link Name} instances, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name The id of the attribute.
* @param values Attribute values.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValues(String name, Object[] values);
/**
* Sets a multivalue attribute.
*
* If value is null or value.length == 0 then the attribute will be removed.
*
* If update mode, changes will be made if the array has more or less
* objects or if one or more string has changed.
*
* Reordering the objects will only cause an update if orderMatters is set
* to true.
*
* If the values are {@link Name} instances, equality for Distinguished
* Names will be used for calculating attribute modifications.
* @param name The id of the attribute.
* @param values Attribute values.
* @param orderMatters If <code>true</code>, it will be changed even if data
* was just reordered.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValues(String name, Object[] values, boolean orderMatters);
/**
* Add a value to the Attribute with the specified name. If the Attribute
* doesn't exist it will be created. This method makes sure that the there
* will be no duplicates of an added value - it the value exists it will not
* be added again.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute to which the specified value should
* be added.
* @param value the Attribute value to add.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void addAttributeValue(String name, Object value);
/**
* Add a value to the Attribute with the specified name. If the Attribute
* doesn't exist it will be created. The <code>addIfDuplicateExists</code>
* parameter controls the handling of duplicates. It <code>false</code>,
* this method makes sure that the there will be no duplicates of an added
* value - it the value exists it will not be added again.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute to which the specified value should
* be added.
* @param value the Attribute value to add.
* @param addIfDuplicateExists <code>true</code> will add the value
* regardless of whether there is an identical value already, allowing for
* duplicate attribute values; <code>false</code> will not add the value if
* it already exists.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void addAttributeValue(String name, Object value,
boolean addIfDuplicateExists);
/**
* Remove a value from the Attribute with the specified name. If the
* Attribute doesn't exist, do nothing.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute from which the specified value
* should be removed.
* @param value the value to remove.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void removeAttributeValue(String name, Object value);
/**
* Get all values of a String attribute.
*
* @param name name of the attribute.
* @return a (possibly empty) array containing all registered values of the
* attribute as Strings if the attribute is defined or <code>null</code>
* otherwise.
* @throws IllegalArgumentException if any of the attribute values is not a
* String.
*/
String[] getStringAttributes(String name);
/**
* Get all values of an Object attribute.
*
* @param name name of the attribute.
* @return a (possibly empty) array containing all registered values of the
* attribute if the attribute is defined or <code>null</code> otherwise.
* @since 1.3
*/
Object[] getObjectAttributes(String name);
/**
* Get all String values of the attribute as a <code>SortedSet</code>.
*
* @param name name of the attribute.
* @return a <code>SortedSet</code> containing all values of the attribute,
* or <code>null</code> if the attribute does not exist.
* @throws IllegalArgumentException if one of the found attribute values cannot be cast to a String.
*/
SortedSet<String> getAttributeSortedStringSet(String name);
/**
* Returns the DN relative to the base path.
* <b>NB</b>: as of version 2.0 the returned name will be an LdapName instance.
*
* @return The distinguished name of the current context.
*
* @see com.fr.third.springframework.ldap.core.DirContextAdapter#getNameInNamespace()
*/
Name getDn();
/**
* Get all the Attributes.
*
* @return all the Attributes.
* @since 1.3
*/
Attributes getAttributes();
}

45
fine-spring/src/com/fr/third/springframework/dao/CannotAcquireLockException.java

@ -0,0 +1,45 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on failure to aquire a lock during an update,
* for example during a "select for update" statement.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class CannotAcquireLockException extends PessimisticLockingFailureException {
/**
* Constructor for CannotAcquireLockException.
* @param msg the detail message
*/
public CannotAcquireLockException(String msg) {
super(msg);
}
/**
* Constructor for CannotAcquireLockException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public CannotAcquireLockException(String msg, Throwable cause) {
super(msg, cause);
}
}

45
fine-spring/src/com/fr/third/springframework/dao/CannotSerializeTransactionException.java

@ -0,0 +1,45 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on failure to complete a transaction in serialized mode
* due to update conflicts.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class CannotSerializeTransactionException extends PessimisticLockingFailureException {
/**
* Constructor for CannotSerializeTransactionException.
* @param msg the detail message
*/
public CannotSerializeTransactionException(String msg) {
super(msg);
}
/**
* Constructor for CannotSerializeTransactionException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public CannotSerializeTransactionException(String msg, Throwable cause) {
super(msg, cause);
}
}

45
fine-spring/src/com/fr/third/springframework/dao/CleanupFailureDataAccessException.java

@ -0,0 +1,45 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown when we couldn't cleanup after a data access operation,
* but the actual operation went OK.
*
* <p>For example, this exception or a subclass might be thrown if a JDBC
* Connection couldn't be closed after it had been used successfully.
*
* <p>Note that data access code might perform resources cleanup in a
* finally block and therefore log cleanup failure rather than rethrow it,
* to keep the original data access exception, if any.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class CleanupFailureDataAccessException extends NonTransientDataAccessException {
/**
* Constructor for CleanupFailureDataAccessException.
* @param msg the detail message
* @param cause the root cause from the underlying data access API,
* such as JDBC
*/
public CleanupFailureDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

52
fine-spring/src/com/fr/third/springframework/dao/ConcurrencyFailureException.java

@ -0,0 +1,52 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on concurrency failure.
*
* <p>This exception should be subclassed to indicate the type of failure:
* optimistic locking, failure to acquire lock, etc.
*
* @author Thomas Risberg
* @since 1.1
* @see OptimisticLockingFailureException
* @see PessimisticLockingFailureException
* @see CannotAcquireLockException
* @see DeadlockLoserDataAccessException
*/
@SuppressWarnings("serial")
public class ConcurrencyFailureException extends TransientDataAccessException {
/**
* Constructor for ConcurrencyFailureException.
* @param msg the detail message
*/
public ConcurrencyFailureException(String msg) {
super(msg);
}
/**
* Constructor for ConcurrencyFailureException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public ConcurrencyFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}

59
fine-spring/src/com/fr/third/springframework/dao/DataAccessException.java

@ -0,0 +1,59 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
import com.fr.third.springframework.core.NestedRuntimeException;
/**
* Root of the hierarchy of data access exceptions discussed in
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>.
* Please see Chapter 9 of this book for detailed discussion of the
* motivation for this package.
*
* <p>This exception hierarchy aims to let user code find and handle the
* kind of error encountered without knowing the details of the particular
* data access API in use (e.g. JDBC). Thus it is possible to react to an
* optimistic locking failure without knowing that JDBC is being used.
*
* <p>As this class is a runtime exception, there is no need for user code
* to catch it or subclasses if any error is to be considered fatal
* (the usual case).
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public abstract class DataAccessException extends NestedRuntimeException {
/**
* Constructor for DataAccessException.
* @param msg the detail message
*/
public DataAccessException(String msg) {
super(msg);
}
/**
* Constructor for DataAccessException.
* @param msg the detail message
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public DataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

46
fine-spring/src/com/fr/third/springframework/dao/DataAccessResourceFailureException.java

@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a resource fails completely:
* for example, if we can't connect to a database using JDBC.
*
* @author Rod Johnson
* @author Thomas Risberg
*/
@SuppressWarnings("serial")
public class DataAccessResourceFailureException extends NonTransientDataAccessResourceException {
/**
* Constructor for DataAccessResourceFailureException.
* @param msg the detail message
*/
public DataAccessResourceFailureException(String msg) {
super(msg);
}
/**
* Constructor for DataAccessResourceFailureException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DataAccessResourceFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}

47
fine-spring/src/com/fr/third/springframework/dao/DataIntegrityViolationException.java

@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown when an attempt to insert or update data
* results in violation of an integrity constraint. Note that this
* is not purely a relational concept; unique primary keys are
* required by most database types.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class DataIntegrityViolationException extends NonTransientDataAccessException {
/**
* Constructor for DataIntegrityViolationException.
* @param msg the detail message
*/
public DataIntegrityViolationException(String msg) {
super(msg);
}
/**
* Constructor for DataIntegrityViolationException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DataIntegrityViolationException(String msg, Throwable cause) {
super(msg, cause);
}
}

47
fine-spring/src/com/fr/third/springframework/dao/DataRetrievalFailureException.java

@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown if certain expected data could not be retrieved, e.g.
* when looking up specific data via a known identifier. This exception
* will be thrown either by O/R mapping tools or by DAO implementations.
*
* @author Juergen Hoeller
* @since 13.10.2003
*/
@SuppressWarnings("serial")
public class DataRetrievalFailureException extends NonTransientDataAccessException {
/**
* Constructor for DataRetrievalFailureException.
* @param msg the detail message
*/
public DataRetrievalFailureException(String msg) {
super(msg);
}
/**
* Constructor for DataRetrievalFailureException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DataRetrievalFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}

37
fine-spring/src/com/fr/third/springframework/dao/DeadlockLoserDataAccessException.java

@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Generic exception thrown when the current process was
* a deadlock loser, and its transaction rolled back.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class DeadlockLoserDataAccessException extends PessimisticLockingFailureException {
/**
* Constructor for DeadlockLoserDataAccessException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DeadlockLoserDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

47
fine-spring/src/com/fr/third/springframework/dao/DuplicateKeyException.java

@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown when an attempt to insert or update data
* results in violation of an primary key or unique constraint.
* Note that this is not necessarily a purely relational concept;
* unique primary keys are required by most database types.
*
* @author Thomas Risberg
*/
@SuppressWarnings("serial")
public class DuplicateKeyException extends DataIntegrityViolationException {
/**
* Constructor for DuplicateKeyException.
* @param msg the detail message
*/
public DuplicateKeyException(String msg) {
super(msg);
}
/**
* Constructor for DuplicateKeyException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DuplicateKeyException(String msg, Throwable cause) {
super(msg, cause);
}
}

57
fine-spring/src/com/fr/third/springframework/dao/EmptyResultDataAccessException.java

@ -0,0 +1,57 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a result was expected to have at least
* one row (or element) but zero rows (or elements) were actually returned.
*
* @author Juergen Hoeller
* @since 2.0
* @see IncorrectResultSizeDataAccessException
*/
@SuppressWarnings("serial")
public class EmptyResultDataAccessException extends IncorrectResultSizeDataAccessException {
/**
* Constructor for EmptyResultDataAccessException.
* @param expectedSize the expected result size
*/
public EmptyResultDataAccessException(int expectedSize) {
super(expectedSize, 0);
}
/**
* Constructor for EmptyResultDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
*/
public EmptyResultDataAccessException(String msg, int expectedSize) {
super(msg, expectedSize, 0);
}
/**
* Constructor for EmptyResultDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
* @param ex the wrapped exception
*/
public EmptyResultDataAccessException(String msg, int expectedSize, Throwable ex) {
super(msg, expectedSize, 0, ex);
}
}

120
fine-spring/src/com/fr/third/springframework/dao/IncorrectResultSizeDataAccessException.java

@ -0,0 +1,120 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a result was not of the expected size,
* for example when expecting a single row but getting 0 or more than 1 rows.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 1.0.2
* @see EmptyResultDataAccessException
*/
@SuppressWarnings("serial")
public class IncorrectResultSizeDataAccessException extends DataRetrievalFailureException {
private int expectedSize;
private int actualSize;
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param expectedSize the expected result size
*/
public IncorrectResultSizeDataAccessException(int expectedSize) {
super("Incorrect result size: expected " + expectedSize);
this.expectedSize = expectedSize;
this.actualSize = -1;
}
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param expectedSize the expected result size
* @param actualSize the actual result size (or -1 if unknown)
*/
public IncorrectResultSizeDataAccessException(int expectedSize, int actualSize) {
super("Incorrect result size: expected " + expectedSize + ", actual " + actualSize);
this.expectedSize = expectedSize;
this.actualSize = actualSize;
}
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
*/
public IncorrectResultSizeDataAccessException(String msg, int expectedSize) {
super(msg);
this.expectedSize = expectedSize;
this.actualSize = -1;
}
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
* @param ex the wrapped exception
*/
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, Throwable ex) {
super(msg, ex);
this.expectedSize = expectedSize;
this.actualSize = -1;
}
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
* @param actualSize the actual result size (or -1 if unknown)
*/
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, int actualSize) {
super(msg);
this.expectedSize = expectedSize;
this.actualSize = actualSize;
}
/**
* Constructor for IncorrectResultSizeDataAccessException.
* @param msg the detail message
* @param expectedSize the expected result size
* @param actualSize the actual result size (or -1 if unknown)
* @param ex the wrapped exception
*/
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, int actualSize, Throwable ex) {
super(msg, ex);
this.expectedSize = expectedSize;
this.actualSize = actualSize;
}
/**
* Return the expected result size.
*/
public int getExpectedSize() {
return this.expectedSize;
}
/**
* Return the actual result size (or -1 if unknown).
*/
public int getActualSize() {
return this.actualSize;
}
}

57
fine-spring/src/com/fr/third/springframework/dao/IncorrectUpdateSemanticsDataAccessException.java

@ -0,0 +1,57 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when something unintended appears to have
* happened with an update, but the transaction hasn't already been rolled back.
* Thrown, for example, when we wanted to update 1 row in an RDBMS but actually
* updated 3.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class IncorrectUpdateSemanticsDataAccessException extends InvalidDataAccessResourceUsageException {
/**
* Constructor for IncorrectUpdateSemanticsDataAccessException.
* @param msg the detail message
*/
public IncorrectUpdateSemanticsDataAccessException(String msg) {
super(msg);
}
/**
* Constructor for IncorrectUpdateSemanticsDataAccessException.
* @param msg the detail message
* @param cause the root cause from the underlying API, such as JDBC
*/
public IncorrectUpdateSemanticsDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Return whether data was updated.
* If this method returns false, there's nothing to roll back.
* <p>The default implementation always returns true.
* This can be overridden in subclasses.
*/
public boolean wasDataUpdated() {
return true;
}
}

48
fine-spring/src/com/fr/third/springframework/dao/InvalidDataAccessApiUsageException.java

@ -0,0 +1,48 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on incorrect usage of the API, such as failing to
* "compile" a query object that needed compilation before execution.
*
* <p>This represents a problem in our Java data access framework,
* not the underlying data access infrastructure.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class InvalidDataAccessApiUsageException extends NonTransientDataAccessException {
/**
* Constructor for InvalidDataAccessApiUsageException.
* @param msg the detail message
*/
public InvalidDataAccessApiUsageException(String msg) {
super(msg);
}
/**
* Constructor for InvalidDataAccessApiUsageException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public InvalidDataAccessApiUsageException(String msg, Throwable cause) {
super(msg, cause);
}
}

46
fine-spring/src/com/fr/third/springframework/dao/InvalidDataAccessResourceUsageException.java

@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Root for exceptions thrown when we use a data access resource incorrectly.
* Thrown for example on specifying bad SQL when using a RDBMS.
* Resource-specific subclasses are supplied by concrete data access packages.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class InvalidDataAccessResourceUsageException extends NonTransientDataAccessException {
/**
* Constructor for InvalidDataAccessResourceUsageException.
* @param msg the detail message
*/
public InvalidDataAccessResourceUsageException(String msg) {
super(msg);
}
/**
* Constructor for InvalidDataAccessResourceUsageException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public InvalidDataAccessResourceUsageException(String msg, Throwable cause) {
super(msg, cause);
}
}

49
fine-spring/src/com/fr/third/springframework/dao/NonTransientDataAccessException.java

@ -0,0 +1,49 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Root of the hierarchy of data access exceptions that are considered non-transient -
* where a retry of the same operation would fail unless the cause of the Exception
* is corrected.
*
* @author Thomas Risberg
* @since 2.5
* @see java.sql.SQLNonTransientException
*/
@SuppressWarnings("serial")
public abstract class NonTransientDataAccessException extends DataAccessException {
/**
* Constructor for NonTransientDataAccessException.
* @param msg the detail message
*/
public NonTransientDataAccessException(String msg) {
super(msg);
}
/**
* Constructor for NonTransientDataAccessException.
* @param msg the detail message
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public NonTransientDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

46
fine-spring/src/com/fr/third/springframework/dao/NonTransientDataAccessResourceException.java

@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a resource fails completely and the failure is permanent.
*
* @author Thomas Risberg
* @since 2.5
* @see java.sql.SQLNonTransientConnectionException
*/
@SuppressWarnings("serial")
public class NonTransientDataAccessResourceException extends NonTransientDataAccessException {
/**
* Constructor for NonTransientDataAccessResourceException.
* @param msg the detail message
*/
public NonTransientDataAccessResourceException(String msg) {
super(msg);
}
/**
* Constructor for NonTransientDataAccessResourceException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public NonTransientDataAccessResourceException(String msg, Throwable cause) {
super(msg, cause);
}
}

49
fine-spring/src/com/fr/third/springframework/dao/OptimisticLockingFailureException.java

@ -0,0 +1,49 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on an optimistic locking violation.
*
* <p>This exception will be thrown either by O/R mapping tools
* or by custom DAO implementations. Optimistic locking failure
* is typically <i>not</i> detected by the database itself.
*
* @author Rod Johnson
* @see PessimisticLockingFailureException
*/
@SuppressWarnings("serial")
public class OptimisticLockingFailureException extends ConcurrencyFailureException {
/**
* Constructor for OptimisticLockingFailureException.
* @param msg the detail message
*/
public OptimisticLockingFailureException(String msg) {
super(msg);
}
/**
* Constructor for OptimisticLockingFailureException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public OptimisticLockingFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}

39
fine-spring/src/com/fr/third/springframework/dao/PermissionDeniedDataAccessException.java

@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown when the underlying resource denied a permission
* to access a specific element, such as a specific database table.
*
* @author Juergen Hoeller
* @since 2.0
*/
@SuppressWarnings("serial")
public class PermissionDeniedDataAccessException extends NonTransientDataAccessException {
/**
* Constructor for PermissionDeniedDataAccessException.
* @param msg the detail message
* @param cause the root cause from the underlying data access API,
* such as JDBC
*/
public PermissionDeniedDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

53
fine-spring/src/com/fr/third/springframework/dao/PessimisticLockingFailureException.java

@ -0,0 +1,53 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on a pessimistic locking violation.
* Thrown by Spring's SQLException translation mechanism
* if a corresponding database error is encountered.
*
* <p>Serves as superclass for more specific exceptions, like
* CannotAcquireLockException and DeadlockLoserDataAccessException.
*
* @author Thomas Risberg
* @since 1.2
* @see CannotAcquireLockException
* @see DeadlockLoserDataAccessException
* @see OptimisticLockingFailureException
*/
@SuppressWarnings("serial")
public class PessimisticLockingFailureException extends ConcurrencyFailureException {
/**
* Constructor for PessimisticLockingFailureException.
* @param msg the detail message
*/
public PessimisticLockingFailureException(String msg) {
super(msg);
}
/**
* Constructor for PessimisticLockingFailureException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public PessimisticLockingFailureException(String msg, Throwable cause) {
super(msg, cause);
}
}

50
fine-spring/src/com/fr/third/springframework/dao/QueryTimeoutException.java

@ -0,0 +1,50 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception to be thrown on a query timeout. This could have different causes depending on
* the database API in use but most likely thrown after the database interrupts or stops
* the processing of a query before it has completed.
*
* <p>This exception can be thrown by user code trapping the native database exception or
* by exception translation.
*
* @author Thomas Risberg
* @since 3.1
*/
@SuppressWarnings("serial")
public class QueryTimeoutException extends TransientDataAccessException {
/**
* Constructor for QueryTimeoutException.
* @param msg the detail message
*/
public QueryTimeoutException(String msg) {
super(msg);
}
/**
* Constructor for QueryTimeoutException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public QueryTimeoutException(String msg, Throwable cause) {
super(msg, cause);
}
}

51
fine-spring/src/com/fr/third/springframework/dao/RecoverableDataAccessException.java

@ -0,0 +1,51 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a previously failed operation might be able
* to succeed if the application performs some recovery steps and retries the entire
* transaction or in the case of a distributed transaction, the transaction branch.
* At a minimum, the recovery operation must include closing the current connection
* and getting a new connection.
*
* @author Thomas Risberg
* @since 2.5
* @see java.sql.SQLRecoverableException
*/
@SuppressWarnings("serial")
public class RecoverableDataAccessException extends DataAccessException {
/**
* Constructor for RecoverableDataAccessException.
* @param msg the detail message
*/
public RecoverableDataAccessException(String msg) {
super(msg);
}
/**
* Constructor for RecoverableDataAccessException.
* @param msg the detail message
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public RecoverableDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

49
fine-spring/src/com/fr/third/springframework/dao/TransientDataAccessException.java

@ -0,0 +1,49 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Root of the hierarchy of data access exceptions that are considered transient -
* where a previously failed operation might be able to succeed when the operation
* is retried without any intervention by application-level functionality.
*
* @author Thomas Risberg
* @since 2.5
* @see java.sql.SQLTransientException
*/
@SuppressWarnings("serial")
public abstract class TransientDataAccessException extends DataAccessException {
/**
* Constructor for TransientDataAccessException.
* @param msg the detail message
*/
public TransientDataAccessException(String msg) {
super(msg);
}
/**
* Constructor for TransientDataAccessException.
* @param msg the detail message
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public TransientDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

47
fine-spring/src/com/fr/third/springframework/dao/TransientDataAccessResourceException.java

@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Data access exception thrown when a resource fails temporarily
* and the operation can be retried.
*
* @author Thomas Risberg
* @since 2.5
* @see java.sql.SQLTransientConnectionException
*/
@SuppressWarnings("serial")
public class TransientDataAccessResourceException extends TransientDataAccessException {
/**
* Constructor for TransientDataAccessResourceException.
* @param msg the detail message
*/
public TransientDataAccessResourceException(String msg) {
super(msg);
}
/**
* Constructor for TransientDataAccessResourceException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public TransientDataAccessResourceException(String msg, Throwable cause) {
super(msg, cause);
}
}

46
fine-spring/src/com/fr/third/springframework/dao/TypeMismatchDataAccessException.java

@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Exception thrown on mismatch between Java type and database type:
* for example on an attempt to set an object of the wrong type
* in an RDBMS column.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public class TypeMismatchDataAccessException extends InvalidDataAccessResourceUsageException {
/**
* Constructor for TypeMismatchDataAccessException.
* @param msg the detail message
*/
public TypeMismatchDataAccessException(String msg) {
super(msg);
}
/**
* Constructor for TypeMismatchDataAccessException.
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public TypeMismatchDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

38
fine-spring/src/com/fr/third/springframework/dao/UncategorizedDataAccessException.java

@ -0,0 +1,38 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao;
/**
* Normal superclass when we can't distinguish anything more specific
* than "something went wrong with the underlying resource": for example,
* a SQLException from JDBC we can't pinpoint more precisely.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
public abstract class UncategorizedDataAccessException extends NonTransientDataAccessException {
/**
* Constructor for UncategorizedDataAccessException.
* @param msg the detail message
* @param cause the exception thrown by underlying data access API
*/
public UncategorizedDataAccessException(String msg, Throwable cause) {
super(msg, cause);
}
}

86
fine-spring/src/com/fr/third/springframework/dao/annotation/PersistenceExceptionTranslationAdvisor.java

@ -0,0 +1,86 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.annotation;
import java.lang.annotation.Annotation;
import org.aopalliance.aop.Advice;
import com.fr.third.springframework.aop.Pointcut;
import com.fr.third.springframework.aop.support.AbstractPointcutAdvisor;
import com.fr.third.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import com.fr.third.springframework.beans.factory.ListableBeanFactory;
import com.fr.third.springframework.dao.support.PersistenceExceptionTranslationInterceptor;
import com.fr.third.springframework.dao.support.PersistenceExceptionTranslator;
/**
* Spring AOP exception translation aspect for use at Repository or DAO layer level.
* Translates native persistence exceptions into Spring's DataAccessException hierarchy,
* based on a given PersistenceExceptionTranslator.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
* @see com.fr.third.springframework.dao.DataAccessException
* @see com.fr.third.springframework.dao.support.PersistenceExceptionTranslator
*/
@SuppressWarnings("serial")
public class PersistenceExceptionTranslationAdvisor extends AbstractPointcutAdvisor {
private final PersistenceExceptionTranslationInterceptor advice;
private final AnnotationMatchingPointcut pointcut;
/**
* Create a new PersistenceExceptionTranslationAdvisor.
* @param persistenceExceptionTranslator the PersistenceExceptionTranslator to use
* @param repositoryAnnotationType the annotation type to check for
*/
public PersistenceExceptionTranslationAdvisor(
PersistenceExceptionTranslator persistenceExceptionTranslator,
Class<? extends Annotation> repositoryAnnotationType) {
this.advice = new PersistenceExceptionTranslationInterceptor(persistenceExceptionTranslator);
this.pointcut = new AnnotationMatchingPointcut(repositoryAnnotationType, true);
}
/**
* Create a new PersistenceExceptionTranslationAdvisor.
* @param beanFactory the ListableBeanFactory to obtaining all
* PersistenceExceptionTranslators from
* @param repositoryAnnotationType the annotation type to check for
*/
PersistenceExceptionTranslationAdvisor(
ListableBeanFactory beanFactory, Class<? extends Annotation> repositoryAnnotationType) {
this.advice = new PersistenceExceptionTranslationInterceptor(beanFactory);
this.pointcut = new AnnotationMatchingPointcut(repositoryAnnotationType, true);
}
@Override
public Advice getAdvice() {
return this.advice;
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}

89
fine-spring/src/com/fr/third/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.java

@ -0,0 +1,89 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.annotation;
import java.lang.annotation.Annotation;
import com.fr.third.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
import com.fr.third.springframework.beans.factory.BeanFactory;
import com.fr.third.springframework.beans.factory.BeanFactoryAware;
import com.fr.third.springframework.beans.factory.ListableBeanFactory;
import com.fr.third.springframework.stereotype.Repository;
import com.fr.third.springframework.util.Assert;
/**
* Bean post-processor that automatically applies persistence exception translation to any
* bean marked with Spring's @{@link com.fr.third.springframework.stereotype.Repository Repository}
* annotation, adding a corresponding {@link PersistenceExceptionTranslationAdvisor} to
* the exposed proxy (either an existing AOP proxy or a newly generated proxy that
* implements all of the target's interfaces).
*
* <p>Translates native resource exceptions to Spring's
* {@link com.fr.third.springframework.dao.DataAccessException DataAccessException} hierarchy.
* Autodetects beans that implement the
* {@link com.fr.third.springframework.dao.support.PersistenceExceptionTranslator
* PersistenceExceptionTranslator} interface, which are subsequently asked to translate
* candidate exceptions.
*
* <p>All of Spring's applicable resource factories (e.g.
* {@link com.fr.third.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean})
* implement the {@code PersistenceExceptionTranslator} interface out of the box.
* As a consequence, all that is usually needed to enable automatic exception
* translation is marking all affected beans (such as Repositories or DAOs)
* with the {@code @Repository} annotation, along with defining this post-processor
* as a bean in the application context.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
* @see PersistenceExceptionTranslationAdvisor
* @see com.fr.third.springframework.stereotype.Repository
* @see com.fr.third.springframework.dao.DataAccessException
* @see com.fr.third.springframework.dao.support.PersistenceExceptionTranslator
*/
@SuppressWarnings("serial")
public class PersistenceExceptionTranslationPostProcessor extends AbstractAdvisingBeanPostProcessor
implements BeanFactoryAware {
private Class<? extends Annotation> repositoryAnnotationType = Repository.class;
/**
* Set the 'repository' annotation type.
* The default repository annotation type is the {@link Repository} annotation.
* <p>This setter property exists so that developers can provide their own
* (non-Spring-specific) annotation type to indicate that a class has a
* repository role.
* @param repositoryAnnotationType the desired annotation type
*/
public void setRepositoryAnnotationType(Class<? extends Annotation> repositoryAnnotationType) {
Assert.notNull(repositoryAnnotationType, "'repositoryAnnotationType' must not be null");
this.repositoryAnnotationType = repositoryAnnotationType;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ListableBeanFactory)) {
throw new IllegalArgumentException(
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
}
this.advisor = new PersistenceExceptionTranslationAdvisor(
(ListableBeanFactory) beanFactory, this.repositoryAnnotationType);
}
}

9
fine-spring/src/com/fr/third/springframework/dao/annotation/package-info.java

@ -0,0 +1,9 @@
/**
*
* Annotation support for DAOs. Contains a bean post-processor for translating
* persistence exceptions based on a repository stereotype annotation.
*
*/
package com.fr.third.springframework.dao.annotation;

20
fine-spring/src/com/fr/third/springframework/dao/package-info.java

@ -0,0 +1,20 @@
/**
*
* Exception hierarchy enabling sophisticated error handling independent
* of the data access approach in use. For example, when DAOs and data
* access frameworks use the exceptions in this package (and custom
* subclasses), calling code can detect and handle common problems such
* as deadlocks without being tied to a particular data access strategy,
* such as JDBC.
*
* <p>All these exceptions are unchecked, meaning that calling code can
* leave them uncaught and treat all data access exceptions as fatal.
*
* <p>The classes in this package are discussed in Chapter 9 of
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>
* by Rod Johnson (Wrox, 2002).
*
*/
package com.fr.third.springframework.dao;

67
fine-spring/src/com/fr/third/springframework/dao/support/ChainedPersistenceExceptionTranslator.java

@ -0,0 +1,67 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.support;
import java.util.ArrayList;
import java.util.List;
import com.fr.third.springframework.dao.DataAccessException;
import com.fr.third.springframework.util.Assert;
/**
* Implementation of {@link PersistenceExceptionTranslator} that supports chaining,
* allowing the addition of PersistenceExceptionTranslator instances in order.
* Returns {@code non-null} on the first (if any) match.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
*/
public class ChainedPersistenceExceptionTranslator implements PersistenceExceptionTranslator {
/** List of PersistenceExceptionTranslators */
private final List<PersistenceExceptionTranslator> delegates = new ArrayList<PersistenceExceptionTranslator>(4);
/**
* Add a PersistenceExceptionTranslator to the chained delegate list.
*/
public final void addDelegate(PersistenceExceptionTranslator pet) {
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null");
this.delegates.add(pet);
}
/**
* Return all registered PersistenceExceptionTranslator delegates (as array).
*/
public final PersistenceExceptionTranslator[] getDelegates() {
return this.delegates.toArray(new PersistenceExceptionTranslator[this.delegates.size()]);
}
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
for (PersistenceExceptionTranslator pet : this.delegates) {
DataAccessException translatedDex = pet.translateExceptionIfPossible(ex);
if (translatedDex != null) {
return translatedDex;
}
}
return null;
}
}

73
fine-spring/src/com/fr/third/springframework/dao/support/DaoSupport.java

@ -0,0 +1,73 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.beans.factory.BeanInitializationException;
import com.fr.third.springframework.beans.factory.InitializingBean;
/**
* Generic base class for DAOs, defining template methods for DAO initialization.
*
* <p>Extended by Spring's specific DAO support classes, such as:
* JdbcDaoSupport, JdoDaoSupport, etc.
*
* @author Juergen Hoeller
* @since 1.2.2
* @see com.fr.third.springframework.jdbc.core.support.JdbcDaoSupport
*/
public abstract class DaoSupport implements InitializingBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@Override
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
// Let abstract subclasses check their configuration.
checkDaoConfig();
// Let concrete implementations initialize themselves.
try {
initDao();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of DAO failed", ex);
}
}
/**
* Abstract subclasses must override this to check their configuration.
* <p>Implementors should be marked as {@code final} if concrete subclasses
* are not supposed to override this template method themselves.
* @throws IllegalArgumentException in case of illegal configuration
*/
protected abstract void checkDaoConfig() throws IllegalArgumentException;
/**
* Concrete subclasses can override this for custom initialization behavior.
* Gets called after population of this instance's bean properties.
* @throws Exception if DAO initialization fails
* (will be rethrown as a BeanInitializationException)
* @see com.fr.third.springframework.beans.factory.BeanInitializationException
*/
protected void initDao() throws Exception {
}
}

217
fine-spring/src/com/fr/third/springframework/dao/support/DataAccessUtils.java

@ -0,0 +1,217 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.support;
import java.util.Collection;
import com.fr.third.springframework.dao.DataAccessException;
import com.fr.third.springframework.dao.EmptyResultDataAccessException;
import com.fr.third.springframework.dao.IncorrectResultSizeDataAccessException;
import com.fr.third.springframework.dao.TypeMismatchDataAccessException;
import com.fr.third.springframework.util.Assert;
import com.fr.third.springframework.util.CollectionUtils;
import com.fr.third.springframework.util.NumberUtils;
/**
* Miscellaneous utility methods for DAO implementations.
* Useful with any data access technology.
*
* @author Juergen Hoeller
* @since 1.0.2
*/
public abstract class DataAccessUtils {
/**
* Return a single result object from the given Collection.
* <p>Returns {@code null} if 0 result objects found;
* throws an exception if more than 1 element found.
* @param results the result Collection (can be {@code null})
* @return the single result object, or {@code null} if none
* @throws IncorrectResultSizeDataAccessException if more than one
* element has been found in the given Collection
*/
public static <T> T singleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a single result object from the given Collection.
* <p>Throws an exception if 0 or more than 1 element found.
* @param results the result Collection (can be {@code null})
* @return the single result object
* @throws IncorrectResultSizeDataAccessException if more than one
* element has been found in the given Collection
* @throws EmptyResultDataAccessException if no element at all
* has been found in the given Collection
*/
public static <T> T requiredSingleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* <p>Returns {@code null} if 0 result objects found;
* throws an exception if more than 1 instance found.
* @param results the result Collection (can be {@code null})
* @return the unique result object, or {@code null} if none
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @see com.fr.third.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T uniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
}
if (!CollectionUtils.hasUniqueObject(results)) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* <p>Throws an exception if 0 or more than 1 instance found.
* @param results the result Collection (can be {@code null})
* @return the unique result object
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object at all
* has been found in the given Collection
* @see com.fr.third.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T requiredUniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (!CollectionUtils.hasUniqueObject(results)) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
/**
* Return a unique result object from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to the
* specified required type.
* @param results the result Collection (can be {@code null})
* @return the unique result object
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object does
* not match the specified required type
*/
@SuppressWarnings("unchecked")
public static <T> T objectResult(Collection<?> results, Class<T> requiredType)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
Object result = requiredUniqueResult(results);
if (requiredType != null && !requiredType.isInstance(result)) {
if (String.class.equals(requiredType)) {
result = result.toString();
}
else if (Number.class.isAssignableFrom(requiredType) && Number.class.isInstance(result)) {
try {
result = NumberUtils.convertNumberToTargetClass(((Number) result), (Class<? extends Number>) requiredType);
}
catch (IllegalArgumentException ex) {
throw new TypeMismatchDataAccessException(ex.getMessage());
}
}
else {
throw new TypeMismatchDataAccessException(
"Result object is of type [" + result.getClass().getName() +
"] and could not be converted to required type [" + requiredType.getName() + "]");
}
}
return (T) result;
}
/**
* Return a unique int result from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to an int.
* @param results the result Collection (can be {@code null})
* @return the unique int result
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertable to an int
*/
public static int intResult(Collection<?> results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).intValue();
}
/**
* Return a unique long result from the given Collection.
* Throws an exception if 0 or more than 1 result objects found,
* of if the unique result object is not convertable to a long.
* @param results the result Collection (can be {@code null})
* @return the unique long result
* @throws IncorrectResultSizeDataAccessException if more than one
* result object has been found in the given Collection
* @throws EmptyResultDataAccessException if no result object
* at all has been found in the given Collection
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertable to a long
*/
public static long longResult(Collection<?> results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).longValue();
}
/**
* Return a translated exception if this is appropriate,
* otherwise return the input exception.
* @param rawException exception we may wish to translate
* @param pet PersistenceExceptionTranslator to use to perform the translation
* @return a translated exception if translation is possible, or
* the raw exception if it is not
*/
public static RuntimeException translateIfNecessary(
RuntimeException rawException, PersistenceExceptionTranslator pet) {
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null");
DataAccessException dex = pet.translateExceptionIfPossible(rawException);
return (dex != null ? dex : rawException);
}
}

171
fine-spring/src/com/fr/third/springframework/dao/support/PersistenceExceptionTranslationInterceptor.java

@ -0,0 +1,171 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.support;
import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.fr.third.springframework.beans.BeansException;
import com.fr.third.springframework.beans.factory.BeanFactory;
import com.fr.third.springframework.beans.factory.BeanFactoryAware;
import com.fr.third.springframework.beans.factory.BeanFactoryUtils;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.beans.factory.ListableBeanFactory;
import com.fr.third.springframework.util.Assert;
import com.fr.third.springframework.util.ReflectionUtils;
/**
* AOP Alliance MethodInterceptor that provides persistence exception translation
* based on a given PersistenceExceptionTranslator.
*
* <p>Delegates to the given {@link PersistenceExceptionTranslator} to translate
* a RuntimeException thrown into Spring's DataAccessException hierarchy
* (if appropriate). If the RuntimeException in question is declared on the
* target method, it is always propagated as-is (with no translation applied).
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
* @see PersistenceExceptionTranslator
*/
public class PersistenceExceptionTranslationInterceptor
implements MethodInterceptor, BeanFactoryAware, InitializingBean {
private volatile PersistenceExceptionTranslator persistenceExceptionTranslator;
private boolean alwaysTranslate = false;
private ListableBeanFactory beanFactory;
/**
* Create a new PersistenceExceptionTranslationInterceptor.
* Needs to be configured with a PersistenceExceptionTranslator afterwards.
* @see #setPersistenceExceptionTranslator
*/
public PersistenceExceptionTranslationInterceptor() {
}
/**
* Create a new PersistenceExceptionTranslationInterceptor
* for the given PersistenceExceptionTranslator.
* @param pet the PersistenceExceptionTranslator to use
*/
public PersistenceExceptionTranslationInterceptor(PersistenceExceptionTranslator pet) {
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null");
this.persistenceExceptionTranslator = pet;
}
/**
* Create a new PersistenceExceptionTranslationInterceptor, autodetecting
* PersistenceExceptionTranslators in the given BeanFactory.
* @param beanFactory the ListableBeanFactory to obtaining all
* PersistenceExceptionTranslators from
*/
public PersistenceExceptionTranslationInterceptor(ListableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
this.beanFactory = beanFactory;
}
/**
* Specify the PersistenceExceptionTranslator to use.
* <p>Default is to autodetect all PersistenceExceptionTranslators
* in the containing BeanFactory, using them in a chain.
* @see #detectPersistenceExceptionTranslators
*/
public void setPersistenceExceptionTranslator(PersistenceExceptionTranslator pet) {
this.persistenceExceptionTranslator = pet;
}
/**
* Specify whether to always translate the exception ("true"), or whether throw the
* raw exception when declared, i.e. when the originating method signature's exception
* declarations allow for the raw exception to be thrown ("false").
* <p>Default is "false". Switch this flag to "true" in order to always translate
* applicable exceptions, independent from the originating method signature.
* <p>Note that the originating method does not have to declare the specific exception.
* Any base class will do as well, even {@code throws Exception}: As long as the
* originating method does explicitly declare compatible exceptions, the raw exception
* will be rethrown. If you would like to avoid throwing raw exceptions in any case,
* switch this flag to "true".
*/
public void setAlwaysTranslate(boolean alwaysTranslate) {
this.alwaysTranslate = alwaysTranslate;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.persistenceExceptionTranslator == null) {
// No explicit exception translator specified - perform autodetection.
if (!(beanFactory instanceof ListableBeanFactory)) {
throw new IllegalArgumentException(
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory");
}
this.beanFactory = (ListableBeanFactory) beanFactory;
}
}
@Override
public void afterPropertiesSet() {
if (this.persistenceExceptionTranslator == null && this.beanFactory == null) {
throw new IllegalArgumentException("Property 'persistenceExceptionTranslator' is required");
}
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (RuntimeException ex) {
// Let it throw raw if the type of the exception is on the throws clause of the method.
if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) {
throw ex;
}
else {
if (this.persistenceExceptionTranslator == null) {
this.persistenceExceptionTranslator = detectPersistenceExceptionTranslators(this.beanFactory);
}
throw DataAccessUtils.translateIfNecessary(ex, this.persistenceExceptionTranslator);
}
}
}
/**
* Detect all PersistenceExceptionTranslators in the given BeanFactory.
* @param beanFactory the ListableBeanFactory to obtaining all
* PersistenceExceptionTranslators from
* @return a chained PersistenceExceptionTranslator, combining all
* PersistenceExceptionTranslators found in the factory
* @see ChainedPersistenceExceptionTranslator
*/
protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory beanFactory) {
// Find all translators, being careful not to activate FactoryBeans.
Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors(
beanFactory, PersistenceExceptionTranslator.class, false, false);
ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator();
for (PersistenceExceptionTranslator pet : pets.values()) {
cpet.addDelegate(pet);
}
return cpet;
}
}

55
fine-spring/src/com/fr/third/springframework/dao/support/PersistenceExceptionTranslator.java

@ -0,0 +1,55 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.dao.support;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Interface implemented by Spring integrations with data access technologies
* that throw runtime exceptions, such as JPA, TopLink, JDO and Hibernate.
*
* <p>This allows consistent usage of combined exception translation functionality,
* without forcing a single translator to understand every single possible type
* of exception.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 2.0
*/
public interface PersistenceExceptionTranslator {
/**
* Translate the given runtime exception thrown by a persistence framework to a
* corresponding exception from Spring's generic DataAccessException hierarchy,
* if possible.
* <p>Do not translate exceptions that are not understand by this translator:
* for example, if coming from another persistence framework, or resulting
* from user code and unrelated to persistence.
* <p>Of particular importance is the correct translation to
* DataIntegrityViolationException, for example on constraint violation.
* Implementations may use Spring JDBC's sophisticated exception translation
* to provide further information in the event of SQLException as a root cause.
* @param ex a RuntimeException thrown
* @return the corresponding DataAccessException (or {@code null} if the
* exception could not be translated, as in this case it may result from
* user code rather than an actual persistence problem)
* @see com.fr.third.springframework.dao.DataIntegrityViolationException
* @see com.fr.third.springframework.jdbc.support.SQLExceptionTranslator
*/
DataAccessException translateExceptionIfPossible(RuntimeException ex);
}

9
fine-spring/src/com/fr/third/springframework/dao/support/package-info.java

@ -0,0 +1,9 @@
/**
*
* Support classes for DAO implementations,
* providing miscellaneous utility methods.
*
*/
package com.fr.third.springframework.dao.support;

42
fine-spring/src/com/fr/third/springframework/jca/cci/CannotCreateRecordException.java

@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci;
import javax.resource.ResourceException;
import com.fr.third.springframework.dao.DataAccessResourceFailureException;
/**
* Exception thrown when the creating of a CCI Record failed
* for connector-internal reasons.
*
* @author Juergen Hoeller
* @since 1.2
*/
@SuppressWarnings("serial")
public class CannotCreateRecordException extends DataAccessResourceFailureException {
/**
* Constructor for CannotCreateRecordException.
* @param msg message
* @param ex ResourceException root cause
*/
public CannotCreateRecordException(String msg, ResourceException ex) {
super(msg, ex);
}
}

42
fine-spring/src/com/fr/third/springframework/jca/cci/CannotGetCciConnectionException.java

@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci;
import javax.resource.ResourceException;
import com.fr.third.springframework.dao.DataAccessResourceFailureException;
/**
* Fatal exception thrown when we can't connect to an EIS using CCI.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
*/
@SuppressWarnings("serial")
public class CannotGetCciConnectionException extends DataAccessResourceFailureException {
/**
* Constructor for CannotGetCciConnectionException.
* @param msg message
* @param ex ResourceException root cause
*/
public CannotGetCciConnectionException(String msg, ResourceException ex) {
super(msg, ex);
}
}

41
fine-spring/src/com/fr/third/springframework/jca/cci/CciOperationNotSupportedException.java

@ -0,0 +1,41 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci;
import javax.resource.ResourceException;
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* Exception thrown when the connector doesn't support a specific CCI operation.
*
* @author Juergen Hoeller
* @since 1.2
*/
@SuppressWarnings("serial")
public class CciOperationNotSupportedException extends InvalidDataAccessResourceUsageException {
/**
* Constructor for CciOperationNotSupportedException.
* @param msg message
* @param ex ResourceException root cause
*/
public CciOperationNotSupportedException(String msg, ResourceException ex) {
super(msg, ex);
}
}

46
fine-spring/src/com/fr/third/springframework/jca/cci/InvalidResultSetAccessException.java

@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci;
import java.sql.SQLException;
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* Exception thrown when a ResultSet has been accessed in an invalid fashion.
* Such exceptions always have a {@code java.sql.SQLException} root cause.
*
* <p>This typically happens when an invalid ResultSet column index or name
* has been specified.
*
* @author Juergen Hoeller
* @since 1.2
* @see javax.resource.cci.ResultSet
*/
@SuppressWarnings("serial")
public class InvalidResultSetAccessException extends InvalidDataAccessResourceUsageException {
/**
* Constructor for InvalidResultSetAccessException.
* @param msg message
* @param ex the root cause
*/
public InvalidResultSetAccessException(String msg, SQLException ex) {
super(ex.getMessage(), ex);
}
}

42
fine-spring/src/com/fr/third/springframework/jca/cci/RecordTypeNotSupportedException.java

@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci;
import javax.resource.ResourceException;
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* Exception thrown when the creating of a CCI Record failed because
* the connector doesn't support the desired CCI Record type.
*
* @author Juergen Hoeller
* @since 1.2
*/
@SuppressWarnings("serial")
public class RecordTypeNotSupportedException extends InvalidDataAccessResourceUsageException {
/**
* Constructor for RecordTypeNotSupportedException.
* @param msg message
* @param ex ResourceException root cause
*/
public RecordTypeNotSupportedException(String msg, ResourceException ex) {
super(msg, ex);
}
}

274
fine-spring/src/com/fr/third/springframework/jca/cci/connection/CciLocalTransactionManager.java

@ -0,0 +1,274 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.spi.LocalTransactionException;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.transaction.CannotCreateTransactionException;
import com.fr.third.springframework.transaction.TransactionDefinition;
import com.fr.third.springframework.transaction.TransactionException;
import com.fr.third.springframework.transaction.TransactionSystemException;
import com.fr.third.springframework.transaction.support.AbstractPlatformTransactionManager;
import com.fr.third.springframework.transaction.support.DefaultTransactionStatus;
import com.fr.third.springframework.transaction.support.ResourceTransactionManager;
import com.fr.third.springframework.transaction.support.TransactionSynchronizationManager;
/**
* {@link com.fr.third.springframework.transaction.PlatformTransactionManager} implementation
* that manages local transactions for a single CCI ConnectionFactory.
* Binds a CCI Connection from the specified ConnectionFactory to the thread,
* potentially allowing for one thread-bound Connection per ConnectionFactory.
*
* <p>Application code is required to retrieve the CCI Connection via
* {@link ConnectionFactoryUtils#getConnection(ConnectionFactory)} instead of a standard
* J2EE-style {@link ConnectionFactory#getConnection()} call. Spring classes such as
* {@link com.fr.third.springframework.jca.cci.core.CciTemplate} use this strategy implicitly.
* If not used in combination with this transaction manager, the
* {@link ConnectionFactoryUtils} lookup strategy behaves exactly like the native
* DataSource lookup; it can thus be used in a portable fashion.
*
* <p>Alternatively, you can allow application code to work with the standard
* J2EE lookup pattern {@link ConnectionFactory#getConnection()}, for example
* for legacy code that is not aware of Spring at all. In that case, define a
* {@link TransactionAwareConnectionFactoryProxy} for your target ConnectionFactory,
* which will automatically participate in Spring-managed transactions.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
* @see ConnectionFactoryUtils#releaseConnection
* @see TransactionAwareConnectionFactoryProxy
* @see com.fr.third.springframework.jca.cci.core.CciTemplate
*/
@SuppressWarnings("serial")
public class CciLocalTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
private ConnectionFactory connectionFactory;
/**
* Create a new CciLocalTransactionManager instance.
* A ConnectionFactory has to be set to be able to use it.
* @see #setConnectionFactory
*/
public CciLocalTransactionManager() {
}
/**
* Create a new CciLocalTransactionManager instance.
* @param connectionFactory CCI ConnectionFactory to manage local transactions for
*/
public CciLocalTransactionManager(ConnectionFactory connectionFactory) {
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}
/**
* Set the CCI ConnectionFactory that this instance should manage local
* transactions for.
*/
public void setConnectionFactory(ConnectionFactory cf) {
if (cf instanceof TransactionAwareConnectionFactoryProxy) {
// If we got a TransactionAwareConnectionFactoryProxy, we need to perform transactions
// for its underlying target ConnectionFactory, else JMS access code won't see
// properly exposed transactions (i.e. transactions for the target ConnectionFactory).
this.connectionFactory = ((TransactionAwareConnectionFactoryProxy) cf).getTargetConnectionFactory();
}
else {
this.connectionFactory = cf;
}
}
/**
* Return the CCI ConnectionFactory that this instance manages local
* transactions for.
*/
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
@Override
public void afterPropertiesSet() {
if (getConnectionFactory() == null) {
throw new IllegalArgumentException("Property 'connectionFactory' is required");
}
}
@Override
public Object getResourceFactory() {
return getConnectionFactory();
}
@Override
protected Object doGetTransaction() {
CciLocalTransactionObject txObject = new CciLocalTransactionObject();
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(getConnectionFactory());
txObject.setConnectionHolder(conHolder);
return txObject;
}
@Override
protected boolean isExistingTransaction(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
// Consider a pre-bound connection as transaction.
return (txObject.getConnectionHolder() != null);
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
Connection con = null;
try {
con = getConnectionFactory().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + con + "] for local CCI transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(con));
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con.getLocalTransaction().begin();
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getConnectionHolder());
}
catch (NotSupportedException ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
throw new CannotCreateTransactionException("CCI Connection does not support local transactions", ex);
}
catch (LocalTransactionException ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
throw new CannotCreateTransactionException("Could not begin local CCI transaction", ex);
}
catch (Throwable ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
throw new TransactionSystemException("Unexpected failure on begin of CCI local transaction", ex);
}
}
@Override
protected Object doSuspend(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(getConnectionFactory());
}
@Override
protected void doResume(Object transaction, Object suspendedResources) {
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
TransactionSynchronizationManager.bindResource(getConnectionFactory(), conHolder);
}
protected boolean isRollbackOnly(Object transaction) throws TransactionException {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
return txObject.getConnectionHolder().isRollbackOnly();
}
@Override
protected void doCommit(DefaultTransactionStatus status) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing CCI local transaction on Connection [" + con + "]");
}
try {
con.getLocalTransaction().commit();
}
catch (LocalTransactionException ex) {
throw new TransactionSystemException("Could not commit CCI local transaction", ex);
}
catch (ResourceException ex) {
throw new TransactionSystemException("Unexpected failure on commit of CCI local transaction", ex);
}
}
@Override
protected void doRollback(DefaultTransactionStatus status) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back CCI local transaction on Connection [" + con + "]");
}
try {
con.getLocalTransaction().rollback();
}
catch (LocalTransactionException ex) {
throw new TransactionSystemException("Could not roll back CCI local transaction", ex);
}
catch (ResourceException ex) {
throw new TransactionSystemException("Unexpected failure on rollback of CCI local transaction", ex);
}
}
@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Setting CCI local transaction [" + txObject.getConnectionHolder().getConnection() +
"] rollback-only");
}
txObject.getConnectionHolder().setRollbackOnly();
}
@Override
protected void doCleanupAfterCompletion(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
// Remove the connection holder from the thread.
TransactionSynchronizationManager.unbindResource(getConnectionFactory());
txObject.getConnectionHolder().clear();
Connection con = txObject.getConnectionHolder().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Releasing CCI Connection [" + con + "] after transaction");
}
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
}
/**
* CCI local transaction object, representing a ConnectionHolder.
* Used as transaction object by CciLocalTransactionManager.
* @see ConnectionHolder
*/
private static class CciLocalTransactionObject {
private ConnectionHolder connectionHolder;
public void setConnectionHolder(ConnectionHolder connectionHolder) {
this.connectionHolder = connectionHolder;
}
public ConnectionHolder getConnectionHolder() {
return this.connectionHolder;
}
}
}

214
fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionFactoryUtils.java

@ -0,0 +1,214 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.jca.cci.CannotGetCciConnectionException;
import com.fr.third.springframework.transaction.support.ResourceHolderSynchronization;
import com.fr.third.springframework.transaction.support.TransactionSynchronizationManager;
import com.fr.third.springframework.util.Assert;
/**
* Helper class that provides static methods for obtaining CCI Connections
* from a {@link javax.resource.cci.ConnectionFactory}. Includes special
* support for Spring-managed transactional Connections, e.g. managed
* by {@link CciLocalTransactionManager} or
* {@link com.fr.third.springframework.transaction.jta.JtaTransactionManager}.
*
* <p>Used internally by {@link com.fr.third.springframework.jca.cci.core.CciTemplate},
* Spring's CCI operation objects and the {@link CciLocalTransactionManager}.
* Can also be used directly in application code.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see #getConnection
* @see #releaseConnection
* @see CciLocalTransactionManager
* @see com.fr.third.springframework.transaction.jta.JtaTransactionManager
* @see com.fr.third.springframework.transaction.support.TransactionSynchronizationManager
*/
public abstract class ConnectionFactoryUtils {
private static final Log logger = LogFactory.getLog(ConnectionFactoryUtils.class);
/**
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying
* calling code and making any exception that is thrown more meaningful.
* <p>Is aware of a corresponding Connection bound to the current thread, for example
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
* if transaction synchronization is active (e.g. if in a JTA transaction).
* @param cf the ConnectionFactory to obtain Connection from
* @return a CCI Connection from the given ConnectionFactory
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException
* if the attempt to get a Connection failed
* @see #releaseConnection
*/
public static Connection getConnection(ConnectionFactory cf) throws CannotGetCciConnectionException {
return getConnection(cf, null);
}
/**
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying
* calling code and making any exception that is thrown more meaningful.
* <p>Is aware of a corresponding Connection bound to the current thread, for example
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
* if transaction synchronization is active (e.g. if in a JTA transaction).
* @param cf the ConnectionFactory to obtain Connection from
* @param spec the ConnectionSpec for the desired Connection (may be {@code null}).
* Note: If this is specified, a new Connection will be obtained for every call,
* without participating in a shared transactional Connection.
* @return a CCI Connection from the given ConnectionFactory
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException
* if the attempt to get a Connection failed
* @see #releaseConnection
*/
public static Connection getConnection(ConnectionFactory cf, ConnectionSpec spec)
throws CannotGetCciConnectionException {
try {
if (spec != null) {
Assert.notNull(cf, "No ConnectionFactory specified");
return cf.getConnection(spec);
}
else {
return doGetConnection(cf);
}
}
catch (ResourceException ex) {
throw new CannotGetCciConnectionException("Could not get CCI Connection", ex);
}
}
/**
* Actually obtain a CCI Connection from the given ConnectionFactory.
* Same as {@link #getConnection}, but throwing the original ResourceException.
* <p>Is aware of a corresponding Connection bound to the current thread, for example
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
* if transaction synchronization is active (e.g. if in a JTA transaction).
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
* @param cf the ConnectionFactory to obtain Connection from
* @return a CCI Connection from the given ConnectionFactory
* @throws ResourceException if thrown by CCI API methods
* @see #doReleaseConnection
*/
public static Connection doGetConnection(ConnectionFactory cf) throws ResourceException {
Assert.notNull(cf, "No ConnectionFactory specified");
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
if (conHolder != null) {
return conHolder.getConnection();
}
logger.debug("Opening CCI Connection");
Connection con = cf.getConnection();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
logger.debug("Registering transaction synchronization for CCI Connection");
conHolder = new ConnectionHolder(con);
conHolder.setSynchronizedWithTransaction(true);
TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, cf));
TransactionSynchronizationManager.bindResource(cf, conHolder);
}
return con;
}
/**
* Determine whether the given JCA CCI Connection is transactional, that is,
* bound to the current thread by Spring's transaction facilities.
* @param con the Connection to check
* @param cf the ConnectionFactory that the Connection was obtained from
* (may be {@code null})
* @return whether the Connection is transactional
*/
public static boolean isConnectionTransactional(Connection con, ConnectionFactory cf) {
if (cf == null) {
return false;
}
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
return (conHolder != null && conHolder.getConnection() == con);
}
/**
* Close the given Connection, obtained from the given ConnectionFactory,
* if it is not managed externally (that is, not bound to the thread).
* @param con the Connection to close if necessary
* (if this is {@code null}, the call will be ignored)
* @param cf the ConnectionFactory that the Connection was obtained from
* (can be {@code null})
* @see #getConnection
*/
public static void releaseConnection(Connection con, ConnectionFactory cf) {
try {
doReleaseConnection(con, cf);
}
catch (ResourceException ex) {
logger.debug("Could not close CCI Connection", ex);
}
catch (Throwable ex) {
// We don't trust the CCI driver: It might throw RuntimeException or Error.
logger.debug("Unexpected exception on closing CCI Connection", ex);
}
}
/**
* Actually close the given Connection, obtained from the given ConnectionFactory.
* Same as {@link #releaseConnection}, but throwing the original ResourceException.
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
* @param con the Connection to close if necessary
* (if this is {@code null}, the call will be ignored)
* @param cf the ConnectionFactory that the Connection was obtained from
* (can be {@code null})
* @throws ResourceException if thrown by JCA CCI methods
* @see #doGetConnection
*/
public static void doReleaseConnection(Connection con, ConnectionFactory cf) throws ResourceException {
if (con == null || isConnectionTransactional(con, cf)) {
return;
}
con.close();
}
/**
* Callback for resource cleanup at the end of a non-native CCI transaction
* (e.g. when participating in a JTA transaction).
*/
private static class ConnectionSynchronization
extends ResourceHolderSynchronization<ConnectionHolder, ConnectionFactory> {
public ConnectionSynchronization(ConnectionHolder connectionHolder, ConnectionFactory connectionFactory) {
super(connectionHolder, connectionFactory);
}
@Override
protected void releaseResource(ConnectionHolder resourceHolder, ConnectionFactory resourceKey) {
releaseConnection(resourceHolder.getConnection(), resourceKey);
}
}
}

49
fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionHolder.java

@ -0,0 +1,49 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.resource.cci.Connection;
import com.fr.third.springframework.transaction.support.ResourceHolderSupport;
/**
* Connection holder, wrapping a CCI Connection.
*
* <p>CciLocalTransactionManager binds instances of this class
* to the thread, for a given ConnectionFactory.
*
* <p>Note: This is an SPI class, not intended to be used by applications.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see CciLocalTransactionManager
* @see ConnectionFactoryUtils
*/
public class ConnectionHolder extends ResourceHolderSupport {
private final Connection connection;
public ConnectionHolder(Connection connection) {
this.connection = connection;
}
public Connection getConnection() {
return this.connection;
}
}

143
fine-spring/src/com/fr/third/springframework/jca/cci/connection/ConnectionSpecConnectionFactoryAdapter.java

@ -0,0 +1,143 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionSpec;
import com.fr.third.springframework.core.NamedThreadLocal;
/**
* An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory},
* applying the given ConnectionSpec to every standard {@code getConnection()}
* call, that is, implicitly invoking {@code getConnection(ConnectionSpec)}
* on the target. All other methods simply delegate to the corresponding methods
* of the target ConnectionFactory.
*
* <p>Can be used to proxy a target JNDI ConnectionFactory that does not have a
* ConnectionSpec configured. Client code can work with the ConnectionFactory
* without passing in a ConnectionSpec on every {@code getConnection()} call.
*
* <p>In the following example, client code can simply transparently work with
* the preconfigured "myConnectionFactory", implicitly accessing
* "myTargetConnectionFactory" with the specified user credentials.
*
* <pre class="code">
* &lt;bean id="myTargetConnectionFactory" class="com.fr.third.springframework.jndi.JndiObjectFactoryBean"&gt;
* &lt;property name="jndiName" value="java:comp/env/cci/mycf"/&gt;
* &lt;/bean>
*
* &lt;bean id="myConnectionFactory" class="com.fr.third.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter"&gt;
* &lt;property name="targetConnectionFactory" ref="myTargetConnectionFactory"/&gt;
* &lt;property name="connectionSpec"&gt;
* &lt;bean class="your.resource.adapter.ConnectionSpecImpl"&gt;
* &lt;property name="username" value="myusername"/&gt;
* &lt;property name="password" value="mypassword"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* <p>If the "connectionSpec" is empty, this proxy will simply delegate to the
* standard {@code getConnection()} method of the target ConnectionFactory.
* This can be used to keep a UserCredentialsConnectionFactoryAdapter bean definition
* just for the <i>option</i> of implicitly passing in a ConnectionSpec if the
* particular target ConnectionFactory requires it.
*
* @author Juergen Hoeller
* @since 1.2
* @see #getConnection
*/
@SuppressWarnings("serial")
public class ConnectionSpecConnectionFactoryAdapter extends DelegatingConnectionFactory {
private ConnectionSpec connectionSpec;
private final ThreadLocal<ConnectionSpec> threadBoundSpec =
new NamedThreadLocal<ConnectionSpec>("Current CCI ConnectionSpec");
/**
* Set the ConnectionSpec that this adapter should use for retrieving Connections.
* Default is none.
*/
public void setConnectionSpec(ConnectionSpec connectionSpec) {
this.connectionSpec = connectionSpec;
}
/**
* Set a ConnectionSpec for this proxy and the current thread.
* The given ConnectionSpec will be applied to all subsequent
* {@code getConnection()} calls on this ConnectionFactory proxy.
* <p>This will override any statically specified "connectionSpec" property.
* @param spec the ConnectionSpec to apply
* @see #removeConnectionSpecFromCurrentThread
*/
public void setConnectionSpecForCurrentThread(ConnectionSpec spec) {
this.threadBoundSpec.set(spec);
}
/**
* Remove any ConnectionSpec for this proxy from the current thread.
* A statically specified ConnectionSpec applies again afterwards.
* @see #setConnectionSpecForCurrentThread
*/
public void removeConnectionSpecFromCurrentThread() {
this.threadBoundSpec.remove();
}
/**
* Determine whether there is currently a thread-bound ConnectionSpec,
* using it if available, falling back to the statically specified
* "connectionSpec" property else.
* @see #doGetConnection
*/
@Override
public final Connection getConnection() throws ResourceException {
ConnectionSpec threadSpec = this.threadBoundSpec.get();
if (threadSpec != null) {
return doGetConnection(threadSpec);
}
else {
return doGetConnection(this.connectionSpec);
}
}
/**
* This implementation delegates to the {@code getConnection(ConnectionSpec)}
* method of the target ConnectionFactory, passing in the specified user credentials.
* If the specified username is empty, it will simply delegate to the standard
* {@code getConnection()} method of the target ConnectionFactory.
* @param spec the ConnectionSpec to apply
* @return the Connection
* @see javax.resource.cci.ConnectionFactory#getConnection(javax.resource.cci.ConnectionSpec)
* @see javax.resource.cci.ConnectionFactory#getConnection()
*/
protected Connection doGetConnection(ConnectionSpec spec) throws ResourceException {
if (getTargetConnectionFactory() == null) {
throw new IllegalStateException("targetConnectionFactory is required");
}
if (spec != null) {
return getTargetConnectionFactory().getConnection(spec);
}
else {
return getTargetConnectionFactory().getConnection();
}
}
}

101
fine-spring/src/com/fr/third/springframework/jca/cci/connection/DelegatingConnectionFactory.java

@ -0,0 +1,101 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import javax.resource.cci.RecordFactory;
import javax.resource.cci.ResourceAdapterMetaData;
import com.fr.third.springframework.beans.factory.InitializingBean;
/**
* CCI {@link ConnectionFactory} implementation that delegates all calls
* to a given target {@link ConnectionFactory}.
*
* <p>This class is meant to be subclassed, with subclasses overriding only
* those methods (such as {@link #getConnection()}) that should not simply
* delegate to the target {@link ConnectionFactory}.
*
* @author Juergen Hoeller
* @since 1.2
* @see #getConnection
*/
@SuppressWarnings("serial")
public class DelegatingConnectionFactory implements ConnectionFactory, InitializingBean {
private ConnectionFactory targetConnectionFactory;
/**
* Set the target ConnectionFactory that this ConnectionFactory should delegate to.
*/
public void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) {
this.targetConnectionFactory = targetConnectionFactory;
}
/**
* Return the target ConnectionFactory that this ConnectionFactory should delegate to.
*/
public ConnectionFactory getTargetConnectionFactory() {
return this.targetConnectionFactory;
}
@Override
public void afterPropertiesSet() {
if (getTargetConnectionFactory() == null) {
throw new IllegalArgumentException("Property 'targetConnectionFactory' is required");
}
}
@Override
public Connection getConnection() throws ResourceException {
return getTargetConnectionFactory().getConnection();
}
@Override
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {
return getTargetConnectionFactory().getConnection(connectionSpec);
}
@Override
public RecordFactory getRecordFactory() throws ResourceException {
return getTargetConnectionFactory().getRecordFactory();
}
@Override
public ResourceAdapterMetaData getMetaData() throws ResourceException {
return getTargetConnectionFactory().getMetaData();
}
@Override
public Reference getReference() throws NamingException {
return getTargetConnectionFactory().getReference();
}
@Override
public void setReference(Reference reference) {
getTargetConnectionFactory().setReference(reference);
}
}

54
fine-spring/src/com/fr/third/springframework/jca/cci/connection/NotSupportedRecordFactory.java

@ -0,0 +1,54 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.IndexedRecord;
import javax.resource.cci.MappedRecord;
import javax.resource.cci.RecordFactory;
/**
* Implementation of the CCI RecordFactory interface that always throws
* NotSupportedException.
*
* <p>Useful as a placeholder for a RecordFactory argument (for example as
* defined by the RecordCreator callback), in particular when the connector's
* {@code ConnectionFactory.getRecordFactory()} implementation happens to
* throw NotSupportedException early rather than throwing the exception from
* RecordFactory's methods.
*
* @author Juergen Hoeller
* @since 1.2.4
* @see com.fr.third.springframework.jca.cci.core.RecordCreator#createRecord(javax.resource.cci.RecordFactory)
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#getRecordFactory(javax.resource.cci.ConnectionFactory)
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
* @see javax.resource.NotSupportedException
*/
public class NotSupportedRecordFactory implements RecordFactory {
@Override
public MappedRecord createMappedRecord(String name) throws ResourceException {
throw new NotSupportedException("The RecordFactory facility is not supported by the connector");
}
@Override
public IndexedRecord createIndexedRecord(String name) throws ResourceException {
throw new NotSupportedException("The RecordFactory facility is not supported by the connector");
}
}

255
fine-spring/src/com/fr/third/springframework/jca/cci/connection/SingleConnectionFactory.java

@ -0,0 +1,255 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.beans.factory.DisposableBean;
import com.fr.third.springframework.util.Assert;
/**
* A CCI ConnectionFactory adapter that returns the same Connection on all
* {@code getConnection} calls, and ignores calls to
* {@code Connection.close()}.
*
* <p>Useful for testing and standalone environments, to keep using the same
* Connection for multiple CciTemplate calls, without having a pooling
* ConnectionFactory, also spanning any number of transactions.
*
* <p>You can either pass in a CCI Connection directly, or let this
* factory lazily create a Connection via a given target ConnectionFactory.
*
* @author Juergen Hoeller
* @since 1.2
* @see #getConnection()
* @see javax.resource.cci.Connection#close()
* @see com.fr.third.springframework.jca.cci.core.CciTemplate
*/
@SuppressWarnings("serial")
public class SingleConnectionFactory extends DelegatingConnectionFactory implements DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
/** Wrapped Connection */
private Connection target;
/** Proxy Connection */
private Connection connection;
/** Synchronization monitor for the shared Connection */
private final Object connectionMonitor = new Object();
/**
* Create a new SingleConnectionFactory for bean-style usage.
* @see #setTargetConnectionFactory
*/
public SingleConnectionFactory() {
}
/**
* Create a new SingleConnectionFactory that always returns the
* given Connection.
* @param target the single Connection
*/
public SingleConnectionFactory(Connection target) {
Assert.notNull(target, "Target Connection must not be null");
this.target = target;
this.connection = getCloseSuppressingConnectionProxy(target);
}
/**
* Create a new SingleConnectionFactory that always returns a single
* Connection which it will lazily create via the given target
* ConnectionFactory.
* @param targetConnectionFactory the target ConnectionFactory
*/
public SingleConnectionFactory(ConnectionFactory targetConnectionFactory) {
Assert.notNull(targetConnectionFactory, "Target ConnectionFactory must not be null");
setTargetConnectionFactory(targetConnectionFactory);
}
/**
* Make sure a Connection or ConnectionFactory has been set.
*/
@Override
public void afterPropertiesSet() {
if (this.connection == null && getTargetConnectionFactory() == null) {
throw new IllegalArgumentException("Connection or 'targetConnectionFactory' is required");
}
}
@Override
public Connection getConnection() throws ResourceException {
synchronized (this.connectionMonitor) {
if (this.connection == null) {
initConnection();
}
return this.connection;
}
}
@Override
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {
throw new NotSupportedException(
"SingleConnectionFactory does not support custom ConnectionSpec");
}
/**
* Close the underlying Connection.
* The provider of this ConnectionFactory needs to care for proper shutdown.
* <p>As this bean implements DisposableBean, a bean factory will
* automatically invoke this on destruction of its cached singletons.
*/
@Override
public void destroy() {
resetConnection();
}
/**
* Initialize the single underlying Connection.
* <p>Closes and reinitializes the Connection if an underlying
* Connection is present already.
* @throws javax.resource.ResourceException if thrown by CCI API methods
*/
public void initConnection() throws ResourceException {
if (getTargetConnectionFactory() == null) {
throw new IllegalStateException(
"'targetConnectionFactory' is required for lazily initializing a Connection");
}
synchronized (this.connectionMonitor) {
if (this.target != null) {
closeConnection(this.target);
}
this.target = doCreateConnection();
prepareConnection(this.target);
if (logger.isInfoEnabled()) {
logger.info("Established shared CCI Connection: " + this.target);
}
this.connection = getCloseSuppressingConnectionProxy(this.target);
}
}
/**
* Reset the underlying shared Connection, to be reinitialized on next access.
*/
public void resetConnection() {
synchronized (this.connectionMonitor) {
if (this.target != null) {
closeConnection(this.target);
}
this.target = null;
this.connection = null;
}
}
/**
* Create a CCI Connection via this template's ConnectionFactory.
* @return the new CCI Connection
* @throws javax.resource.ResourceException if thrown by CCI API methods
*/
protected Connection doCreateConnection() throws ResourceException {
return getTargetConnectionFactory().getConnection();
}
/**
* Prepare the given Connection before it is exposed.
* <p>The default implementation is empty. Can be overridden in subclasses.
* @param con the Connection to prepare
*/
protected void prepareConnection(Connection con) throws ResourceException {
}
/**
* Close the given Connection.
* @param con the Connection to close
*/
protected void closeConnection(Connection con) {
try {
con.close();
}
catch (Throwable ex) {
logger.warn("Could not close shared CCI Connection", ex);
}
}
/**
* Wrap the given Connection with a proxy that delegates every method call to it
* but suppresses close calls. This is useful for allowing application code to
* handle a special framework Connection just like an ordinary Connection from a
* CCI ConnectionFactory.
* @param target the original Connection to wrap
* @return the wrapped Connection
*/
protected Connection getCloseSuppressingConnectionProxy(Connection target) {
return (Connection) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class<?>[] {Connection.class},
new CloseSuppressingInvocationHandler(target));
}
/**
* Invocation handler that suppresses close calls on CCI Connections.
*/
private static class CloseSuppressingInvocationHandler implements InvocationHandler {
private final Connection target;
private CloseSuppressingInvocationHandler(Connection target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("close")) {
// Handle close method: don't pass the call on.
return null;
}
try {
return method.invoke(this.target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}

165
fine-spring/src/com/fr/third/springframework/jca/cci/connection/TransactionAwareConnectionFactoryProxy.java

@ -0,0 +1,165 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.connection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
/**
* Proxy for a target CCI {@link javax.resource.cci.ConnectionFactory}, adding
* awareness of Spring-managed transactions. Similar to a transactional JNDI
* ConnectionFactory as provided by a J2EE server.
*
* <p>Data access code that should remain unaware of Spring's data access support
* can work with this proxy to seamlessly participate in Spring-managed transactions.
* Note that the transaction manager, for example the {@link CciLocalTransactionManager},
* still needs to work with underlying ConnectionFactory, <i>not</i> with this proxy.
*
* <p><b>Make sure that TransactionAwareConnectionFactoryProxy is the outermost
* ConnectionFactory of a chain of ConnectionFactory proxies/adapters.</b>
* TransactionAwareConnectionFactoryProxy can delegate either directly to the
* target connection pool or to some intermediate proxy/adapter like
* {@link ConnectionSpecConnectionFactoryAdapter}.
*
* <p>Delegates to {@link ConnectionFactoryUtils} for automatically participating in
* thread-bound transactions, for example managed by {@link CciLocalTransactionManager}.
* {@code getConnection} calls and {@code close} calls on returned Connections
* will behave properly within a transaction, i.e. always operate on the transactional
* Connection. If not within a transaction, normal ConnectionFactory behavior applies.
*
* <p>This proxy allows data access code to work with the plain JCA CCI API and still
* participate in Spring-managed transactions, similar to CCI code in a J2EE/JTA
* environment. However, if possible, use Spring's ConnectionFactoryUtils, CciTemplate or
* CCI operation objects to get transaction participation even without a proxy for
* the target ConnectionFactory, avoiding the need to define such a proxy in the first place.
*
* <p><b>NOTE:</b> This ConnectionFactory proxy needs to return wrapped Connections
* in order to handle close calls properly. Therefore, the returned Connections cannot
* be cast to a native CCI Connection type or to a connection pool implementation type.
*
* @author Juergen Hoeller
* @since 1.2
* @see javax.resource.cci.ConnectionFactory#getConnection
* @see javax.resource.cci.Connection#close
* @see ConnectionFactoryUtils#doGetConnection
* @see ConnectionFactoryUtils#doReleaseConnection
*/
@SuppressWarnings("serial")
public class TransactionAwareConnectionFactoryProxy extends DelegatingConnectionFactory {
/**
* Create a new TransactionAwareConnectionFactoryProxy.
* @see #setTargetConnectionFactory
*/
public TransactionAwareConnectionFactoryProxy() {
}
/**
* Create a new TransactionAwareConnectionFactoryProxy.
* @param targetConnectionFactory the target ConnectionFactory
*/
public TransactionAwareConnectionFactoryProxy(ConnectionFactory targetConnectionFactory) {
setTargetConnectionFactory(targetConnectionFactory);
afterPropertiesSet();
}
/**
* Delegate to ConnectionFactoryUtils for automatically participating in Spring-managed
* transactions. Throws the original ResourceException, if any.
* @return a transactional Connection if any, a new one else
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#doGetConnection
*/
@Override
public Connection getConnection() throws ResourceException {
Connection con = ConnectionFactoryUtils.doGetConnection(getTargetConnectionFactory());
return getTransactionAwareConnectionProxy(con, getTargetConnectionFactory());
}
/**
* Wrap the given Connection with a proxy that delegates every method call to it
* but delegates {@code close} calls to ConnectionFactoryUtils.
* @param target the original Connection to wrap
* @param cf ConnectionFactory that the Connection came from
* @return the wrapped Connection
* @see javax.resource.cci.Connection#close()
* @see ConnectionFactoryUtils#doReleaseConnection
*/
protected Connection getTransactionAwareConnectionProxy(Connection target, ConnectionFactory cf) {
return (Connection) Proxy.newProxyInstance(
Connection.class.getClassLoader(),
new Class<?>[] {Connection.class},
new TransactionAwareInvocationHandler(target, cf));
}
/**
* Invocation handler that delegates close calls on CCI Connections
* to ConnectionFactoryUtils for being aware of thread-bound transactions.
*/
private static class TransactionAwareInvocationHandler implements InvocationHandler {
private final Connection target;
private final ConnectionFactory connectionFactory;
public TransactionAwareInvocationHandler(Connection target, ConnectionFactory cf) {
this.target = target;
this.connectionFactory = cf;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Connection interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Connection proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("getLocalTransaction")) {
if (ConnectionFactoryUtils.isConnectionTransactional(this.target, this.connectionFactory)) {
throw new javax.resource.spi.IllegalStateException(
"Local transaction handling not allowed within a managed transaction");
}
}
else if (method.getName().equals("close")) {
// Handle close method: only close if not within a transaction.
ConnectionFactoryUtils.doReleaseConnection(this.target, this.connectionFactory);
return null;
}
// Invoke method on target Connection.
try {
return method.invoke(this.target, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
}

10
fine-spring/src/com/fr/third/springframework/jca/cci/connection/package-info.java

@ -0,0 +1,10 @@
/**
*
* Provides a utility class for easy ConnectionFactory access,
* a PlatformTransactionManager for local CCI transactions,
* and various simple ConnectionFactory proxies/adapters.
*
*/
package com.fr.third.springframework.jca.cci.connection;

121
fine-spring/src/com/fr/third/springframework/jca/cci/core/CciOperations.java

@ -0,0 +1,121 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.Record;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Interface that specifies a basic set of CCI operations on an EIS.
* Implemented by CciTemplate. Not often used, but a useful option
* to enhance testability, as it can easily be mocked or stubbed.
*
* <p>Alternatively, the standard CCI infrastructure can be mocked.
* However, mocking this interface constitutes significantly less work.
*
* @author Juergen Hoeller
* @since 1.2
* @see CciTemplate
*/
public interface CciOperations {
/**
* Execute a request on an EIS with CCI, implemented as callback action
* working on a CCI Connection. This allows for implementing arbitrary
* data access operations, within Spring's managed CCI environment:
* that is, participating in Spring-managed transactions and converting
* JCA ResourceExceptions into Spring's DataAccessException hierarchy.
* <p>The callback action can return a result object, for example a
* domain object or a collection of domain objects.
* @param action the callback object that specifies the action
* @return the result object returned by the action, if any
* @throws DataAccessException if there is any problem
*/
<T> T execute(ConnectionCallback<T> action) throws DataAccessException;
/**
* Execute a request on an EIS with CCI, implemented as callback action
* working on a CCI Interaction. This allows for implementing arbitrary
* data access operations on a single Interaction, within Spring's managed
* CCI environment: that is, participating in Spring-managed transactions
* and converting JCA ResourceExceptions into Spring's DataAccessException
* hierarchy.
* <p>The callback action can return a result object, for example a
* domain object or a collection of domain objects.
* @param action the callback object that specifies the action
* @return the result object returned by the action, if any
* @throws DataAccessException if there is any problem
*/
<T> T execute(InteractionCallback<T> action) throws DataAccessException;
/**
* Execute the specified interaction on an EIS with CCI.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputRecord the input record
* @return the output record
* @throws DataAccessException if there is any problem
*/
Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException;
/**
* Execute the specified interaction on an EIS with CCI.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputRecord the input record
* @param outputRecord the output record
* @throws DataAccessException if there is any problem
*/
void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException;
/**
* Execute the specified interaction on an EIS with CCI.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputCreator object that creates the input record to use
* @return the output record
* @throws DataAccessException if there is any problem
*/
Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException;
/**
* Execute the specified interaction on an EIS with CCI.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputRecord the input record
* @param outputExtractor object to convert the output record to a result object
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
<T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor)
throws DataAccessException;
/**
* Execute the specified interaction on an EIS with CCI.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputCreator object that creates the input record to use
* @param outputExtractor object to convert the output record to a result object
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
<T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor)
throws DataAccessException;
}

439
fine-spring/src/com/fr/third/springframework/jca/cci/core/CciTemplate.java

@ -0,0 +1,439 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import javax.resource.cci.IndexedRecord;
import javax.resource.cci.Interaction;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.MappedRecord;
import javax.resource.cci.Record;
import javax.resource.cci.RecordFactory;
import javax.resource.cci.ResultSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.dao.DataAccessException;
import com.fr.third.springframework.dao.DataAccessResourceFailureException;
import com.fr.third.springframework.jca.cci.CannotCreateRecordException;
import com.fr.third.springframework.jca.cci.CciOperationNotSupportedException;
import com.fr.third.springframework.jca.cci.InvalidResultSetAccessException;
import com.fr.third.springframework.jca.cci.RecordTypeNotSupportedException;
import com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils;
import com.fr.third.springframework.jca.cci.connection.NotSupportedRecordFactory;
import com.fr.third.springframework.util.Assert;
/**
* <b>This is the central class in the CCI core package.</b>
* It simplifies the use of CCI and helps to avoid common errors.
* It executes core CCI workflow, leaving application code to provide parameters
* to CCI and extract results. This class executes EIS queries or updates,
* catching ResourceExceptions and translating them to the generic exception
* hierarchy defined in the {@code com.fr.third.springframework.dao} package.
*
* <p>Code using this class can pass in and receive {@link javax.resource.cci.Record}
* instances, or alternatively implement callback interfaces for creating input
* Records and extracting result objects from output Records (or CCI ResultSets).
*
* <p>Can be used within a service implementation via direct instantiation
* with a ConnectionFactory reference, or get prepared in an application context
* and given to services as bean reference. Note: The ConnectionFactory should
* always be configured as a bean in the application context, in the first case
* given to the service directly, in the second case to the prepared template.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see RecordCreator
* @see RecordExtractor
*/
public class CciTemplate implements CciOperations {
private final Log logger = LogFactory.getLog(getClass());
private ConnectionFactory connectionFactory;
private ConnectionSpec connectionSpec;
private RecordCreator outputRecordCreator;
/**
* Construct a new CciTemplate for bean usage.
* <p>Note: The ConnectionFactory has to be set before using the instance.
* @see #setConnectionFactory
*/
public CciTemplate() {
}
/**
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from.
* Note: This will trigger eager initialization of the exception translator.
* @param connectionFactory JCA ConnectionFactory to obtain Connections from
*/
public CciTemplate(ConnectionFactory connectionFactory) {
setConnectionFactory(connectionFactory);
afterPropertiesSet();
}
/**
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from.
* Note: This will trigger eager initialization of the exception translator.
* @param connectionFactory JCA ConnectionFactory to obtain Connections from
* @param connectionSpec the CCI ConnectionSpec to obtain Connections for
* (may be {@code null})
*/
public CciTemplate(ConnectionFactory connectionFactory, ConnectionSpec connectionSpec) {
setConnectionFactory(connectionFactory);
setConnectionSpec(connectionSpec);
afterPropertiesSet();
}
/**
* Set the CCI ConnectionFactory to obtain Connections from.
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
* Return the CCI ConnectionFactory used by this template.
*/
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
/**
* Set the CCI ConnectionSpec that this template instance is
* supposed to obtain Connections for.
*/
public void setConnectionSpec(ConnectionSpec connectionSpec) {
this.connectionSpec = connectionSpec;
}
/**
* Return the CCI ConnectionSpec used by this template, if any.
*/
public ConnectionSpec getConnectionSpec() {
return this.connectionSpec;
}
/**
* Set a RecordCreator that should be used for creating default output Records.
* <p>Default is none: When no explicit output Record gets passed into an
* {@code execute} method, CCI's {@code Interaction.execute} variant
* that returns an output Record will be called.
* <p>Specify a RecordCreator here if you always need to call CCI's
* {@code Interaction.execute} variant with a passed-in output Record.
* Unless there is an explicitly specified output Record, CciTemplate will
* then invoke this RecordCreator to create a default output Record instance.
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
*/
public void setOutputRecordCreator(RecordCreator creator) {
this.outputRecordCreator = creator;
}
/**
* Return a RecordCreator that should be used for creating default output Records.
*/
public RecordCreator getOutputRecordCreator() {
return this.outputRecordCreator;
}
public void afterPropertiesSet() {
if (getConnectionFactory() == null) {
throw new IllegalArgumentException("Property 'connectionFactory' is required");
}
}
/**
* Create a template derived from this template instance,
* inheriting the ConnectionFactory and other settings but
* overriding the ConnectionSpec used for obtaining Connections.
* @param connectionSpec the CCI ConnectionSpec that the derived template
* instance is supposed to obtain Connections for
* @return the derived template instance
* @see #setConnectionSpec
*/
public CciTemplate getDerivedTemplate(ConnectionSpec connectionSpec) {
CciTemplate derived = new CciTemplate();
derived.setConnectionFactory(getConnectionFactory());
derived.setConnectionSpec(connectionSpec);
derived.setOutputRecordCreator(getOutputRecordCreator());
return derived;
}
@Override
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = ConnectionFactoryUtils.getConnection(getConnectionFactory(), getConnectionSpec());
try {
return action.doInConnection(con, getConnectionFactory());
}
catch (NotSupportedException ex) {
throw new CciOperationNotSupportedException("CCI operation not supported by connector", ex);
}
catch (ResourceException ex) {
throw new DataAccessResourceFailureException("CCI operation failed", ex);
}
catch (SQLException ex) {
throw new InvalidResultSetAccessException("Parsing of CCI ResultSet failed", ex);
}
finally {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
}
}
@Override
public <T> T execute(final InteractionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
return execute(new ConnectionCallback<T>() {
@Override
public T doInConnection(Connection connection, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException {
Interaction interaction = connection.createInteraction();
try {
return action.doInInteraction(interaction, connectionFactory);
}
finally {
closeInteraction(interaction);
}
}
});
}
@Override
public Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException {
return doExecute(spec, inputRecord, null, new SimpleRecordExtractor());
}
@Override
public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException {
doExecute(spec, inputRecord, outputRecord, null);
}
@Override
public Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException {
return doExecute(spec, createRecord(inputCreator), null, new SimpleRecordExtractor());
}
@Override
public <T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor)
throws DataAccessException {
return doExecute(spec, inputRecord, null, outputExtractor);
}
@Override
public <T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor)
throws DataAccessException {
return doExecute(spec, createRecord(inputCreator), null, outputExtractor);
}
/**
* Execute the specified interaction on an EIS with CCI.
* All other interaction execution methods go through this.
* @param spec the CCI InteractionSpec instance that defines
* the interaction (connector-specific)
* @param inputRecord the input record
* @param outputRecord output record (can be {@code null})
* @param outputExtractor object to convert the output record to a result object
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
protected <T> T doExecute(
final InteractionSpec spec, final Record inputRecord, final Record outputRecord,
final RecordExtractor<T> outputExtractor) throws DataAccessException {
return execute(new InteractionCallback<T>() {
@Override
public T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException {
Record outputRecordToUse = outputRecord;
try {
if (outputRecord != null || getOutputRecordCreator() != null) {
// Use the CCI execute method with output record as parameter.
if (outputRecord == null) {
RecordFactory recordFactory = getRecordFactory(connectionFactory);
outputRecordToUse = getOutputRecordCreator().createRecord(recordFactory);
}
interaction.execute(spec, inputRecord, outputRecordToUse);
}
else {
outputRecordToUse = interaction.execute(spec, inputRecord);
}
return (outputExtractor != null ? outputExtractor.extractData(outputRecordToUse) : null);
}
finally {
if (outputRecordToUse instanceof ResultSet) {
closeResultSet((ResultSet) outputRecordToUse);
}
}
}
});
}
/**
* Create an indexed Record through the ConnectionFactory's RecordFactory.
* @param name the name of the record
* @return the Record
* @throws DataAccessException if creation of the Record failed
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
* @see javax.resource.cci.RecordFactory#createIndexedRecord(String)
*/
public IndexedRecord createIndexedRecord(String name) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
return recordFactory.createIndexedRecord(name);
}
catch (NotSupportedException ex) {
throw new RecordTypeNotSupportedException("Creation of indexed Record not supported by connector", ex);
}
catch (ResourceException ex) {
throw new CannotCreateRecordException("Creation of indexed Record failed", ex);
}
}
/**
* Create a mapped Record from the ConnectionFactory's RecordFactory.
* @param name record name
* @return the Record
* @throws DataAccessException if creation of the Record failed
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
* @see javax.resource.cci.RecordFactory#createMappedRecord(String)
*/
public MappedRecord createMappedRecord(String name) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
return recordFactory.createMappedRecord(name);
}
catch (NotSupportedException ex) {
throw new RecordTypeNotSupportedException("Creation of mapped Record not supported by connector", ex);
}
catch (ResourceException ex) {
throw new CannotCreateRecordException("Creation of mapped Record failed", ex);
}
}
/**
* Invoke the given RecordCreator, converting JCA ResourceExceptions
* to Spring's DataAccessException hierarchy.
* @param recordCreator the RecordCreator to invoke
* @return the created Record
* @throws DataAccessException if creation of the Record failed
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory)
* @see RecordCreator#createRecord(javax.resource.cci.RecordFactory)
*/
protected Record createRecord(RecordCreator recordCreator) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
return recordCreator.createRecord(recordFactory);
}
catch (NotSupportedException ex) {
throw new RecordTypeNotSupportedException(
"Creation of the desired Record type not supported by connector", ex);
}
catch (ResourceException ex) {
throw new CannotCreateRecordException("Creation of the desired Record failed", ex);
}
}
/**
* Return a RecordFactory for the given ConnectionFactory.
* <p>Default implementation returns the connector's RecordFactory if
* available, falling back to a NotSupportedRecordFactory placeholder.
* This allows to invoke a RecordCreator callback with a non-null
* RecordFactory reference in any case.
* @param connectionFactory the CCI ConnectionFactory
* @return the CCI RecordFactory for the ConnectionFactory
* @throws ResourceException if thrown by CCI methods
* @see com.fr.third.springframework.jca.cci.connection.NotSupportedRecordFactory
*/
protected RecordFactory getRecordFactory(ConnectionFactory connectionFactory) throws ResourceException {
try {
return connectionFactory.getRecordFactory();
}
catch (NotSupportedException ex) {
return new NotSupportedRecordFactory();
}
}
/**
* Close the given CCI Interaction and ignore any thrown exception.
* This is useful for typical finally blocks in manual CCI code.
* @param interaction the CCI Interaction to close
* @see javax.resource.cci.Interaction#close()
*/
private void closeInteraction(Interaction interaction) {
if (interaction != null) {
try {
interaction.close();
}
catch (ResourceException ex) {
logger.trace("Could not close CCI Interaction", ex);
}
catch (Throwable ex) {
// We don't trust the CCI driver: It might throw RuntimeException or Error.
logger.trace("Unexpected exception on closing CCI Interaction", ex);
}
}
}
/**
* Close the given CCI ResultSet and ignore any thrown exception.
* This is useful for typical finally blocks in manual CCI code.
* @param resultSet the CCI ResultSet to close
* @see javax.resource.cci.ResultSet#close()
*/
private void closeResultSet(ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException ex) {
logger.trace("Could not close CCI ResultSet", ex);
}
catch (Throwable ex) {
// We don't trust the CCI driver: It might throw RuntimeException or Error.
logger.trace("Unexpected exception on closing CCI ResultSet", ex);
}
}
}
private static class SimpleRecordExtractor implements RecordExtractor<Record> {
@Override
public Record extractData(Record record) {
return record;
}
}
}

79
fine-spring/src/com/fr/third/springframework/jca/cci/core/ConnectionCallback.java

@ -0,0 +1,79 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Generic callback interface for code that operates on a CCI Connection.
* Allows to execute any number of operations on a single Connection,
* using any type and number of Interaction.
*
* <p>This is particularly useful for delegating to existing data access code
* that expects a Connection to work on and throws ResourceException. For newly
* written code, it is strongly recommended to use CciTemplate's more specific
* {@code execute} variants.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see CciTemplate#execute(ConnectionCallback)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
public interface ConnectionCallback<T> {
/**
* Gets called by {@code CciTemplate.execute} with an active CCI Connection.
* Does not need to care about activating or closing the Connection, or handling
* transactions.
*
* <p>If called without a thread-bound CCI transaction (initiated by
* CciLocalTransactionManager), the code will simply get executed on the CCI
* Connection with its transactional semantics. If CciTemplate is configured
* to use a JTA-aware ConnectionFactory, the CCI Connection and thus the callback
* code will be transactional if a JTA transaction is active.
*
* <p>Allows for returning a result object created within the callback, i.e.
* a domain object or a collection of domain objects. Note that there's special
* support for single step actions: see the {@code CciTemplate.execute}
* variants. A thrown RuntimeException is treated as application exception:
* it gets propagated to the caller of the template.
*
* @param connection active CCI Connection
* @param connectionFactory the CCI ConnectionFactory that the Connection was
* created with (gives access to RecordFactory and ResourceAdapterMetaData)
* @return a result object, or {@code null} if none
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
* to a DataAccessException
* @throws DataAccessException in case of custom exceptions
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
* @see javax.resource.cci.ConnectionFactory#getMetaData()
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
T doInConnection(Connection connection, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException;
}

80
fine-spring/src/com/fr/third/springframework/jca/cci/core/InteractionCallback.java

@ -0,0 +1,80 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.Interaction;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Generic callback interface for code that operates on a CCI Interaction.
* Allows to execute any number of operations on a single Interaction, for
* example a single execute call or repeated execute calls with varying
* parameters.
*
* <p>This is particularly useful for delegating to existing data access code
* that expects an Interaction to work on and throws ResourceException. For newly
* written code, it is strongly recommended to use CciTemplate's more specific
* {@code execute} variants.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see CciTemplate#execute(InteractionCallback)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
public interface InteractionCallback<T> {
/**
* Gets called by {@code CciTemplate.execute} with an active CCI Interaction.
* Does not need to care about activating or closing the Interaction, or
* handling transactions.
*
* <p>If called without a thread-bound CCI transaction (initiated by
* CciLocalTransactionManager), the code will simply get executed on the CCI
* Interaction with its transactional semantics. If CciTemplate is configured
* to use a JTA-aware ConnectionFactory, the CCI Interaction and thus the callback
* code will be transactional if a JTA transaction is active.
*
* <p>Allows for returning a result object created within the callback, i.e.
* a domain object or a collection of domain objects. Note that there's special
* support for single step actions: see the {@code CciTemplate.execute}
* variants. A thrown RuntimeException is treated as application exception:
* it gets propagated to the caller of the template.
*
* @param interaction active CCI Interaction
* @param connectionFactory the CCI ConnectionFactory that the Connection was
* created with (gives access to RecordFactory and ResourceAdapterMetaData)
* @return a result object, or {@code null} if none
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
* to a DataAccessException
* @throws DataAccessException in case of custom exceptions
* @see javax.resource.cci.ConnectionFactory#getRecordFactory()
* @see javax.resource.cci.ConnectionFactory#getMetaData()
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException;
}

64
fine-spring/src/com/fr/third/springframework/jca/cci/core/RecordCreator.java

@ -0,0 +1,64 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import javax.resource.ResourceException;
import javax.resource.cci.Record;
import javax.resource.cci.RecordFactory;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Callback interface for creating a CCI Record instance,
* usually based on the passed-in CCI RecordFactory.
*
* <p>Used for input Record creation in CciTemplate. Alternatively,
* Record instances can be passed into CciTemplate's corresponding
* {@code execute} methods directly, either instantiated manually
* or created through CciTemplate's Record factory methods.
*
* <P>Also used for creating default output Records in CciTemplate.
* This is useful when the JCA connector needs an explicit output Record
* instance, but no output Records should be passed into CciTemplate's
* {@code execute} methods.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
* @see CciTemplate#createIndexedRecord(String)
* @see CciTemplate#createMappedRecord(String)
* @see CciTemplate#setOutputRecordCreator(RecordCreator)
*/
public interface RecordCreator {
/**
* Create a CCI Record instance, usually based on the passed-in CCI RecordFactory.
* <p>For use as <i>input</i> creator with CciTemplate's {@code execute} methods,
* this method should create a <i>populated</i> Record instance. For use as
* <i>output</i> Record creator, it should return an <i>empty</i> Record instance.
* @param recordFactory the CCI RecordFactory (never {@code null}, but not guaranteed to be
* supported by the connector: its create methods might throw NotSupportedException)
* @return the Record instance
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @throws DataAccessException in case of custom exceptions
*/
Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException;
}

63
fine-spring/src/com/fr/third/springframework/jca/cci/core/RecordExtractor.java

@ -0,0 +1,63 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.Record;
import com.fr.third.springframework.dao.DataAccessException;
/**
* Callback interface for extracting a result object from a CCI Record instance.
*
* <p>Used for output object creation in CciTemplate. Alternatively, output
* Records can also be returned to client code as-is. In case of a CCI ResultSet
* as execution result, you will almost always want to implement a RecordExtractor,
* to be able to read the ResultSet in a managed fashion, with the CCI Connection
* still open while reading the ResultSet.
*
* <p>Implementations of this interface perform the actual work of extracting
* results, but don't need to worry about exception handling. ResourceExceptions
* will be caught and handled correctly by the CciTemplate class.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, Record, RecordExtractor)
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
* @see javax.resource.cci.ResultSet
*/
public interface RecordExtractor<T> {
/**
* Process the data in the given Record, creating a corresponding result object.
* @param record the Record to extract data from
* (possibly a CCI ResultSet)
* @return an arbitrary result object, or {@code null} if none
* (the extractor will typically be stateful in the latter case)
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @throws SQLException if thrown by a ResultSet method, to be auto-converted
* to a DataAccessException
* @throws DataAccessException in case of custom exceptions
* @see javax.resource.cci.ResultSet
*/
T extractData(Record record) throws ResourceException, SQLException, DataAccessException;
}

9
fine-spring/src/com/fr/third/springframework/jca/cci/core/package-info.java

@ -0,0 +1,9 @@
/**
*
* Provides the core JCA CCI support, based on CciTemplate
* and its associated callback interfaces.
*
*/
package com.fr.third.springframework.jca.cci.core;

138
fine-spring/src/com/fr/third/springframework/jca/cci/core/support/CciDaoSupport.java

@ -0,0 +1,138 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core.support;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import com.fr.third.springframework.dao.support.DaoSupport;
import com.fr.third.springframework.jca.cci.CannotGetCciConnectionException;
import com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils;
import com.fr.third.springframework.jca.cci.core.CciTemplate;
/**
* Convenient super class for CCI-based data access objects.
*
* <p>Requires a {@link javax.resource.cci.ConnectionFactory} to be set,
* providing a {@link com.fr.third.springframework.jca.cci.core.CciTemplate} based
* on it to subclasses through the {@link #getCciTemplate()} method.
*
* <p>This base class is mainly intended for CciTemplate usage but can
* also be used when working with a Connection directly or when using
* {@code com.fr.third.springframework.jca.cci.object} classes.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see #setConnectionFactory
* @see #getCciTemplate
* @see com.fr.third.springframework.jca.cci.core.CciTemplate
*/
public abstract class CciDaoSupport extends DaoSupport {
private CciTemplate cciTemplate;
/**
* Set the ConnectionFactory to be used by this DAO.
*/
public final void setConnectionFactory(ConnectionFactory connectionFactory) {
if (this.cciTemplate == null || connectionFactory != this.cciTemplate.getConnectionFactory()) {
this.cciTemplate = createCciTemplate(connectionFactory);
}
}
/**
* Create a CciTemplate for the given ConnectionFactory.
* Only invoked if populating the DAO with a ConnectionFactory reference!
* <p>Can be overridden in subclasses to provide a CciTemplate instance
* with different configuration, or a custom CciTemplate subclass.
* @param connectionFactory the CCI ConnectionFactory to create a CciTemplate for
* @return the new CciTemplate instance
* @see #setConnectionFactory(javax.resource.cci.ConnectionFactory)
*/
protected CciTemplate createCciTemplate(ConnectionFactory connectionFactory) {
return new CciTemplate(connectionFactory);
}
/**
* Return the ConnectionFactory used by this DAO.
*/
public final ConnectionFactory getConnectionFactory() {
return this.cciTemplate.getConnectionFactory();
}
/**
* Set the CciTemplate for this DAO explicitly,
* as an alternative to specifying a ConnectionFactory.
*/
public final void setCciTemplate(CciTemplate cciTemplate) {
this.cciTemplate = cciTemplate;
}
/**
* Return the CciTemplate for this DAO,
* pre-initialized with the ConnectionFactory or set explicitly.
*/
public final CciTemplate getCciTemplate() {
return this.cciTemplate;
}
@Override
protected final void checkDaoConfig() {
if (this.cciTemplate == null) {
throw new IllegalArgumentException("'connectionFactory' or 'cciTemplate' is required");
}
}
/**
* Obtain a CciTemplate derived from the main template instance,
* inheriting the ConnectionFactory and other settings but
* overriding the ConnectionSpec used for obtaining Connections.
* @param connectionSpec the CCI ConnectionSpec that the returned
* template instance is supposed to obtain Connections for
* @return the derived template instance
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#getDerivedTemplate(javax.resource.cci.ConnectionSpec)
*/
protected final CciTemplate getCciTemplate(ConnectionSpec connectionSpec) {
return getCciTemplate().getDerivedTemplate(connectionSpec);
}
/**
* Get a CCI Connection, either from the current transaction or a new one.
* @return the CCI Connection
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException
* if the attempt to get a Connection failed
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
*/
protected final Connection getConnection() throws CannotGetCciConnectionException {
return ConnectionFactoryUtils.getConnection(getConnectionFactory());
}
/**
* Close the given CCI Connection, created via this bean's ConnectionFactory,
* if it isn't bound to the thread.
* @param con Connection to close
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#releaseConnection
*/
protected final void releaseConnection(Connection con) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
}
}

104
fine-spring/src/com/fr/third/springframework/jca/cci/core/support/CommAreaRecord.java

@ -0,0 +1,104 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.core.support;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.resource.cci.Record;
import javax.resource.cci.Streamable;
import com.fr.third.springframework.util.FileCopyUtils;
/**
* CCI Record implementation for a COMMAREA, holding a byte array.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see com.fr.third.springframework.jca.cci.object.MappingCommAreaOperation
*/
@SuppressWarnings("serial")
public class CommAreaRecord implements Record, Streamable {
private byte[] bytes;
private String recordName;
private String recordShortDescription;
/**
* Create a new CommAreaRecord.
* @see #read(java.io.InputStream)
*/
public CommAreaRecord() {
}
/**
* Create a new CommAreaRecord.
* @param bytes the bytes to fill the record with
*/
public CommAreaRecord(byte[] bytes) {
this.bytes = bytes;
}
@Override
public void setRecordName(String recordName) {
this.recordName=recordName;
}
@Override
public String getRecordName() {
return recordName;
}
@Override
public void setRecordShortDescription(String recordShortDescription) {
this.recordShortDescription=recordShortDescription;
}
@Override
public String getRecordShortDescription() {
return recordShortDescription;
}
@Override
public void read(InputStream in) throws IOException {
this.bytes = FileCopyUtils.copyToByteArray(in);
}
@Override
public void write(OutputStream out) throws IOException {
out.write(this.bytes);
out.flush();
}
public byte[] toByteArray() {
return this.bytes;
}
@Override
public Object clone() {
return new CommAreaRecord(this.bytes);
}
}

8
fine-spring/src/com/fr/third/springframework/jca/cci/core/support/package-info.java

@ -0,0 +1,8 @@
/**
*
* Classes supporting the {@code com.fr.third.springframework.jca.cci.core} package.
* Contains a DAO base class for CciTemplate usage.
*
*/
package com.fr.third.springframework.jca.cci.core.support;

94
fine-spring/src/com/fr/third/springframework/jca/cci/object/EisOperation.java

@ -0,0 +1,94 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.object;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.InteractionSpec;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.jca.cci.core.CciTemplate;
/**
* Base class for EIS operation objects that work with the CCI API.
* Encapsulates a CCI ConnectionFactory and a CCI InteractionSpec.
*
* <p>Works with a CciTemplate instance underneath. EIS operation objects
* are an alternative to working with a CciTemplate directly.
*
* @author Juergen Hoeller
* @since 1.2
* @see #setConnectionFactory
* @see #setInteractionSpec
*/
public abstract class EisOperation implements InitializingBean {
private CciTemplate cciTemplate = new CciTemplate();
private InteractionSpec interactionSpec;
/**
* Set the CciTemplate to be used by this operation.
* Alternatively, specify a CCI ConnectionFactory.
* @see #setConnectionFactory
*/
public void setCciTemplate(CciTemplate cciTemplate) {
if (cciTemplate == null) {
throw new IllegalArgumentException("cciTemplate must not be null");
}
this.cciTemplate = cciTemplate;
}
/**
* Return the CciTemplate used by this operation.
*/
public CciTemplate getCciTemplate() {
return this.cciTemplate;
}
/**
* Set the CCI ConnectionFactory to be used by this operation.
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.cciTemplate.setConnectionFactory(connectionFactory);
}
/**
* Set the CCI InteractionSpec for this operation.
*/
public void setInteractionSpec(InteractionSpec interactionSpec) {
this.interactionSpec = interactionSpec;
}
/**
* Return the CCI InteractionSpec for this operation.
*/
public InteractionSpec getInteractionSpec() {
return this.interactionSpec;
}
@Override
public void afterPropertiesSet() {
this.cciTemplate.afterPropertiesSet();
if (this.interactionSpec == null) {
throw new IllegalArgumentException("interactionSpec is required");
}
}
}

97
fine-spring/src/com/fr/third/springframework/jca/cci/object/MappingCommAreaOperation.java

@ -0,0 +1,97 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.object;
import java.io.IOException;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.Record;
import javax.resource.cci.RecordFactory;
import com.fr.third.springframework.dao.DataAccessException;
import com.fr.third.springframework.dao.DataRetrievalFailureException;
import com.fr.third.springframework.jca.cci.core.support.CommAreaRecord;
/**
* EIS operation object for access to COMMAREA records.
* Subclass of the generic MappingRecordOperation class.
*
* @author Thierry Templier
* @since 1.2
*/
public abstract class MappingCommAreaOperation extends MappingRecordOperation {
/**
* Create a new MappingCommAreaQuery.
* @see #setConnectionFactory
* @see #setInteractionSpec
*/
public MappingCommAreaOperation() {
}
/**
* Create a new MappingCommAreaQuery.
* @param connectionFactory ConnectionFactory to use to obtain connections
* @param interactionSpec specification to configure the interaction
*/
public MappingCommAreaOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
super(connectionFactory, interactionSpec);
}
@Override
protected final Record createInputRecord(RecordFactory recordFactory, Object inObject) {
try {
return new CommAreaRecord(objectToBytes(inObject));
}
catch (IOException ex) {
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex);
}
}
@Override
protected final Object extractOutputData(Record record) throws DataAccessException {
CommAreaRecord commAreaRecord = (CommAreaRecord) record;
try {
return bytesToObject(commAreaRecord.toByteArray());
}
catch (IOException ex) {
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex);
}
}
/**
* Method used to convert an object into COMMAREA bytes.
* @param inObject the input data
* @return the COMMAREA's bytes
* @throws IOException if thrown by I/O methods
* @throws DataAccessException if conversion failed
*/
protected abstract byte[] objectToBytes(Object inObject) throws IOException, DataAccessException;
/**
* Method used to convert the COMMAREA's bytes to an object.
* @param bytes the COMMAREA's bytes
* @return the output data
* @throws IOException if thrown by I/O methods
* @throws DataAccessException if conversion failed
*/
protected abstract Object bytesToObject(byte[] bytes) throws IOException, DataAccessException;
}

151
fine-spring/src/com/fr/third/springframework/jca/cci/object/MappingRecordOperation.java

@ -0,0 +1,151 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.object;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.Record;
import javax.resource.cci.RecordFactory;
import com.fr.third.springframework.dao.DataAccessException;
import com.fr.third.springframework.jca.cci.core.RecordCreator;
import com.fr.third.springframework.jca.cci.core.RecordExtractor;
/**
* EIS operation object that expects mapped input and output objects,
* converting to and from CCI Records.
*
* <p>Concrete subclasses must implement the abstract
* {@code createInputRecord(RecordFactory, Object)} and
* {@code extractOutputData(Record)} methods, to create an input
* Record from an object and to convert an output Record into an object,
* respectively.
*
* @author Thierry Templier
* @author Juergen Hoeller
* @since 1.2
* @see #createInputRecord(javax.resource.cci.RecordFactory, Object)
* @see #extractOutputData(javax.resource.cci.Record)
*/
public abstract class MappingRecordOperation extends EisOperation {
/**
* Constructor that allows use as a JavaBean.
*/
public MappingRecordOperation() {
}
/**
* Convenient constructor with ConnectionFactory and specifications
* (connection and interaction).
* @param connectionFactory ConnectionFactory to use to obtain connections
*/
public MappingRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
getCciTemplate().setConnectionFactory(connectionFactory);
setInteractionSpec(interactionSpec);
}
/**
* Set a RecordCreator that should be used for creating default output Records.
* <p>Default is none: CCI's {@code Interaction.execute} variant
* that returns an output Record will be called.
* <p>Specify a RecordCreator here if you always need to call CCI's
* {@code Interaction.execute} variant with a passed-in output Record.
* This RecordCreator will then be invoked to create a default output Record instance.
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#setOutputRecordCreator
*/
public void setOutputRecordCreator(RecordCreator creator) {
getCciTemplate().setOutputRecordCreator(creator);
}
/**
* Execute the interaction encapsulated by this operation object.
* @param inputObject the input data, to be converted to a Record
* by the {@code createInputRecord} method
* @return the output data extracted with the {@code extractOutputData} method
* @throws DataAccessException if there is any problem
* @see #createInputRecord
* @see #extractOutputData
*/
public Object execute(Object inputObject) throws DataAccessException {
return getCciTemplate().execute(
getInteractionSpec(), new RecordCreatorImpl(inputObject), new RecordExtractorImpl());
}
/**
* Subclasses must implement this method to generate an input Record
* from an input object passed into the {@code execute} method.
* @param inputObject the passed-in input object
* @return the CCI input Record
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @see #execute(Object)
*/
protected abstract Record createInputRecord(RecordFactory recordFactory, Object inputObject)
throws ResourceException, DataAccessException;
/**
* Subclasses must implement this method to convert the Record returned
* by CCI execution into a result object for the {@code execute} method.
* @param outputRecord the Record returned by CCI execution
* @return the result object
* @throws ResourceException if thrown by a CCI method, to be auto-converted
* to a DataAccessException
* @see #execute(Object)
*/
protected abstract Object extractOutputData(Record outputRecord)
throws ResourceException, SQLException, DataAccessException;
/**
* Implementation of RecordCreator that calls the enclosing
* class's {@code createInputRecord} method.
*/
protected class RecordCreatorImpl implements RecordCreator {
private final Object inputObject;
public RecordCreatorImpl(Object inObject) {
this.inputObject = inObject;
}
@Override
public Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException {
return createInputRecord(recordFactory, this.inputObject);
}
}
/**
* Implementation of RecordExtractor that calls the enclosing
* class's {@code extractOutputData} method.
*/
protected class RecordExtractorImpl implements RecordExtractor<Object> {
@Override
public Object extractData(Record record) throws ResourceException, SQLException, DataAccessException {
return extractOutputData(record);
}
}
}

76
fine-spring/src/com/fr/third/springframework/jca/cci/object/SimpleRecordOperation.java

@ -0,0 +1,76 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.cci.object;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.InteractionSpec;
import javax.resource.cci.Record;
import com.fr.third.springframework.dao.DataAccessException;
/**
* EIS operation object that accepts a passed-in CCI input Record
* and returns a corresponding CCI output Record.
*
* @author Juergen Hoeller
* @since 1.2
*/
public class SimpleRecordOperation extends EisOperation {
/**
* Constructor that allows use as a JavaBean.
*/
public SimpleRecordOperation() {
}
/**
* Convenient constructor with ConnectionFactory and specifications
* (connection and interaction).
* @param connectionFactory ConnectionFactory to use to obtain connections
*/
public SimpleRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) {
getCciTemplate().setConnectionFactory(connectionFactory);
setInteractionSpec(interactionSpec);
}
/**
* Execute the CCI interaction encapsulated by this operation object.
* <p>This method will call CCI's {@code Interaction.execute} variant
* that returns an output Record.
* @param inputRecord the input record
* @return the output record
* @throws DataAccessException if there is any problem
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
*/
public Record execute(Record inputRecord) throws DataAccessException {
return getCciTemplate().execute(getInteractionSpec(), inputRecord);
}
/**
* Execute the CCI interaction encapsulated by this operation object.
* <p>This method will call CCI's {@code Interaction.execute} variant
* with a passed-in output Record.
* @param inputRecord the input record
* @param outputRecord the output record
* @throws DataAccessException if there is any problem
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
*/
public void execute(Record inputRecord, Record outputRecord) throws DataAccessException {
getCciTemplate().execute(getInteractionSpec(), inputRecord, outputRecord);
}
}

11
fine-spring/src/com/fr/third/springframework/jca/cci/object/package-info.java

@ -0,0 +1,11 @@
/**
*
* The classes in this package represent EIS operations as threadsafe,
* reusable objects. This higher level of CCI abstraction depends on the
* lower-level abstraction in the {@code com.fr.third.springframework.jca.cci.core} package.
* Exceptions thrown are as in the {@code com.fr.third.springframework.dao} package,
* meaning that code using this package does not need to worry about error handling.
*
*/
package com.fr.third.springframework.jca.cci.object;

10
fine-spring/src/com/fr/third/springframework/jca/cci/package-info.java

@ -0,0 +1,10 @@
/**
*
* This package contains Spring's support for the Common Client Interface (CCI),
* as defined by the J2EE Connector Architecture. It is conceptually similar
* to the {@code com.fr.third.springframework.jdbc} package, providing the same
* levels of data access abstraction.
*
*/
package com.fr.third.springframework.jca.cci;

47
fine-spring/src/com/fr/third/springframework/jca/context/BootstrapContextAware.java

@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.context;
import javax.resource.spi.BootstrapContext;
import com.fr.third.springframework.beans.factory.Aware;
/**
* Interface to be implemented by any object that wishes to be
* notified of the BootstrapContext (typically determined by the
* {@link ResourceAdapterApplicationContext}) that it runs in.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 2.5
* @see javax.resource.spi.BootstrapContext
*/
public interface BootstrapContextAware extends Aware {
/**
* Set the BootstrapContext that this object runs in.
* <p>Invoked after population of normal bean properties but before an init
* callback like InitializingBean's {@code afterPropertiesSet} or a
* custom init-method. Invoked after ApplicationContextAware's
* {@code setApplicationContext}.
* @param bootstrapContext BootstrapContext object to be used by this object
* @see com.fr.third.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see com.fr.third.springframework.context.ApplicationContextAware#setApplicationContext
*/
void setBootstrapContext(BootstrapContext bootstrapContext);
}

62
fine-spring/src/com/fr/third/springframework/jca/context/BootstrapContextAwareProcessor.java

@ -0,0 +1,62 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.context;
import javax.resource.spi.BootstrapContext;
import com.fr.third.springframework.beans.BeansException;
import com.fr.third.springframework.beans.factory.config.BeanPostProcessor;
/**
* {@link com.fr.third.springframework.beans.factory.config.BeanPostProcessor}
* implementation that passes the BootstrapContext to beans that implement
* the {@link BootstrapContextAware} interface.
*
* <p>{@link ResourceAdapterApplicationContext} automatically registers
* this processor with its underlying bean factory.
*
* @author Juergen Hoeller
* @since 2.5
* @see BootstrapContextAware
*/
class BootstrapContextAwareProcessor implements BeanPostProcessor {
private final BootstrapContext bootstrapContext;
/**
* Create a new BootstrapContextAwareProcessor for the given context.
*/
public BootstrapContextAwareProcessor(BootstrapContext bootstrapContext) {
this.bootstrapContext = bootstrapContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (this.bootstrapContext != null && bean instanceof BootstrapContextAware) {
((BootstrapContextAware) bean).setBootstrapContext(this.bootstrapContext);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}

70
fine-spring/src/com/fr/third/springframework/jca/context/ResourceAdapterApplicationContext.java

@ -0,0 +1,70 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.context;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.work.WorkManager;
import com.fr.third.springframework.beans.BeansException;
import com.fr.third.springframework.beans.factory.ObjectFactory;
import com.fr.third.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import com.fr.third.springframework.context.support.GenericApplicationContext;
import com.fr.third.springframework.util.Assert;
/**
* {@link com.fr.third.springframework.context.ApplicationContext} implementation
* for a JCA ResourceAdapter. Needs to be initialized with the JCA
* {@link javax.resource.spi.BootstrapContext}, passing it on to
* Spring-managed beans that implement {@link BootstrapContextAware}.
*
* @author Juergen Hoeller
* @since 2.5
* @see SpringContextResourceAdapter
* @see BootstrapContextAware
*/
public class ResourceAdapterApplicationContext extends GenericApplicationContext {
private final BootstrapContext bootstrapContext;
/**
* Create a new ResourceAdapterApplicationContext for the given BootstrapContext.
* @param bootstrapContext the JCA BootstrapContext that the ResourceAdapter
* has been started with
*/
public ResourceAdapterApplicationContext(BootstrapContext bootstrapContext) {
Assert.notNull(bootstrapContext, "BootstrapContext must not be null");
this.bootstrapContext = bootstrapContext;
}
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.addBeanPostProcessor(new BootstrapContextAwareProcessor(this.bootstrapContext));
beanFactory.ignoreDependencyInterface(BootstrapContextAware.class);
beanFactory.registerResolvableDependency(BootstrapContext.class, this.bootstrapContext);
// JCA WorkManager resolved lazily - may not be available.
beanFactory.registerResolvableDependency(WorkManager.class, new ObjectFactory<WorkManager>() {
@Override
public WorkManager getObject() {
return bootstrapContext.getWorkManager();
}
});
}
}

250
fine-spring/src/com/fr/third/springframework/jca/context/SpringContextResourceAdapter.java

@ -0,0 +1,250 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.context;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.transaction.xa.XAResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.beans.factory.support.BeanDefinitionRegistry;
import com.fr.third.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import com.fr.third.springframework.context.ConfigurableApplicationContext;
import com.fr.third.springframework.core.env.ConfigurableEnvironment;
import com.fr.third.springframework.core.env.StandardEnvironment;
import com.fr.third.springframework.util.ObjectUtils;
import com.fr.third.springframework.util.StringUtils;
/**
* JCA 1.5 {@link javax.resource.spi.ResourceAdapter} implementation
* that loads a Spring {@link com.fr.third.springframework.context.ApplicationContext},
* starting and stopping Spring-managed beans as part of the ResourceAdapter's
* lifecycle.
*
* <p>Ideal for application contexts that do not need any HTTP entry points
* but rather just consist of message endpoints and scheduled jobs etc.
* Beans in such a context may use application server resources such as the
* JTA transaction manager and JNDI-bound JDBC DataSources and JMS
* ConnectionFactory instances, and may also register with the platform's
* JMX server - all through Spring's standard transaction management and
* JNDI and JMX support facilities.
*
* <p>If the need for scheduling asynchronous work arises, consider using
* Spring's {@link com.fr.third.springframework.jca.work.WorkManagerTaskExecutor}
* as a standard bean definition, to be injected into application beans
* through dependency injection. This WorkManagerTaskExecutor will automatically
* use the JCA WorkManager from the BootstrapContext that has been provided
* to this ResourceAdapter.
*
* <p>The JCA {@link javax.resource.spi.BootstrapContext} may also be
* accessed directly, through application components that implement the
* {@link BootstrapContextAware} interface. When deployed using this
* ResourceAdapter, the BootstrapContext is guaranteed to be passed on
* to such components.
*
* <p>This ResourceAdapter is to be defined in a "META-INF/ra.xml" file
* within a J2EE ".rar" deployment unit like as follows:
*
* <pre class="code">
* &lt;?xml version="1.0" encoding="UTF-8"?&gt;
* &lt;connector xmlns="http://java.sun.com/xml/ns/j2ee"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
* version="1.5"&gt;
* &lt;vendor-name&gt;Spring Framework&lt;/vendor-name&gt;
* &lt;eis-type&gt;Spring Connector&lt;/eis-type&gt;
* &lt;resourceadapter-version&gt;1.0&lt;/resourceadapter-version&gt;
* &lt;resourceadapter&gt;
* &lt;resourceadapter-class&gt;com.fr.third.springframework.jca.context.SpringContextResourceAdapter&lt;/resourceadapter-class&gt;
* &lt;config-property&gt;
* &lt;config-property-name&gt;ContextConfigLocation&lt;/config-property-name&gt;
* &lt;config-property-type&gt;java.lang.String&lt;/config-property-type&gt;
* &lt;config-property-value&gt;META-INF/applicationContext.xml&lt;/config-property-value&gt;
* &lt;/config-property&gt;
* &lt;/resourceadapter&gt;
* &lt;/connector&gt;</pre>
*
* Note that "META-INF/applicationContext.xml" is the default context config
* location, so it doesn't have to specified unless you intend to specify
* different/additional config files. So in the default case, you may remove
* the entire {@code config-property} section above.
*
* <p><b>For simple deployment needs, all you need to do is the following:</b>
* Package all application classes into a RAR file (which is just a standard
* JAR file with a different file extension), add all required library jars
* into the root of the RAR archive, add a "META-INF/ra.xml" deployment
* descriptor as shown above as well as the corresponding Spring XML bean
* definition file(s) (typically "META-INF/applicationContext.xml"),
* and drop the resulting RAR file into your application server's
* deployment directory!
*
* @author Juergen Hoeller
* @since 2.5
* @see #setContextConfigLocation
* @see #loadBeanDefinitions
* @see ResourceAdapterApplicationContext
*/
public class SpringContextResourceAdapter implements ResourceAdapter {
/**
* Any number of these characters are considered delimiters between
* multiple context config paths in a single String value.
* @see #setContextConfigLocation
*/
public static final String CONFIG_LOCATION_DELIMITERS = ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS;
public static final String DEFAULT_CONTEXT_CONFIG_LOCATION = "META-INF/applicationContext.xml";
protected final Log logger = LogFactory.getLog(getClass());
private String contextConfigLocation = DEFAULT_CONTEXT_CONFIG_LOCATION;
private ConfigurableApplicationContext applicationContext;
/**
* Set the location of the context configuration files, within the
* resource adapter's deployment unit. This can be a delimited
* String that consists of multiple resource location, separated
* by commas, semicolons, whitespace, or line breaks.
* <p>This can be specified as "ContextConfigLocation" config
* property in the {@code ra.xml} deployment descriptor.
* <p>The default is "classpath:META-INF/applicationContext.xml".
*/
public void setContextConfigLocation(String contextConfigLocation) {
this.contextConfigLocation = contextConfigLocation;
}
/**
* Return the specified context configuration files.
*/
protected String getContextConfigLocation() {
return this.contextConfigLocation;
}
/**
* Return a new {@link StandardEnvironment}.
* <p>Subclasses may override this method in order to supply
* a custom {@link ConfigurableEnvironment} implementation.
*/
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
/**
* This implementation loads a Spring ApplicationContext through the
* {@link #createApplicationContext} template method.
*/
@Override
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
if (logger.isInfoEnabled()) {
logger.info("Starting SpringContextResourceAdapter with BootstrapContext: " + bootstrapContext);
}
this.applicationContext = createApplicationContext(bootstrapContext);
}
/**
* Build a Spring ApplicationContext for the given JCA BootstrapContext.
* <p>The default implementation builds a {@link ResourceAdapterApplicationContext}
* and delegates to {@link #loadBeanDefinitions} for actually parsing the
* specified configuration files.
* @param bootstrapContext this ResourceAdapter's BootstrapContext
* @return the Spring ApplicationContext instance
*/
protected ConfigurableApplicationContext createApplicationContext(BootstrapContext bootstrapContext) {
ResourceAdapterApplicationContext applicationContext =
new ResourceAdapterApplicationContext(bootstrapContext);
// Set ResourceAdapter's ClassLoader as bean class loader.
applicationContext.setClassLoader(getClass().getClassLoader());
// Extract individual config locations.
String[] configLocations =
StringUtils.tokenizeToStringArray(getContextConfigLocation(), CONFIG_LOCATION_DELIMITERS);
if (configLocations != null) {
loadBeanDefinitions(applicationContext, configLocations);
}
applicationContext.refresh();
return applicationContext;
}
/**
* Load the bean definitions into the given registry,
* based on the specified configuration files.
* @param registry the registry to load into
* @param configLocations the parsed config locations
* @see #setContextConfigLocation
*/
protected void loadBeanDefinitions(BeanDefinitionRegistry registry, String[] configLocations) {
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(configLocations);
}
/**
* This implementation closes the Spring ApplicationContext.
*/
@Override
public void stop() {
logger.info("Stopping SpringContextResourceAdapter");
this.applicationContext.close();
}
/**
* This implementation always throws a NotSupportedException.
*/
@Override
public void endpointActivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec)
throws ResourceException {
throw new NotSupportedException("SpringContextResourceAdapter does not support message endpoints");
}
/**
* This implementation does nothing.
*/
@Override
public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) {
}
/**
* This implementation always returns {@code null}.
*/
@Override
public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
return null;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof SpringContextResourceAdapter &&
ObjectUtils.nullSafeEquals(getContextConfigLocation(),
((SpringContextResourceAdapter) obj).getContextConfigLocation()));
}
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(getContextConfigLocation());
}
}

9
fine-spring/src/com/fr/third/springframework/jca/context/package-info.java

@ -0,0 +1,9 @@
/**
*
* Integration package that allows for deploying a Spring application context
* as a JCA 1.5 compliant RAR file.
*
*/
package com.fr.third.springframework.jca.context;

17
fine-spring/src/com/fr/third/springframework/jca/context/ra.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<connector xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
version="1.5">
<vendor-name>Spring Framework</vendor-name>
<eis-type>Spring Connector</eis-type>
<resourceadapter-version>1.0</resourceadapter-version>
<resourceadapter>
<resourceadapter-class>com.fr.third.springframework.jca.context.SpringContextResourceAdapter</resourceadapter-class>
<config-property>
<config-property-name>ContextConfigLocation</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>META-INF/applicationContext.xml</config-property-value>
</config-property>
</resourceadapter>
</connector>

341
fine-spring/src/com/fr/third/springframework/jca/endpoint/AbstractMessageEndpointFactory.java

@ -0,0 +1,341 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.endpoint;
import java.lang.reflect.Method;
import javax.resource.ResourceException;
import javax.resource.spi.ApplicationServerInternalException;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.fr.third.springframework.beans.factory.BeanNameAware;
import com.fr.third.springframework.transaction.jta.SimpleTransactionFactory;
import com.fr.third.springframework.transaction.jta.TransactionFactory;
/**
* Abstract base implementation of the JCA 1.5/1.6/1.7
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface,
* providing transaction management capabilities as well as ClassLoader
* exposure for endpoint invocations.
*
* @author Juergen Hoeller
* @since 2.5
* @see #setTransactionManager
*/
public abstract class AbstractMessageEndpointFactory implements MessageEndpointFactory, BeanNameAware {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private TransactionFactory transactionFactory;
private String transactionName;
private int transactionTimeout = -1;
private String beanName;
/**
* Set the the XA transaction manager to use for wrapping endpoint
* invocations, enlisting the endpoint resource in each such transaction.
* <p>The passed-in object may be a transaction manager which implements
* Spring's {@link com.fr.third.springframework.transaction.jta.TransactionFactory}
* interface, or a plain {@link javax.transaction.TransactionManager}.
* <p>If no transaction manager is specified, the endpoint invocation
* will simply not be wrapped in an XA transaction. Check out your
* resource provider's ActivationSpec documentation for local
* transaction options of your particular provider.
* @see #setTransactionName
* @see #setTransactionTimeout
*/
public void setTransactionManager(Object transactionManager) {
if (transactionManager instanceof TransactionFactory) {
this.transactionFactory = (TransactionFactory) transactionManager;
}
else if (transactionManager instanceof TransactionManager) {
this.transactionFactory = new SimpleTransactionFactory((TransactionManager) transactionManager);
}
else {
throw new IllegalArgumentException("Transaction manager [" + transactionManager +
"] is neither a [com.fr.third.springframework.transaction.jta.TransactionFactory} nor a " +
"[javax.transaction.TransactionManager]");
}
}
/**
* Set the Spring TransactionFactory to use for wrapping endpoint
* invocations, enlisting the endpoint resource in each such transaction.
* <p>Alternatively, specify an appropriate transaction manager through
* the {@link #setTransactionManager "transactionManager"} property.
* <p>If no transaction factory is specified, the endpoint invocation
* will simply not be wrapped in an XA transaction. Check out your
* resource provider's ActivationSpec documentation for local
* transaction options of your particular provider.
* @see #setTransactionName
* @see #setTransactionTimeout
*/
public void setTransactionFactory(TransactionFactory transactionFactory) {
this.transactionFactory = transactionFactory;
}
/**
* Specify the name of the transaction, if any.
* <p>Default is none. A specified name will be passed on to the transaction
* manager, allowing to identify the transaction in a transaction monitor.
*/
public void setTransactionName(String transactionName) {
this.transactionName = transactionName;
}
/**
* Specify the transaction timeout, if any.
* <p>Default is -1: rely on the transaction manager's default timeout.
* Specify a concrete timeout to restrict the maximum duration of each
* endpoint invocation.
*/
public void setTransactionTimeout(int transactionTimeout) {
this.transactionTimeout = transactionTimeout;
}
/**
* Set the name of this message endpoint. Populated with the bean name
* automatically when defined within Spring's bean factory.
*/
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
/**
* Implementation of the JCA 1.7 {@code #getActivationName()} method,
* returning the bean name as set on this MessageEndpointFactory.
* @see #setBeanName
*/
public String getActivationName() {
return this.beanName;
}
/**
* This implementation returns {@code true} if a transaction manager
* has been specified; {@code false} otherwise.
* @see #setTransactionManager
* @see #setTransactionFactory
*/
@Override
public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException {
return (this.transactionFactory != null);
}
/**
* The standard JCA 1.5 version of {@code createEndpoint}.
* <p>This implementation delegates to {@link #createEndpointInternal()},
* initializing the endpoint's XAResource before the endpoint gets invoked.
*/
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
AbstractMessageEndpoint endpoint = createEndpointInternal();
endpoint.initXAResource(xaResource);
return endpoint;
}
/**
* The alternative JCA 1.6 version of {@code createEndpoint}.
* <p>This implementation delegates to {@link #createEndpointInternal()},
* ignoring the specified timeout. It is only here for JCA 1.6 compliance.
*/
public MessageEndpoint createEndpoint(XAResource xaResource, long timeout) throws UnavailableException {
AbstractMessageEndpoint endpoint = createEndpointInternal();
endpoint.initXAResource(xaResource);
return endpoint;
}
/**
* Create the actual endpoint instance, as a subclass of the
* {@link AbstractMessageEndpoint} inner class of this factory.
* @return the actual endpoint instance (never {@code null})
* @throws UnavailableException if no endpoint is available at present
*/
protected abstract AbstractMessageEndpoint createEndpointInternal() throws UnavailableException;
/**
* Inner class for actual endpoint implementations, based on template
* method to allow for any kind of concrete endpoint implementation.
*/
protected abstract class AbstractMessageEndpoint implements MessageEndpoint {
private TransactionDelegate transactionDelegate;
private boolean beforeDeliveryCalled = false;
private ClassLoader previousContextClassLoader;
/**
* Initialize this endpoint's TransactionDelegate.
* @param xaResource the XAResource for this endpoint
*/
void initXAResource(XAResource xaResource) {
this.transactionDelegate = new TransactionDelegate(xaResource);
}
/**
* This {@code beforeDelivery} implementation starts a transaction,
* if necessary, and exposes the endpoint ClassLoader as current
* thread context ClassLoader.
* <p>Note that the JCA 1.5 specification does not require a ResourceAdapter
* to call this method before invoking the concrete endpoint. If this method
* has not been called (check {@link #hasBeforeDeliveryBeenCalled()}), the
* concrete endpoint method should call {@code beforeDelivery} and its
* sibling {@link #afterDelivery()} explicitly, as part of its own processing.
*/
@Override
public void beforeDelivery(Method method) throws ResourceException {
this.beforeDeliveryCalled = true;
try {
this.transactionDelegate.beginTransaction();
}
catch (Throwable ex) {
throw new ApplicationServerInternalException("Failed to begin transaction", ex);
}
Thread currentThread = Thread.currentThread();
this.previousContextClassLoader = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(getEndpointClassLoader());
}
/**
* Template method for exposing the endpoint's ClassLoader
* (typically the ClassLoader that the message listener class
* has been loaded with).
* @return the endpoint ClassLoader (never {@code null})
*/
protected abstract ClassLoader getEndpointClassLoader();
/**
* Return whether the {@link #beforeDelivery} method of this endpoint
* has already been called.
*/
protected final boolean hasBeforeDeliveryBeenCalled() {
return this.beforeDeliveryCalled;
}
/**
* Callback method for notifying the endpoint base class
* that the concrete endpoint invocation led to an exception.
* <p>To be invoked by subclasses in case of the concrete
* endpoint throwing an exception.
* @param ex the exception thrown from the concrete endpoint
*/
protected final void onEndpointException(Throwable ex) {
this.transactionDelegate.setRollbackOnly();
}
/**
* This {@code afterDelivery} implementation resets the thread context
* ClassLoader and completes the transaction, if any.
* <p>Note that the JCA 1.5 specification does not require a ResourceAdapter
* to call this method after invoking the concrete endpoint. See the
* explanation in {@link #beforeDelivery}'s javadoc.
*/
@Override
public void afterDelivery() throws ResourceException {
this.beforeDeliveryCalled = false;
Thread.currentThread().setContextClassLoader(this.previousContextClassLoader);
this.previousContextClassLoader = null;
try {
this.transactionDelegate.endTransaction();
}
catch (Throwable ex) {
throw new ApplicationServerInternalException("Failed to complete transaction", ex);
}
}
@Override
public void release() {
try {
this.transactionDelegate.setRollbackOnly();
this.transactionDelegate.endTransaction();
}
catch (Throwable ex) {
logger.error("Could not complete unfinished transaction on endpoint release", ex);
}
}
}
/**
* Private inner class that performs the actual transaction handling,
* including enlistment of the endpoint's XAResource.
*/
private class TransactionDelegate {
private final XAResource xaResource;
private Transaction transaction;
private boolean rollbackOnly;
public TransactionDelegate(XAResource xaResource) {
if (xaResource == null) {
if (transactionFactory != null && !transactionFactory.supportsResourceAdapterManagedTransactions()) {
throw new IllegalStateException("ResourceAdapter-provided XAResource is required for " +
"transaction management. Check your ResourceAdapter's configuration.");
}
}
this.xaResource = xaResource;
}
public void beginTransaction() throws Exception {
if (transactionFactory != null && this.xaResource != null) {
this.transaction = transactionFactory.createTransaction(transactionName, transactionTimeout);
this.transaction.enlistResource(this.xaResource);
}
}
public void setRollbackOnly() {
if (this.transaction != null) {
this.rollbackOnly = true;
}
}
public void endTransaction() throws Exception {
if (this.transaction != null) {
try {
if (this.rollbackOnly) {
this.transaction.rollback();
}
else {
this.transaction.commit();
}
}
finally {
this.transaction = null;
this.rollbackOnly = false;
}
}
}
}
}

160
fine-spring/src/com/fr/third/springframework/jca/endpoint/GenericMessageEndpointFactory.java

@ -0,0 +1,160 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.endpoint;
import javax.resource.ResourceException;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.transaction.xa.XAResource;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import com.fr.third.springframework.aop.framework.ProxyFactory;
import com.fr.third.springframework.aop.support.DelegatingIntroductionInterceptor;
import com.fr.third.springframework.util.ReflectionUtils;
/**
* Generic implementation of the JCA 1.5
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface,
* providing transaction management capabilities for any kind of message
* listener object (e.g. {@link javax.jms.MessageListener} objects or
* {@link javax.resource.cci.MessageListener} objects.
*
* <p>Uses AOP proxies for concrete endpoint instances, simply wrapping
* the specified message listener object and exposing all of its implemented
* interfaces on the endpoint instance.
*
* <p>Typically used with Spring's {@link GenericMessageEndpointManager},
* but not tied to it. As a consequence, this endpoint factory could
* also be used with programmatic endpoint management on a native
* {@link javax.resource.spi.ResourceAdapter} instance.
*
* @author Juergen Hoeller
* @since 2.5
* @see #setMessageListener
* @see #setTransactionManager
* @see GenericMessageEndpointManager
*/
public class GenericMessageEndpointFactory extends AbstractMessageEndpointFactory {
private Object messageListener;
/**
* Specify the message listener object that the endpoint should expose
* (e.g. a {@link javax.jms.MessageListener} objects or
* {@link javax.resource.cci.MessageListener} implementation).
*/
public void setMessageListener(Object messageListener) {
this.messageListener = messageListener;
}
/**
* Wrap each concrete endpoint instance with an AOP proxy,
* exposing the message listener's interfaces as well as the
* endpoint SPI through an AOP introduction.
*/
@Override
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException {
GenericMessageEndpoint endpoint = (GenericMessageEndpoint) super.createEndpoint(xaResource);
ProxyFactory proxyFactory = new ProxyFactory(this.messageListener);
DelegatingIntroductionInterceptor introduction = new DelegatingIntroductionInterceptor(endpoint);
introduction.suppressInterface(MethodInterceptor.class);
proxyFactory.addAdvice(introduction);
return (MessageEndpoint) proxyFactory.getProxy();
}
/**
* Creates a concrete generic message endpoint, internal to this factory.
*/
@Override
protected AbstractMessageEndpoint createEndpointInternal() throws UnavailableException {
return new GenericMessageEndpoint();
}
/**
* Private inner class that implements the concrete generic message endpoint,
* as an AOP Alliance MethodInterceptor that will be invoked by a proxy.
*/
private class GenericMessageEndpoint extends AbstractMessageEndpoint implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
boolean applyDeliveryCalls = !hasBeforeDeliveryBeenCalled();
if (applyDeliveryCalls) {
try {
beforeDelivery(null);
}
catch (ResourceException ex) {
if (ReflectionUtils.declaresException(methodInvocation.getMethod(), ex.getClass())) {
throw ex;
}
else {
throw new InternalResourceException(ex);
}
}
}
try {
return methodInvocation.proceed();
}
catch (Throwable ex) {
onEndpointException(ex);
throw ex;
}
finally {
if (applyDeliveryCalls) {
try {
afterDelivery();
}
catch (ResourceException ex) {
if (ReflectionUtils.declaresException(methodInvocation.getMethod(), ex.getClass())) {
throw ex;
}
else {
throw new InternalResourceException(ex);
}
}
}
}
}
@Override
protected ClassLoader getEndpointClassLoader() {
return messageListener.getClass().getClassLoader();
}
}
/**
* Internal exception thrown when a ResourceException has been encountered
* during the endpoint invocation.
* <p>Will only be used if the ResourceAdapter does not invoke the
* endpoint's {@code beforeDelivery} and {@code afterDelivery}
* directly, leaving it up to the concrete endpoint to apply those -
* and to handle any ResourceExceptions thrown from them.
*/
@SuppressWarnings("serial")
public static class InternalResourceException extends RuntimeException {
protected InternalResourceException(ResourceException cause) {
super(cause);
}
}
}

334
fine-spring/src/com/fr/third/springframework/jca/endpoint/GenericMessageEndpointManager.java

@ -0,0 +1,334 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.endpoint;
import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import com.fr.third.springframework.beans.factory.DisposableBean;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.context.SmartLifecycle;
/**
* Generic bean that manages JCA 1.5 message endpoints within a Spring
* application context, activating and deactivating the endpoint as part
* of the application context's lifecycle.
*
* <p>This class is completely generic in that it may work with any
* ResourceAdapter, any MessageEndpointFactory, and any ActivationSpec.
* It can be configured in standard bean style, for example through
* Spring's XML bean definition format, as follows:
*
* <pre class="code">
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"&gt;
* &lt;property name="resourceAdapter" ref="resourceAdapter"/&gt;
* &lt;property name="messageEndpointFactory"&gt;
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"&gt;
* &lt;property name="messageListener" ref="messageListener"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;property name="activationSpec"&gt;
* &lt;bean class="org.apache.activemq.ra.ActiveMQActivationSpec"&gt;
* &lt;property name="destination" value="myQueue"/&gt;
* &lt;property name="destinationType" value="javax.jms.Queue"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* In this example, Spring's own {@link GenericMessageEndpointFactory} is used
* to point to a standard message listener object that happens to be supported
* by the specified target ResourceAdapter: in this case, a JMS
* {@link javax.jms.MessageListener} object as supported by the ActiveMQ
* message broker, defined as a Spring bean:
*
* <pre class="code">
* &lt;bean id="messageListener" class="com.myorg.messaging.myMessageListener"&gt;
* ...
* &lt;/bean&gt;</pre>
*
* The target ResourceAdapter may be configured as a local Spring bean as well
* (the typical case) or obtained from JNDI (e.g. on WebLogic). For the
* example above, a local ResourceAdapter bean could be defined as follows
* (matching the "resourceAdapter" bean reference above):
*
* <pre class="code">
* &lt;bean id="resourceAdapter" class="com.fr.third.springframework.jca.support.ResourceAdapterFactoryBean"&gt;
* &lt;property name="resourceAdapter"&gt;
* &lt;bean class="org.apache.activemq.ra.ActiveMQResourceAdapter"&gt;
* &lt;property name="serverUrl" value="tcp://localhost:61616"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;property name="workManager"&gt;
* &lt;bean class="com.fr.third.springframework.jca.work.SimpleTaskWorkManager"/&gt;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* For a different target resource, the configuration would simply point to a
* different ResourceAdapter and a different ActivationSpec object (which are
* both specific to the resource provider), and possibly a different message
* listener (e.g. a CCI {@link javax.resource.cci.MessageListener} for a
* resource adapter which is based on the JCA Common Client Interface).
*
* <p>The asynchronous execution strategy can be customized through the
* "workManager" property on the ResourceAdapterFactoryBean (as shown above).
* Check out {@link com.fr.third.springframework.jca.work.SimpleTaskWorkManager}'s
* javadoc for its configuration options; alternatively, any other
* JCA-compliant WorkManager can be used (e.g. Geronimo's).
*
* <p>Transactional execution is a responsibility of the concrete message endpoint,
* as built by the specified MessageEndpointFactory. {@link GenericMessageEndpointFactory}
* supports XA transaction participation through its "transactionManager" property,
* typically with a Spring {@link com.fr.third.springframework.transaction.jta.JtaTransactionManager}
* or a plain {@link javax.transaction.TransactionManager} implementation specified there.
*
* <pre class="code">
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"&gt;
* &lt;property name="resourceAdapter" ref="resourceAdapter"/&gt;
* &lt;property name="messageEndpointFactory"&gt;
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"&gt;
* &lt;property name="messageListener" ref="messageListener"/&gt;
* &lt;property name="transactionManager" ref="transactionManager"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;property name="activationSpec"&gt;
* &lt;bean class="org.apache.activemq.ra.ActiveMQActivationSpec"&gt;
* &lt;property name="destination" value="myQueue"/&gt;
* &lt;property name="destinationType" value="javax.jms.Queue"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;/bean&gt;
*
* &lt;bean id="transactionManager" class="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/&gt;</pre>
*
* Alternatively, check out your resource provider's ActivationSpec object,
* which should support local transactions through a provider-specific config flag,
* e.g. ActiveMQActivationSpec's "useRAManagedTransaction" bean property.
*
* <pre class="code">
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"&gt;
* &lt;property name="resourceAdapter" ref="resourceAdapter"/&gt;
* &lt;property name="messageEndpointFactory"&gt;
* &lt;bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"&gt;
* &lt;property name="messageListener" ref="messageListener"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;property name="activationSpec"&gt;
* &lt;bean class="org.apache.activemq.ra.ActiveMQActivationSpec"&gt;
* &lt;property name="destination" value="myQueue"/&gt;
* &lt;property name="destinationType" value="javax.jms.Queue"/&gt;
* &lt;property name="useRAManagedTransaction" value="true"/&gt;
* &lt;/bean&gt;
* &lt;/property&gt;
* &lt;/bean&gt;</pre>
*
* @author Juergen Hoeller
* @since 2.5
* @see javax.resource.spi.ResourceAdapter#endpointActivation
* @see javax.resource.spi.ResourceAdapter#endpointDeactivation
* @see javax.resource.spi.endpoint.MessageEndpointFactory
* @see javax.resource.spi.ActivationSpec
*/
public class GenericMessageEndpointManager implements SmartLifecycle, InitializingBean, DisposableBean {
private ResourceAdapter resourceAdapter;
private MessageEndpointFactory messageEndpointFactory;
private ActivationSpec activationSpec;
private boolean autoStartup = true;
private int phase = Integer.MAX_VALUE;
private boolean running = false;
private final Object lifecycleMonitor = new Object();
/**
* Set the JCA ResourceAdapter to manage endpoints for.
*/
public void setResourceAdapter(ResourceAdapter resourceAdapter) {
this.resourceAdapter = resourceAdapter;
}
/**
* Return the JCA ResourceAdapter to manage endpoints for.
*/
public ResourceAdapter getResourceAdapter() {
return this.resourceAdapter;
}
/**
* Set the JCA MessageEndpointFactory to activate, pointing to a
* MessageListener object that the endpoints will delegate to.
* <p>A MessageEndpointFactory instance may be shared across multiple
* endpoints (i.e. multiple GenericMessageEndpointManager instances),
* with different {@link #setActivationSpec ActivationSpec} objects applied.
* @see GenericMessageEndpointFactory#setMessageListener
*/
public void setMessageEndpointFactory(MessageEndpointFactory messageEndpointFactory) {
this.messageEndpointFactory = messageEndpointFactory;
}
/**
* Return the JCA MessageEndpointFactory to activate.
*/
public MessageEndpointFactory getMessageEndpointFactory() {
return this.messageEndpointFactory;
}
/**
* Set the JCA ActivationSpec to use for activating the endpoint.
* <p>Note that this ActivationSpec instance should not be shared
* across multiple ResourceAdapter instances.
*/
public void setActivationSpec(ActivationSpec activationSpec) {
this.activationSpec = activationSpec;
}
/**
* Return the JCA ActivationSpec to use for activating the endpoint.
*/
public ActivationSpec getActivationSpec() {
return this.activationSpec;
}
/**
* Set whether to auto-start the endpoint activation after this endpoint
* manager has been initialized and the context has been refreshed.
* <p>Default is "true". Turn this flag off to defer the endpoint
* activation until an explicit {#start()} call.
*/
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
/**
* Return the value for the 'autoStartup' property. If "true", this
* endpoint manager will start upon a ContextRefreshedEvent.
*/
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
/**
* Specify the phase in which this endpoint manager should be started
* and stopped. The startup order proceeds from lowest to highest, and
* the shutdown order is the reverse of that. By default this value is
* Integer.MAX_VALUE meaning that this endpoint manager starts as late
* as possible and stops as soon as possible.
*/
public void setPhase(int phase) {
this.phase = phase;
}
/**
* Return the phase in which this endpoint manager will be started and stopped.
*/
@Override
public int getPhase() {
return this.phase;
}
/**
* Prepares the message endpoint, and automatically activates it
* if the "autoStartup" flag is set to "true".
*/
@Override
public void afterPropertiesSet() throws ResourceException {
if (getResourceAdapter() == null) {
throw new IllegalArgumentException("Property 'resourceAdapter' is required");
}
if (getMessageEndpointFactory() == null) {
throw new IllegalArgumentException("Property 'messageEndpointFactory' is required");
}
ActivationSpec activationSpec = getActivationSpec();
if (activationSpec == null) {
throw new IllegalArgumentException("Property 'activationSpec' is required");
}
if (activationSpec.getResourceAdapter() == null) {
activationSpec.setResourceAdapter(getResourceAdapter());
}
else if (activationSpec.getResourceAdapter() != getResourceAdapter()) {
throw new IllegalArgumentException("ActivationSpec [" + activationSpec +
"] is associated with a different ResourceAdapter: " + activationSpec.getResourceAdapter());
}
}
/**
* Activates the configured message endpoint.
*/
@Override
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.running) {
try {
getResourceAdapter().endpointActivation(getMessageEndpointFactory(), getActivationSpec());
}
catch (ResourceException ex) {
throw new IllegalStateException("Could not activate message endpoint", ex);
}
this.running = true;
}
}
}
/**
* Deactivates the configured message endpoint.
*/
@Override
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.running) {
getResourceAdapter().endpointDeactivation(getMessageEndpointFactory(), getActivationSpec());
this.running = false;
}
}
}
@Override
public void stop(Runnable callback) {
synchronized (this.lifecycleMonitor) {
this.stop();
callback.run();
}
}
/**
* Return whether the configured message endpoint is currently active.
*/
@Override
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.running;
}
}
/**
* Deactivates the message endpoint, preparing it for shutdown.
*/
@Override
public void destroy() {
stop();
}
}

8
fine-spring/src/com/fr/third/springframework/jca/endpoint/package-info.java

@ -0,0 +1,8 @@
/**
*
* This package provides a facility for generic JCA message endpoint management.
*
*/
package com.fr.third.springframework.jca.endpoint;

141
fine-spring/src/com/fr/third/springframework/jca/support/LocalConnectionFactoryBean.java

@ -0,0 +1,141 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.support;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
import com.fr.third.springframework.beans.factory.FactoryBean;
import com.fr.third.springframework.beans.factory.InitializingBean;
/**
* {@link com.fr.third.springframework.beans.factory.FactoryBean} that creates
* a local JCA connection factory in "non-managed" mode (as defined by the
* Java Connector Architecture specification). This is a direct alternative
* to a {@link com.fr.third.springframework.jndi.JndiObjectFactoryBean} definition that
* obtains a connection factory handle from a J2EE server's naming environment.
*
* <p>The type of the connection factory is dependent on the actual connector:
* the connector can either expose its native API (such as a JDBC
* {@link javax.sql.DataSource} or a JMS {@link javax.jms.ConnectionFactory})
* or follow the standard Common Client Interface (CCI), as defined by the JCA spec.
* The exposed interface in the CCI case is {@link javax.resource.cci.ConnectionFactory}.
*
* <p>In order to use this FactoryBean, you must specify the connector's
* {@link #setManagedConnectionFactory "managedConnectionFactory"} (usually
* configured as separate JavaBean), which will be used to create the actual
* connection factory reference as exposed to the application. Optionally,
* you can also specify a {@link #setConnectionManager "connectionManager"},
* in order to use a custom ConnectionManager instead of the connector's default.
*
* <p><b>NOTE:</b> In non-managed mode, a connector is not deployed on an
* application server, or more specificially not interacting with an application
* server. Consequently, it cannot use a J2EE server's system contracts:
* connection management, transaction management, and security management.
* A custom ConnectionManager implementation has to be used for applying those
* services in conjunction with a standalone transaction coordinator etc.
*
* <p>The connector will use a local ConnectionManager (included in the connector)
* by default, which cannot participate in global transactions due to the lack
* of XA enlistment. You need to specify an XA-capable ConnectionManager in
* order to make the connector interact with an XA transaction coordinator.
* Alternatively, simply use the native local transaction facilities of the
* exposed API (e.g. CCI local transactions), or use a corresponding
* implementation of Spring's PlatformTransactionManager SPI
* (e.g. {@link com.fr.third.springframework.jca.cci.connection.CciLocalTransactionManager})
* to drive local transactions.
*
* @author Juergen Hoeller
* @since 1.2
* @see #setManagedConnectionFactory
* @see #setConnectionManager
* @see javax.resource.cci.ConnectionFactory
* @see javax.resource.cci.Connection#getLocalTransaction
* @see com.fr.third.springframework.jca.cci.connection.CciLocalTransactionManager
*/
public class LocalConnectionFactoryBean implements FactoryBean<Object>, InitializingBean {
private ManagedConnectionFactory managedConnectionFactory;
private ConnectionManager connectionManager;
private Object connectionFactory;
/**
* Set the JCA ManagerConnectionFactory that should be used to create
* the desired connection factory.
* <p>The ManagerConnectionFactory will usually be set up as separate bean
* (potentially as inner bean), populated with JavaBean properties:
* a ManagerConnectionFactory is encouraged to follow the JavaBean pattern
* by the JCA specification, analogous to a JDBC DataSource and a JDO
* PersistenceManagerFactory.
* <p>Note that the ManagerConnectionFactory implementation might expect
* a reference to its JCA 1.5 ResourceAdapter, expressed through the
* {@link javax.resource.spi.ResourceAdapterAssociation} interface.
* Simply inject the corresponding ResourceAdapter instance into its
* "resourceAdapter" bean property in this case, before passing the
* ManagerConnectionFactory into this LocalConnectionFactoryBean.
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory()
*/
public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) {
this.managedConnectionFactory = managedConnectionFactory;
}
/**
* Set the JCA ConnectionManager that should be used to create the
* desired connection factory.
* <p>A ConnectionManager implementation for local usage is often
* included with a JCA connector. Such an included ConnectionManager
* might be set as default, with no need to explicitly specify one.
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager)
*/
public void setConnectionManager(ConnectionManager connectionManager) {
this.connectionManager = connectionManager;
}
@Override
public void afterPropertiesSet() throws ResourceException {
if (this.managedConnectionFactory == null) {
throw new IllegalArgumentException("Property 'managedConnectionFactory' is required");
}
if (this.connectionManager != null) {
this.connectionFactory = this.managedConnectionFactory.createConnectionFactory(this.connectionManager);
}
else {
this.connectionFactory = this.managedConnectionFactory.createConnectionFactory();
}
}
@Override
public Object getObject() {
return this.connectionFactory;
}
@Override
public Class<?> getObjectType() {
return (this.connectionFactory != null ? this.connectionFactory.getClass() : null);
}
@Override
public boolean isSingleton() {
return true;
}
}

153
fine-spring/src/com/fr/third/springframework/jca/support/ResourceAdapterFactoryBean.java

@ -0,0 +1,153 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.support;
import javax.resource.ResourceException;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.XATerminator;
import javax.resource.spi.work.WorkManager;
import com.fr.third.springframework.beans.BeanUtils;
import com.fr.third.springframework.beans.factory.DisposableBean;
import com.fr.third.springframework.beans.factory.FactoryBean;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.util.Assert;
/**
* {@link com.fr.third.springframework.beans.factory.FactoryBean} that bootstraps
* the specified JCA 1.5 {@link javax.resource.spi.ResourceAdapter},
* starting it with a local {@link javax.resource.spi.BootstrapContext}
* and exposing it for bean references. It will also stop the ResourceAdapter
* on context shutdown. This corresponds to 'non-managed' bootstrap in a
* local environment, according to the JCA 1.5 specification.
*
* <p>This is essentially an adapter for bean-style bootstrapping of a
* JCA ResourceAdapter, allowing the BootstrapContext or its elements
* (such as the JCA WorkManager) to be specified through bean properties.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see #setResourceAdapter
* @see #setBootstrapContext
* @see #setWorkManager
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
* @see javax.resource.spi.ResourceAdapter#stop()
*/
public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>, InitializingBean, DisposableBean {
private ResourceAdapter resourceAdapter;
private BootstrapContext bootstrapContext;
private WorkManager workManager;
private XATerminator xaTerminator;
/**
* Specify the target JCA ResourceAdapter as class, to be instantiated
* with its default configuration.
* <p>Alternatively, specify a pre-configured ResourceAdapter instance
* through the "resourceAdapter" property.
* @see #setResourceAdapter
*/
public void setResourceAdapterClass(Class<?> resourceAdapterClass) {
Assert.isAssignable(ResourceAdapter.class, resourceAdapterClass);
this.resourceAdapter = (ResourceAdapter) BeanUtils.instantiateClass(resourceAdapterClass);
}
/**
* Specify the target JCA ResourceAdapter, passed in as configured instance
* which hasn't been started yet. This will typically happen as an
* inner bean definition, configuring the ResourceAdapter instance
* through its vendor-specific bean properties.
*/
public void setResourceAdapter(ResourceAdapter resourceAdapter) {
this.resourceAdapter = resourceAdapter;
}
/**
* Specify the JCA BootstrapContext to use for starting the ResourceAdapter.
* <p>Alternatively, you can specify the individual parts (such as the
* JCA WorkManager) as individual references.
* @see #setWorkManager
* @see #setXaTerminator
*/
public void setBootstrapContext(BootstrapContext bootstrapContext) {
this.bootstrapContext = bootstrapContext;
}
/**
* Specify the JCA WorkManager to use for bootstrapping the ResourceAdapter.
* @see #setBootstrapContext
*/
public void setWorkManager(WorkManager workManager) {
this.workManager = workManager;
}
/**
* Specify the JCA XATerminator to use for bootstrapping the ResourceAdapter.
* @see #setBootstrapContext
*/
public void setXaTerminator(XATerminator xaTerminator) {
this.xaTerminator = xaTerminator;
}
/**
* Builds the BootstrapContext and starts the ResourceAdapter with it.
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
*/
@Override
public void afterPropertiesSet() throws ResourceException {
if (this.resourceAdapter == null) {
throw new IllegalArgumentException("'resourceAdapter' or 'resourceAdapterClass' is required");
}
if (this.bootstrapContext == null) {
this.bootstrapContext = new SimpleBootstrapContext(this.workManager, this.xaTerminator);
}
this.resourceAdapter.start(this.bootstrapContext);
}
@Override
public ResourceAdapter getObject() {
return this.resourceAdapter;
}
@Override
public Class<? extends ResourceAdapter> getObjectType() {
return (this.resourceAdapter != null ? this.resourceAdapter.getClass() : ResourceAdapter.class);
}
@Override
public boolean isSingleton() {
return true;
}
/**
* Stops the ResourceAdapter.
* @see javax.resource.spi.ResourceAdapter#stop()
*/
@Override
public void destroy() {
this.resourceAdapter.stop();
}
}

83
fine-spring/src/com/fr/third/springframework/jca/support/SimpleBootstrapContext.java

@ -0,0 +1,83 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.support;
import java.util.Timer;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.XATerminator;
import javax.resource.spi.work.WorkManager;
/**
* Simple implementation of the JCA 1.5 {@link javax.resource.spi.BootstrapContext}
* interface, used for bootstrapping a JCA ResourceAdapter in a local environment.
*
* <p>Delegates to the given WorkManager and XATerminator, if any. Creates simple
* local instances of {@code java.util.Timer}.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
* @see ResourceAdapterFactoryBean
*/
public class SimpleBootstrapContext implements BootstrapContext {
private WorkManager workManager;
private XATerminator xaTerminator;
/**
* Create a new SimpleBootstrapContext for the given WorkManager,
* with no XATerminator available.
* @param workManager the JCA WorkManager to use (may be {@code null})
*/
public SimpleBootstrapContext(WorkManager workManager) {
this.workManager = workManager;
}
/**
* Create a new SimpleBootstrapContext for the given WorkManager and XATerminator.
* @param workManager the JCA WorkManager to use (may be {@code null})
* @param xaTerminator the JCA XATerminator to use (may be {@code null})
*/
public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator) {
this.workManager = workManager;
this.xaTerminator = xaTerminator;
}
@Override
public WorkManager getWorkManager() {
if (this.workManager == null) {
throw new IllegalStateException("No WorkManager available");
}
return this.workManager;
}
@Override
public XATerminator getXATerminator() {
return this.xaTerminator;
}
@Override
public Timer createTimer() throws UnavailableException {
return new Timer();
}
}

9
fine-spring/src/com/fr/third/springframework/jca/support/package-info.java

@ -0,0 +1,9 @@
/**
*
* Provides generic support classes for JCA usage within Spring,
* mainly for local setup of a JCA ResourceAdapter and/or ConnectionFactory.
*
*/
package com.fr.third.springframework.jca.support;

69
fine-spring/src/com/fr/third/springframework/jca/work/DelegatingWork.java

@ -0,0 +1,69 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.work;
import javax.resource.spi.work.Work;
import com.fr.third.springframework.util.Assert;
/**
* Simple Work adapter that delegates to a given Runnable.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see javax.resource.spi.work.Work
* @see Runnable
*/
public class DelegatingWork implements Work {
private final Runnable delegate;
/**
* Create a new DelegatingWork.
* @param delegate the Runnable implementation to delegate to
*/
public DelegatingWork(Runnable delegate) {
Assert.notNull(delegate, "Delegate must not be null");
this.delegate = delegate;
}
/**
* Return the wrapped Runnable implementation.
*/
public final Runnable getDelegate() {
return this.delegate;
}
/**
* Delegates execution to the underlying Runnable.
*/
@Override
public void run() {
this.delegate.run();
}
/**
* This implementation is empty, since we expect the Runnable
* to terminate based on some specific shutdown signal.
*/
@Override
public void release() {
}
}

260
fine-spring/src/com/fr/third/springframework/jca/work/SimpleTaskWorkManager.java

@ -0,0 +1,260 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.work;
import javax.resource.spi.work.ExecutionContext;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkAdapter;
import javax.resource.spi.work.WorkCompletedException;
import javax.resource.spi.work.WorkEvent;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkListener;
import javax.resource.spi.work.WorkManager;
import javax.resource.spi.work.WorkRejectedException;
import com.fr.third.springframework.core.task.AsyncTaskExecutor;
import com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor;
import com.fr.third.springframework.core.task.SyncTaskExecutor;
import com.fr.third.springframework.core.task.TaskExecutor;
import com.fr.third.springframework.core.task.TaskRejectedException;
import com.fr.third.springframework.core.task.TaskTimeoutException;
import com.fr.third.springframework.util.Assert;
/**
* Simple JCA 1.5 {@link javax.resource.spi.work.WorkManager} implementation that
* delegates to a Spring {@link com.fr.third.springframework.core.task.TaskExecutor}.
* Provides simple task execution including start timeouts, but without support
* for a JCA ExecutionContext (i.e. without support for imported transactions).
*
* <p>Uses a {@link com.fr.third.springframework.core.task.SyncTaskExecutor} for {@link #doWork}
* calls and a {@link com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor}
* for {@link #startWork} and {@link #scheduleWork} calls, by default.
* These default task executors can be overridden through configuration.
*
* <p><b>NOTE: This WorkManager does not provide thread pooling by default!</b>
* Specify a {@link com.fr.third.springframework.scheduling.concurrent.ThreadPoolTaskExecutor}
* (or any other thread-pooling TaskExecutor) as "asyncTaskExecutor" in order to
* achieve actual thread pooling.
*
* <p>This WorkManager automatically detects a specified
* {@link com.fr.third.springframework.core.task.AsyncTaskExecutor} implementation
* and uses its extended timeout functionality where appropriate.
* JCA WorkListeners are fully supported in any case.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see #setSyncTaskExecutor
* @see #setAsyncTaskExecutor
*/
public class SimpleTaskWorkManager implements WorkManager {
private TaskExecutor syncTaskExecutor = new SyncTaskExecutor();
private AsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();
/**
* Specify the TaskExecutor to use for <i>synchronous</i> work execution
* (i.e. {@link #doWork} calls).
* <p>Default is a {@link com.fr.third.springframework.core.task.SyncTaskExecutor}.
*/
public void setSyncTaskExecutor(TaskExecutor syncTaskExecutor) {
this.syncTaskExecutor = syncTaskExecutor;
}
/**
* Specify the TaskExecutor to use for <i>asynchronous</i> work execution
* (i.e. {@link #startWork} and {@link #scheduleWork} calls).
* <p>This will typically (but not necessarily) be an
* {@link com.fr.third.springframework.core.task.AsyncTaskExecutor} implementation.
* Default is a {@link com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor}.
*/
public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) {
this.asyncTaskExecutor = asyncTaskExecutor;
}
@Override
public void doWork(Work work) throws WorkException {
doWork(work, WorkManager.INDEFINITE, null, null);
}
@Override
public void doWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
Assert.state(this.syncTaskExecutor != null, "No 'syncTaskExecutor' set");
executeWork(this.syncTaskExecutor, work, startTimeout, false, executionContext, workListener);
}
@Override
public long startWork(Work work) throws WorkException {
return startWork(work, WorkManager.INDEFINITE, null, null);
}
@Override
public long startWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
return executeWork(this.asyncTaskExecutor, work, startTimeout, true, executionContext, workListener);
}
@Override
public void scheduleWork(Work work) throws WorkException {
scheduleWork(work, WorkManager.INDEFINITE, null, null);
}
@Override
public void scheduleWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set");
executeWork(this.asyncTaskExecutor, work, startTimeout, false, executionContext, workListener);
}
/**
* Execute the given Work on the specified TaskExecutor.
* @param taskExecutor the TaskExecutor to use
* @param work the Work to execute
* @param startTimeout the time duration within which the Work is supposed to start
* @param blockUntilStarted whether to block until the Work has started
* @param executionContext the JCA ExecutionContext for the given Work
* @param workListener the WorkListener to clal for the given Work
* @return the time elapsed from Work acceptance until start of execution
* (or -1 if not applicable or not known)
* @throws WorkException if the TaskExecutor did not accept the Work
*/
protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout,
boolean blockUntilStarted, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
if (executionContext != null && executionContext.getXid() != null) {
throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid());
}
WorkListener workListenerToUse = workListener;
if (workListenerToUse == null) {
workListenerToUse = new WorkAdapter();
}
boolean isAsync = (taskExecutor instanceof AsyncTaskExecutor);
DelegatingWorkAdapter workHandle = new DelegatingWorkAdapter(work, workListenerToUse, !isAsync);
try {
if (isAsync) {
((AsyncTaskExecutor) taskExecutor).execute(workHandle, startTimeout);
}
else {
taskExecutor.execute(workHandle);
}
}
catch (TaskTimeoutException ex) {
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex);
wex.setErrorCode(WorkException.START_TIMED_OUT);
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
throw wex;
}
catch (TaskRejectedException ex) {
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work: " + work, ex);
wex.setErrorCode(WorkException.INTERNAL);
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex));
throw wex;
}
catch (Throwable ex) {
WorkException wex = new WorkException("TaskExecutor failed to execute Work: " + work, ex);
wex.setErrorCode(WorkException.INTERNAL);
throw wex;
}
if (isAsync) {
workListenerToUse.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
}
if (blockUntilStarted) {
long acceptanceTime = System.currentTimeMillis();
synchronized (workHandle.monitor) {
try {
while (!workHandle.started) {
workHandle.monitor.wait();
}
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
return (System.currentTimeMillis() - acceptanceTime);
}
else {
return WorkManager.UNKNOWN;
}
}
/**
* Work adapter that supports start timeouts and WorkListener callbacks
* for a given Work that it delegates to.
*/
private static class DelegatingWorkAdapter implements Work {
private final Work work;
private final WorkListener workListener;
private final boolean acceptOnExecution;
public final Object monitor = new Object();
public boolean started = false;
public DelegatingWorkAdapter(Work work, WorkListener workListener, boolean acceptOnExecution) {
this.work = work;
this.workListener = workListener;
this.acceptOnExecution = acceptOnExecution;
}
@Override
public void run() {
if (this.acceptOnExecution) {
this.workListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null));
}
synchronized (this.monitor) {
this.started = true;
this.monitor.notify();
}
this.workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, this.work, null));
try {
this.work.run();
}
catch (RuntimeException ex) {
this.workListener.workCompleted(
new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(ex)));
throw ex;
}
catch (Error err) {
this.workListener.workCompleted(
new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(err)));
throw err;
}
this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, null));
}
@Override
public void release() {
this.work.release();
}
}
}

319
fine-spring/src/com/fr/third/springframework/jca/work/WorkManagerTaskExecutor.java

@ -0,0 +1,319 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.work;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import javax.naming.NamingException;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.work.ExecutionContext;
import javax.resource.spi.work.Work;
import javax.resource.spi.work.WorkException;
import javax.resource.spi.work.WorkListener;
import javax.resource.spi.work.WorkManager;
import javax.resource.spi.work.WorkRejectedException;
import com.fr.third.springframework.beans.factory.InitializingBean;
import com.fr.third.springframework.core.task.AsyncListenableTaskExecutor;
import com.fr.third.springframework.core.task.TaskRejectedException;
import com.fr.third.springframework.core.task.TaskTimeoutException;
import com.fr.third.springframework.jca.context.BootstrapContextAware;
import com.fr.third.springframework.jndi.JndiLocatorSupport;
import com.fr.third.springframework.scheduling.SchedulingException;
import com.fr.third.springframework.scheduling.SchedulingTaskExecutor;
import com.fr.third.springframework.util.Assert;
import com.fr.third.springframework.util.concurrent.ListenableFuture;
import com.fr.third.springframework.util.concurrent.ListenableFutureTask;
/**
* {@link com.fr.third.springframework.core.task.TaskExecutor} implementation
* that delegates to a JCA 1.5 WorkManager, implementing the
* {@link javax.resource.spi.work.WorkManager} interface.
*
* <p>This is mainly intended for use within a JCA ResourceAdapter implementation,
* but may also be used in a standalone environment, delegating to a locally
* embedded WorkManager implementation (such as Geronimo's).
*
* <p>Also implements the JCA 1.5 WorkManager interface itself, delegating all
* calls to the target WorkManager. Hence, a caller can choose whether it wants
* to talk to this executor through the Spring TaskExecutor interface or the
* JCA 1.5 WorkManager interface.
*
* <p>This adapter is also capable of obtaining a JCA WorkManager from JNDI.
* This is for example appropriate on the Geronimo application server, where
* WorkManager GBeans (e.g. Geronimo's default "DefaultWorkManager" GBean)
* can be linked into the J2EE environment through "gbean-ref" entries
* in the {@code geronimo-web.xml} deployment descriptor.
*
* <p><b>On JBoss and GlassFish, obtaining the default JCA WorkManager
* requires special lookup steps.</b> See the
* {@link com.fr.third.springframework.jca.work.jboss.JBossWorkManagerTaskExecutor}
* {@link com.fr.third.springframework.jca.work.glassfish.GlassFishWorkManagerTaskExecutor}
* classes which are the direct equivalent of this generic JCA adapter class.
*
* @author Juergen Hoeller
* @since 2.0.3
* @see #setWorkManager
* @see javax.resource.spi.work.WorkManager#scheduleWork
*/
public class WorkManagerTaskExecutor extends JndiLocatorSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, BootstrapContextAware, InitializingBean {
private WorkManager workManager;
private String workManagerName;
private boolean blockUntilStarted = false;
private boolean blockUntilCompleted = false;
private WorkListener workListener;
/**
* Create a new WorkManagerTaskExecutor, expecting bean-style configuration.
* @see #setWorkManager
*/
public WorkManagerTaskExecutor() {
}
/**
* Create a new WorkManagerTaskExecutor for the given WorkManager.
* @param workManager the JCA WorkManager to delegate to
*/
public WorkManagerTaskExecutor(WorkManager workManager) {
setWorkManager(workManager);
}
/**
* Specify the JCA WorkManager instance to delegate to.
*/
public void setWorkManager(WorkManager workManager) {
Assert.notNull(workManager, "WorkManager must not be null");
this.workManager = workManager;
}
/**
* Set the JNDI name of the JCA WorkManager.
* <p>This can either be a fully qualified JNDI name,
* or the JNDI name relative to the current environment
* naming context if "resourceRef" is set to "true".
* @see #setWorkManager
* @see #setResourceRef
*/
public void setWorkManagerName(String workManagerName) {
this.workManagerName = workManagerName;
}
/**
* Specify the JCA BootstrapContext that contains the
* WorkManager to delegate to.
*/
@Override
public void setBootstrapContext(BootstrapContext bootstrapContext) {
Assert.notNull(bootstrapContext, "BootstrapContext must not be null");
this.workManager = bootstrapContext.getWorkManager();
}
/**
* Set whether to let {@link #execute} block until the work
* has been actually started.
* <p>Uses the JCA {@code startWork} operation underneath,
* instead of the default {@code scheduleWork}.
* @see javax.resource.spi.work.WorkManager#startWork
* @see javax.resource.spi.work.WorkManager#scheduleWork
*/
public void setBlockUntilStarted(boolean blockUntilStarted) {
this.blockUntilStarted = blockUntilStarted;
}
/**
* Set whether to let {@link #execute} block until the work
* has been completed.
* <p>Uses the JCA {@code doWork} operation underneath,
* instead of the default {@code scheduleWork}.
* @see javax.resource.spi.work.WorkManager#doWork
* @see javax.resource.spi.work.WorkManager#scheduleWork
*/
public void setBlockUntilCompleted(boolean blockUntilCompleted) {
this.blockUntilCompleted = blockUntilCompleted;
}
/**
* Specify a JCA 1.5 WorkListener to apply, if any.
* <p>This shared WorkListener instance will be passed on to the
* WorkManager by all {@link #execute} calls on this TaskExecutor.
*/
public void setWorkListener(WorkListener workListener) {
this.workListener = workListener;
}
@Override
public void afterPropertiesSet() throws NamingException {
if (this.workManager == null) {
if (this.workManagerName != null) {
this.workManager = lookup(this.workManagerName, WorkManager.class);
}
else {
this.workManager = getDefaultWorkManager();
}
}
}
/**
* Obtain a default WorkManager to delegate to.
* Called if no explicit WorkManager or WorkManager JNDI name has been specified.
* <p>The default implementation returns a {@link SimpleTaskWorkManager}.
* Can be overridden in subclasses.
*/
protected WorkManager getDefaultWorkManager() {
return new SimpleTaskWorkManager();
}
//-------------------------------------------------------------------------
// Implementation of the Spring SchedulingTaskExecutor interface
//-------------------------------------------------------------------------
@Override
public void execute(Runnable task) {
execute(task, TIMEOUT_INDEFINITE);
}
@Override
public void execute(Runnable task, long startTimeout) {
Assert.state(this.workManager != null, "No WorkManager specified");
Work work = new DelegatingWork(task);
try {
if (this.blockUntilCompleted) {
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
this.workManager.doWork(work, startTimeout, null, this.workListener);
}
else {
this.workManager.doWork(work);
}
}
else if (this.blockUntilStarted) {
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
this.workManager.startWork(work, startTimeout, null, this.workListener);
}
else {
this.workManager.startWork(work);
}
}
else {
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) {
this.workManager.scheduleWork(work, startTimeout, null, this.workListener);
}
else {
this.workManager.scheduleWork(work);
}
}
}
catch (WorkRejectedException ex) {
if (WorkException.START_TIMED_OUT.equals(ex.getErrorCode())) {
throw new TaskTimeoutException("JCA WorkManager rejected task because of timeout: " + task, ex);
}
else {
throw new TaskRejectedException("JCA WorkManager rejected task: " + task, ex);
}
}
catch (WorkException ex) {
throw new SchedulingException("Could not schedule task on JCA WorkManager", ex);
}
}
@Override
public Future<?> submit(Runnable task) {
FutureTask<Object> future = new FutureTask<Object>(task, null);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
@Override
public <T> Future<T> submit(Callable<T> task) {
FutureTask<T> future = new FutureTask<T>(task);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
@Override
public ListenableFuture<?> submitListenable(Runnable task) {
ListenableFutureTask<Object> future = new ListenableFutureTask<Object>(task, null);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
@Override
public <T> ListenableFuture<T> submitListenable(Callable<T> task) {
ListenableFutureTask<T> future = new ListenableFutureTask<T>(task);
execute(future, TIMEOUT_INDEFINITE);
return future;
}
/**
* This task executor prefers short-lived work units.
*/
@Override
public boolean prefersShortLivedTasks() {
return true;
}
//-------------------------------------------------------------------------
// Implementation of the JCA WorkManager interface
//-------------------------------------------------------------------------
@Override
public void doWork(Work work) throws WorkException {
this.workManager.doWork(work);
}
@Override
public void doWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
this.workManager.doWork(work, delay, executionContext, workListener);
}
@Override
public long startWork(Work work) throws WorkException {
return this.workManager.startWork(work);
}
@Override
public long startWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
return this.workManager.startWork(work, delay, executionContext, workListener);
}
@Override
public void scheduleWork(Work work) throws WorkException {
this.workManager.scheduleWork(work);
}
@Override
public void scheduleWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
this.workManager.scheduleWork(work, delay, executionContext, workListener);
}
}

81
fine-spring/src/com/fr/third/springframework/jca/work/glassfish/GlassFishWorkManagerTaskExecutor.java

@ -0,0 +1,81 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.work.glassfish;
import java.lang.reflect.Method;
import javax.resource.spi.work.WorkManager;
import com.fr.third.springframework.jca.work.WorkManagerTaskExecutor;
import com.fr.third.springframework.util.ReflectionUtils;
/**
* Spring TaskExecutor adapter for the GlassFish JCA WorkManager.
* Can be defined in web applications to make a TaskExecutor reference
* available, talking to the GlassFish WorkManager (thread pool) underneath.
*
* <p>This is the GlassFish equivalent of the CommonJ
* {@link com.fr.third.springframework.scheduling.commonj.WorkManagerTaskExecutor}
* adapter for WebLogic and WebSphere.
*
* <p>Note: On GlassFish 4 and higher, a
* {@link com.fr.third.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
* should be preferred, following JSR-236 support in Java EE 7.
*
* @author Juergen Hoeller
* @since 2.5.2
*/
public class GlassFishWorkManagerTaskExecutor extends WorkManagerTaskExecutor {
private static final String WORK_MANAGER_FACTORY_CLASS = "com.sun.enterprise.connectors.work.WorkManagerFactory";
private final Method getWorkManagerMethod;
public GlassFishWorkManagerTaskExecutor() {
try {
Class<?> wmf = getClass().getClassLoader().loadClass(WORK_MANAGER_FACTORY_CLASS);
this.getWorkManagerMethod = wmf.getMethod("getWorkManager", String.class);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize GlassFishWorkManagerTaskExecutor because GlassFish API is not available", ex);
}
}
/**
* Identify a specific GlassFish thread pool to talk to.
* <p>The thread pool name matches the resource adapter name
* in default RAR deployment scenarios.
*/
public void setThreadPoolName(String threadPoolName) {
WorkManager wm = (WorkManager) ReflectionUtils.invokeMethod(this.getWorkManagerMethod, null, threadPoolName);
if (wm == null) {
throw new IllegalArgumentException("Specified thread pool name '" + threadPoolName +
"' does not correspond to an actual pool definition in GlassFish. Check your configuration!");
}
setWorkManager(wm);
}
/**
* Obtains GlassFish's default thread pool.
*/
@Override
protected WorkManager getDefaultWorkManager() {
return (WorkManager) ReflectionUtils.invokeMethod(this.getWorkManagerMethod, null, new Object[] {null});
}
}

9
fine-spring/src/com/fr/third/springframework/jca/work/glassfish/package-info.java

@ -0,0 +1,9 @@
/**
*
* Convenience package for obtaining a GlassFish JCA WorkManager for use in
* web applications. Provides a Spring TaskExecutor adapter for GlassFish.
*
*/
package com.fr.third.springframework.jca.work.glassfish;

67
fine-spring/src/com/fr/third/springframework/jca/work/jboss/JBossWorkManagerTaskExecutor.java

@ -0,0 +1,67 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.springframework.jca.work.jboss;
import javax.resource.spi.work.WorkManager;
import com.fr.third.springframework.jca.work.WorkManagerTaskExecutor;
/**
* Spring TaskExecutor adapter for the JBoss JCA WorkManager.
* Can be defined in web applications to make a TaskExecutor reference
* available, talking to the JBoss WorkManager (thread pool) underneath.
*
* <p>This is the JBoss equivalent of the CommonJ
* {@link com.fr.third.springframework.scheduling.commonj.WorkManagerTaskExecutor}
* adapter for WebLogic and WebSphere.
*
* <p>This class does not work on JBoss 7 or higher. There is no known
* immediate replacement, since JBoss does not want its JCA WorkManager
* to be exposed anymore. As of JBoss/WildFly 8, a
* {@link com.fr.third.springframework.scheduling.concurrent.DefaultManagedTaskExecutor}
* may be used, following JSR-236 support in Java EE 7.
*
* @author Juergen Hoeller
* @since 2.5.2
* @see org.jboss.resource.work.JBossWorkManagerMBean
* @deprecated as of Spring 4.0, since there are no fully supported versions
* of JBoss that this class works with anymore
*/
@Deprecated
public class JBossWorkManagerTaskExecutor extends WorkManagerTaskExecutor {
/**
* Identify a specific JBossWorkManagerMBean to talk to,
* through its JMX object name.
* <p>The default MBean name is "jboss.jca:service=WorkManager".
* @see JBossWorkManagerUtils#getWorkManager(String)
*/
public void setWorkManagerMBeanName(String mbeanName) {
setWorkManager(JBossWorkManagerUtils.getWorkManager(mbeanName));
}
/**
* Obtains the default JBoss JCA WorkManager through a JMX lookup
* for the JBossWorkManagerMBean.
* @see JBossWorkManagerUtils#getWorkManager()
*/
@Override
protected WorkManager getDefaultWorkManager() {
return JBossWorkManagerUtils.getWorkManager();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save