Skip to content

Commit 39821b1

Browse files
authored
add a factory for AS400ConnectionPool objects (#247)
Signed-off-by: Nicola Isotta <[email protected]>
1 parent a47cee2 commit 39821b1

5 files changed

+279
-75
lines changed

src/main/java/com/ibm/as400/access/AS400ConnectionPool.java

+111-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@
2424
import java.io.Serializable;
2525
import java.io.IOException;
2626
import java.io.ObjectInputStream;
27+
import java.util.Objects;
2728

29+
import javax.naming.NamingException;
30+
import javax.naming.RefAddr;
31+
import javax.naming.Reference;
32+
import javax.naming.Referenceable;
33+
import javax.naming.StringRefAddr;
2834

2935
/**
3036
* Manages a pool of AS400 objects. A connection pool is used to
@@ -84,9 +90,20 @@
8490
* <li>PropertyChangeEvent</li>
8591
* </ul>
8692
**/
87-
public class AS400ConnectionPool extends ConnectionPool implements Serializable
93+
public class AS400ConnectionPool extends ConnectionPool implements Serializable, Referenceable
8894
{
8995
static final long serialVersionUID = 4L;
96+
97+
private static final String CCSID_PROPERTY = "ccsid";
98+
private static final String CLEANUP_INTERVAL_PROPERTY = "cleanupInterval";
99+
private static final String MAX_CONNECTIONS_PROPERTY = "maxConnections";
100+
private static final String MAX_INACTIVITY_PROPERTY = "maxInactivity";
101+
private static final String MAX_LIFETIME_PROPERTY = "maxLifetime";
102+
private static final String MAX_USE_COUNT_PROPERTY = "maxUseCount";
103+
private static final String MAX_USE_TIME_PROPERTY = "maxUseTime";
104+
private static final String PRETEST_CONNECTIONS_PROPERTY = "pretestConnections";
105+
private static final String RUN_MAINTENANCE_PROPERTY = "runMaintenance";
106+
private static final String THREAD_USED_PROPERTY = "threadUsed";
90107

91108
/**
92109
Indicates that the CCSID used for new connections is the same as the system default CCSID.
@@ -109,13 +126,105 @@ public AS400ConnectionPool()
109126
initializeTransient();
110127
}
111128

129+
/**
130+
* Constructs an AS400ConnectionPool from the specified Reference object.
131+
*
132+
* @param reference to retrieve the ConnectionPool properties from
133+
*/
134+
AS400ConnectionPool(Reference reference) {
135+
super();
136+
initializeTransient();
137+
138+
Objects.requireNonNull(reference, "reference");
139+
Enumeration<RefAddr> list = reference.getAll();
140+
while (list.hasMoreElements()) {
141+
RefAddr refAddr = list.nextElement();
142+
String property = refAddr.getType();
143+
String value = (String) refAddr.getContent();
144+
switch (property) {
145+
case CCSID_PROPERTY:
146+
setCCSID(Integer.parseInt(value));
147+
break;
148+
case CLEANUP_INTERVAL_PROPERTY:
149+
setCleanupInterval(Long.parseLong(value));
150+
break;
151+
case MAX_CONNECTIONS_PROPERTY:
152+
setMaxConnections(Integer.parseInt(value));
153+
break;
154+
case MAX_INACTIVITY_PROPERTY:
155+
setMaxInactivity(Long.parseLong(value));
156+
break;
157+
case MAX_LIFETIME_PROPERTY:
158+
setMaxLifetime(Long.parseLong(value));
159+
break;
160+
case MAX_USE_COUNT_PROPERTY:
161+
setMaxUseCount(Integer.parseInt(value));
162+
break;
163+
case MAX_USE_TIME_PROPERTY:
164+
setMaxUseTime(Long.parseLong(value));
165+
break;
166+
case PRETEST_CONNECTIONS_PROPERTY:
167+
setPretestConnections(Boolean.parseBoolean(value));
168+
break;
169+
case RUN_MAINTENANCE_PROPERTY:
170+
setRunMaintenance(Boolean.parseBoolean(value));
171+
break;
172+
case THREAD_USED_PROPERTY:
173+
setThreadUsed(Boolean.parseBoolean(value));
174+
break;
175+
default:
176+
if (SocketProperties.isSocketProperty(property)) {
177+
socketProperties_.restore(property, value);
178+
}
179+
break;
180+
}
181+
}
182+
}
183+
184+
/**
185+
* Returns the Reference object for the pool object. This is used by
186+
* JNDI when bound in a JNDI naming service. Contains the information
187+
* necessary to reconstruct the pool object when it is later
188+
* retrieved from JNDI via an object factory.
189+
*
190+
* @return A Reference object of the pool object.
191+
* @exception NamingException If a naming error occurs in resolving the
192+
* object.
193+
*
194+
*/
195+
@Override
196+
public Reference getReference() throws NamingException {
197+
Trace.log(Trace.INFORMATION, "AS400ConnectionPool.getReference");
198+
199+
Reference ref = new Reference(this.getClass().getName(),
200+
AS400ObjectFactory.class.getName(),
201+
null);
202+
203+
ref.add(new StringRefAddr(CCSID_PROPERTY, Integer.toString(getCCSID())));
204+
ref.add(new StringRefAddr(CLEANUP_INTERVAL_PROPERTY, Long.toString(getCleanupInterval())));
205+
ref.add(new StringRefAddr(MAX_CONNECTIONS_PROPERTY, Integer.toString(getMaxConnections())));
206+
ref.add(new StringRefAddr(MAX_INACTIVITY_PROPERTY, Long.toString(getMaxInactivity())));
207+
ref.add(new StringRefAddr(MAX_LIFETIME_PROPERTY, Long.toString(getMaxLifetime())));
208+
ref.add(new StringRefAddr(MAX_USE_COUNT_PROPERTY, Integer.toString(getMaxUseCount())));
209+
ref.add(new StringRefAddr(MAX_USE_TIME_PROPERTY, Long.toString(getMaxUseTime())));
210+
ref.add(new StringRefAddr(PRETEST_CONNECTIONS_PROPERTY, Boolean.toString(isPretestConnections())));
211+
ref.add(new StringRefAddr(RUN_MAINTENANCE_PROPERTY, Boolean.toString(isRunMaintenance())));
212+
ref.add(new StringRefAddr(THREAD_USED_PROPERTY, Boolean.toString(isThreadUsed())));
213+
214+
// Add the Socket options
215+
socketProperties_.save(ref);
216+
217+
return ref;
218+
}
219+
112220
/**
113221
* Remove any connections that have exceeded maximum inactivity time, replace any
114222
* that have aged past maximum usage or maximum lifetime, and remove any that have
115223
* been in use too long.
116224
*
117225
* @see ConnectionPoolProperties
118226
**/
227+
@Override
119228
void cleanupConnections()
120229
{
121230
synchronized (as400ConnectionPool_)
@@ -148,6 +257,7 @@ void cleanupConnections()
148257
/**
149258
* Close and cleanup the connection pool.
150259
**/
260+
@Override
151261
public void close()
152262
{
153263
log(ResourceBundleLoader.getText("AS400CP_SHUTDOWN"));

src/main/java/com/ibm/as400/access/AS400JDBCDataSource.java

+6-37
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,6 @@ public class AS400JDBCDataSource
105105
private static final int MAX_THRESHOLD = 16777216; // Maximum threshold (bytes). @A3C, @A4A
106106
static final int MAX_SCALE = 63; // Maximum decimal scale
107107

108-
// socket options to store away in JNDI
109-
private static final String SOCKET_KEEP_ALIVE = "soKeepAlive"; // @F1A
110-
private static final String SOCKET_RECEIVE_BUFFER_SIZE = "soReceiveBufferSize"; // @F1A
111-
private static final String SOCKET_SEND_BUFFER_SIZE = "soSendBufferSize"; // @F1A
112-
private static final String SOCKET_LINGER = "soLinger"; // @F1A
113-
private static final String SOCKET_TIMEOUT = "soTimeout"; // @F1A
114-
private static final String SOCKET_LOGIN_TIMEOUT = "loginTimeout"; // @st3
115-
private static final String SOCKET_TCP_NO_DELAY = "soTCPNoDelay"; // @F1A
116-
117108
// Data source properties.
118109
transient private AS400 as400_; // AS400 object used to store and encrypt the password.
119110
// @J2d private String databaseName_ = ""; // Database name. @A6C
@@ -373,26 +364,8 @@ else if (property.equals(SAVE_PASSWORD)) {
373364
// set the savePasswordWhenSerialized_ flag
374365
savePasswordWhenSerialized_ = value.equals(TRUE_) ? true : false;
375366
}
376-
else if (property.equals(SOCKET_KEEP_ALIVE)) {
377-
sockProps_.setKeepAlive((value.equals(TRUE_)? true : false));
378-
}
379-
else if (property.equals(SOCKET_RECEIVE_BUFFER_SIZE)) {
380-
sockProps_.setReceiveBufferSize(Integer.parseInt(value));
381-
}
382-
else if (property.equals(SOCKET_SEND_BUFFER_SIZE)) {
383-
sockProps_.setSendBufferSize(Integer.parseInt(value));
384-
}
385-
else if (property.equals(SOCKET_LINGER)) {
386-
sockProps_.setSoLinger(Integer.parseInt(value));
387-
}
388-
else if (property.equals(SOCKET_TIMEOUT)) {
389-
sockProps_.setSoTimeout(Integer.parseInt(value));
390-
}
391-
else if (property.equals(SOCKET_LOGIN_TIMEOUT)) { //@st3
392-
sockProps_.setLoginTimeout(Integer.parseInt(value)); //@st3
393-
}
394-
else if (property.equals(SOCKET_TCP_NO_DELAY)) {
395-
sockProps_.setTcpNoDelay((value.equals(TRUE_)? true : false));
367+
else if (SocketProperties.isSocketProperty(property)) {
368+
sockProps_.restore(property, value);
396369
}
397370
else
398371
{
@@ -431,11 +404,12 @@ public void addPropertyChangeListener(PropertyChangeListener listener)
431404
* Method to create a clone of AS400JDBCDataSource. This does a shallow
432405
* copy, with the exception of JDProperties, which also gets cloned.
433406
*/
407+
@Override
434408
public Object clone()
435409
{
436410
try
437411
{
438-
Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.close()");
412+
Trace.log(Trace.INFORMATION, "AS400JDBCDataSource.clone()");
439413
AS400JDBCDataSource clone = (AS400JDBCDataSource) super.clone();
440414
clone.properties_ = (JDProperties) this.properties_.clone();
441415
return clone;
@@ -1178,6 +1152,7 @@ public String getProxyServer()
11781152
* @return A Reference object of the data source object.
11791153
* @exception NamingException If a naming error occurs in resolving the object.
11801154
**/
1155+
@Override
11811156
public Reference getReference() throws NamingException
11821157
{
11831158

@@ -1196,13 +1171,7 @@ public Reference getReference() throws NamingException
11961171
}
11971172

11981173
// Add the Socket options
1199-
if (sockProps_.keepAliveSet_) ref.add(new StringRefAddr(SOCKET_KEEP_ALIVE, (sockProps_.keepAlive_ ? "true" : "false")));
1200-
if (sockProps_.receiveBufferSizeSet_) ref.add(new StringRefAddr(SOCKET_RECEIVE_BUFFER_SIZE, Integer.toString(sockProps_.receiveBufferSize_)));
1201-
if (sockProps_.sendBufferSizeSet_) ref.add(new StringRefAddr(SOCKET_SEND_BUFFER_SIZE, Integer.toString(sockProps_.sendBufferSize_)));
1202-
if (sockProps_.soLingerSet_) ref.add(new StringRefAddr(SOCKET_LINGER, Integer.toString(sockProps_.soLinger_)));
1203-
if (sockProps_.soTimeoutSet_) ref.add(new StringRefAddr(SOCKET_TIMEOUT, Integer.toString(sockProps_.soTimeout_)));
1204-
if (sockProps_.loginTimeoutSet_) ref.add(new StringRefAddr(SOCKET_LOGIN_TIMEOUT, Integer.toString(sockProps_.loginTimeout_))); //@st3
1205-
if (sockProps_.tcpNoDelaySet_) ref.add(new StringRefAddr(SOCKET_TCP_NO_DELAY, (sockProps_.tcpNoDelay_ ? "true" : "false")));
1174+
sockProps_.save(ref);
12061175

12071176
// Add the data source properties. (unique constant identifiers for storing in JNDI).
12081177
if (getDatabaseName() != null)

src/main/java/com/ibm/as400/access/AS400JDBCManagedDataSource.java

+3-35
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,6 @@ public class AS400JDBCManagedDataSource extends ToolboxWrapper
116116
private static final String TOOLBOX_DRIVER = "jdbc:as400:";
117117
private static final int MAX_THRESHOLD = 16777216; // Maximum threshold (bytes).
118118

119-
// socket options to store away in JNDI
120-
private static final String SOCKET_KEEP_ALIVE = "soKeepAlive";
121-
// JDProperties: "keep alive"
122-
private static final String SOCKET_RECEIVE_BUFFER_SIZE = "soReceiveBufferSize";
123-
// JDProperties: "receive buffer size"
124-
private static final String SOCKET_SEND_BUFFER_SIZE = "soSendBufferSize";
125-
// JDProperties: "send buffer size"
126-
private static final String SOCKET_LINGER = "soLinger";
127-
private static final String SOCKET_TIMEOUT = "soTimeout";
128-
private static final String SOCKET_TCP_NO_DELAY = "soTCPNoDelay";
129-
130119
// Standard data source properties. (See JDBC Tutorial p. 567, table 16.1)
131120

132121
transient private AS400 as400_; // Object used to store and encrypt the password.
@@ -365,18 +354,8 @@ else if (property.equals(USER)) {
365354
|| property.equals(KEY_RING_PASSWORD)) {
366355
// Do nothing for these keys. They've already been handled prior to loop,
367356
// and we don't want them added to JDProperties.
368-
} else if (property.equals(SOCKET_KEEP_ALIVE)) {
369-
sockProps_.setKeepAlive((value.equals(TRUE_) ? true : false));
370-
} else if (property.equals(SOCKET_RECEIVE_BUFFER_SIZE)) {
371-
sockProps_.setReceiveBufferSize(Integer.parseInt(value));
372-
} else if (property.equals(SOCKET_SEND_BUFFER_SIZE)) {
373-
sockProps_.setSendBufferSize(Integer.parseInt(value));
374-
} else if (property.equals(SOCKET_LINGER)) {
375-
sockProps_.setSoLinger(Integer.parseInt(value));
376-
} else if (property.equals(SOCKET_TIMEOUT)) {
377-
sockProps_.setSoTimeout(Integer.parseInt(value));
378-
} else if (property.equals(SOCKET_TCP_NO_DELAY)) {
379-
sockProps_.setTcpNoDelay((value.equals(TRUE_) ? true : false));
357+
} else if (SocketProperties.isSocketProperty(property)) {
358+
sockProps_.restore(property, value);
380359
} else if (isConnectionPoolDataSource
381360
&& AS400JDBCManagedConnectionPoolDataSource.isConnectionPoolProperty(property)) {
382361
// Ignore this property, the subclass will consume it.
@@ -1494,18 +1473,7 @@ public Reference getReference() throws NamingException {
14941473
}
14951474

14961475
// Add the Socket options
1497-
if (sockProps_.keepAliveSet_)
1498-
ref.add(new StringRefAddr(SOCKET_KEEP_ALIVE, (sockProps_.keepAlive_ ? "true" : "false")));
1499-
if (sockProps_.receiveBufferSizeSet_)
1500-
ref.add(new StringRefAddr(SOCKET_RECEIVE_BUFFER_SIZE, Integer.toString(sockProps_.receiveBufferSize_)));
1501-
if (sockProps_.sendBufferSizeSet_)
1502-
ref.add(new StringRefAddr(SOCKET_SEND_BUFFER_SIZE, Integer.toString(sockProps_.sendBufferSize_)));
1503-
if (sockProps_.soLingerSet_)
1504-
ref.add(new StringRefAddr(SOCKET_LINGER, Integer.toString(sockProps_.soLinger_)));
1505-
if (sockProps_.soTimeoutSet_)
1506-
ref.add(new StringRefAddr(SOCKET_TIMEOUT, Integer.toString(sockProps_.soTimeout_)));
1507-
if (sockProps_.tcpNoDelaySet_)
1508-
ref.add(new StringRefAddr(SOCKET_TCP_NO_DELAY, (sockProps_.tcpNoDelay_ ? "true" : "false")));
1476+
sockProps_.save(ref);
15091477

15101478
// Add the data source properties. (unique constant identifiers for storing in
15111479
// JNDI).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
//
3+
// JTOpen (IBM Toolbox for Java - OSS version)
4+
//
5+
// Filename: AS400ObjectFactory.java
6+
//
7+
// The source code contained herein is licensed under the IBM Public License
8+
// Version 1.0, which has been approved by the Open Source Initiative.
9+
// Copyright (C) 1997-2001 International Business Machines Corporation and
10+
// others. All rights reserved.
11+
//
12+
///////////////////////////////////////////////////////////////////////////////
13+
package com.ibm.as400.access;
14+
15+
import java.util.Hashtable;
16+
import javax.naming.Context; // JNDI
17+
import javax.naming.Name; // JNDI
18+
import javax.naming.Reference; // JNDI
19+
import javax.naming.spi.ObjectFactory; // JNDI
20+
21+
/**
22+
* The AS400ObjectFactory is used by a JNDI service provider to reconstruct an
23+
* object when it is retrieved from JNDI.
24+
*
25+
* <p>
26+
* For Example:
27+
* <pre>
28+
* AS400ConnectionPool pool = null;
29+
* String objFactoryName = "com.ibm.as400.access.AS400ObjectFactory";
30+
* String className = "com.ibm.as400.access.AS400ConnectionPool";
31+
* Reference ref = new Reference(className, objFactoryName, "");
32+
* ref.add(new StringRefAddr("maxConnections", "10"));
33+
* try {
34+
* ObjectFactory objectFactory = (ObjectFactory) Class.forName(objFactoryName).newInstance();
35+
* pool = (AS400ConnectionPool) objectFactory.getObjectInstance(ref, null, null, null);
36+
* AS400 as400 = pool.getConnection("myAS400", "myUserID", "myPassword".toCharArray());
37+
* } catch (Exception ex) {
38+
* ex.printStackTrace();
39+
* System.err.println("Exception caught: " + ex);
40+
* }
41+
* </pre>
42+
* The following classes implement the javax.naming.Referenceable interface.
43+
*
44+
* @see com.ibm.as400.access.AS400ConnectionPool
45+
*
46+
*/
47+
@SuppressWarnings("UseOfObsoleteCollectionType")
48+
public class AS400ObjectFactory implements ObjectFactory {
49+
50+
static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others.";
51+
52+
/**
53+
* Returns the object requested.
54+
*
55+
* @param referenceObject The object reference.
56+
* @param name The object name.
57+
* @param nameContext The context of the name.
58+
* @param environment The environment.
59+
* @return The object requested.
60+
* @exception Exception If an error occurs during object creation.
61+
*
62+
*/
63+
@Override
64+
public Object getObjectInstance(Object referenceObject,
65+
Name name,
66+
Context nameContext,
67+
Hashtable<?, ?> environment) throws Exception {
68+
Reference reference = (Reference) referenceObject;
69+
70+
if (reference.getClassName().equals(AS400ConnectionPool.class.getName())) {
71+
return new AS400ConnectionPool(reference);
72+
} else {
73+
if (JDTrace.isTraceOn()) {
74+
JDTrace.logInformation(this, "Lookup error. Class not found: " + reference.getClassName());
75+
}
76+
return null;
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)