src.com.ibm.as400.security.auth.RefreshAgent Maven / Gradle / Ivy
Show all versions of jt400-jdk8 Show documentation
package com.ibm.as400.security.auth;
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: RefreshAgent.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2003 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.ConnectionEvent;
import com.ibm.as400.access.ConnectionListener;
import com.ibm.as400.access.ExtendedIllegalStateException;
import com.ibm.as400.access.Trace;
/**
* The RefreshAgent class implements the automatic refresh
* mechanism for credentials.
*
* Note: The implementation is potentially generic enough
* to work with any object implementing a refreshable
* interface, but is currently limited to credentials.
*
*/
class RefreshAgent extends Thread implements ConnectionListener {
private int refreshInterval_, maxRefreshes_ = 0;
private AS400Credential target_ = null;
private Exception failure_ = null;
private boolean stop_ = false;
/**
* Constructs a RefreshAgent object.
*
*
Agent thread will be identified as a daemon as
* to not prevent the JVM from exiting once user
* threads are complete.
*
*
Thread will be assigned the maximum permitted
* priority within its thread group.
*
*/
RefreshAgent() {
super();
setDaemon(true);
setPriority(Thread.MAX_PRIORITY);
}
/**
* Constructs a RefreshAgent object.
*
* @param target
* The object to refresh automatically.
*
* @param refreshInterval
* The number of seconds between refresh attempts.
* The first refresh will occur immediately;
* the second will occur this many seconds after
* the first, and so on.
*
* @param maxRefreshes
* The maximum number of times to refresh the
* credential. A value of negative one (-1)
* indicates no maximum.
*
*/
RefreshAgent(AS400Credential target, int refreshInterval, int maxRefreshes) {
this();
setTarget(target);
setRefreshInterval(refreshInterval);
setMaxRefreshes(maxRefreshes);
//@D3A - Start Set readable name for refreshing thread.
String className = target.getClass().getName();
int dotIndex = className.lastIndexOf('.');
if (dotIndex >= 0) {
className = className.substring(dotIndex+1);
}
try {
this.setName("Refresh"+className);
} catch (Exception e) {
// Ignore any exception when setting name
}
//@D3A - End
}
/**
* Invoked when a service has been connected
* on an AS400 object.
*
* @param event The connection event.
*
*/
public void connected(ConnectionEvent event) {
// Do nothing; not interested in this event.
}
/**
* Invoked when a service has been disconnected
* on an AS400 object.
*
*
If all services are disconnected, the thread
* is stopped.
*
* @param event The connection event.
*
*/
public void disconnected(ConnectionEvent event) {
try {
AS400 sys = (AS400)event.getSource();
if (isAlive() && !sys.isConnected()) {
stopRefresh();
if (Trace.isTraceOn())
Trace.log(Trace.INFORMATION,
new StringBuffer("RefreshAgent stopped after system disconnect >> "
).append(target_.toString()).toString());
}
}
catch (Exception e) {
Trace.log(Trace.ERROR,
"RefreshAgent not stopped after system disconnect >> "
+ target_.toString(), e);
}
}
/**
* Called when garbage collection determines that there are
* no more references to the object.
*
*/
protected void finalize() throws Throwable {
try {
if (isAlive()) {
stopRefresh();
}
}
catch (Exception e) {
Trace.log(Trace.ERROR,
"RefreshAgent not stopped on finalize >> " + target_.toString(), e);
}
super.finalize();
}
/**
* Returns the exception resulting from failure of
* the most recent refresh attempt.
*
* @return
* The exception; null if not available.
*
*/
public Throwable getFailure() {
return failure_;
}
/**
* Runs the agent.
*
*
Starts automatic refresh. The first refresh
* attempt is performed immediately, followed by
* periodic refresh as appropriate.
*
*
Automatic attempts are discontinued on the
* first failed refresh attempt.
*
*/
public void run() {
stop_ = false;
if (Trace.isTraceOn())
Trace.log(Trace.INFORMATION,
new StringBuffer("RefreshAgent starting with maximum attempts "
).append(maxRefreshes_
).append(" and refresh interval "
).append(refreshInterval_
).append(" >> "
).append(target_.toString()
).toString());
validatePropertySet("target", target_);
AS400 sys = target_.getSystem();
sys.addConnectionListener(this);
failure_ = null;
int i = 0;
while (!stop_ && failure_ == null && (maxRefreshes_ < 0 || i++ < maxRefreshes_)) {
try {
target_.refresh();
if (maxRefreshes_ < 0 || i < maxRefreshes_)
sleep(refreshInterval_ * 1000);
}
catch(InterruptedException ie) {
if (stop_)
Trace.log(Trace.DIAGNOSTIC, "RefreshAgent stopped on interrupt >> " + target_.toString());
else {
Trace.log(Trace.ERROR, "RefreshAgent interrupted >> " + target_.toString(), ie);
failure_ = ie;
}
}
catch(Exception e) {
Trace.log(Trace.ERROR, "RefreshAgent failed >> " + target_.toString(), e);
failure_ = e;
}
}
sys.removeConnectionListener(this);
}
/**
* Sets the number of times to perform refresh.
*
*
This property cannot be changed when active.
*
* @param max
* The maximum number of times to refresh the
* credential. A value of negative one (-1)
* indicates no maximum.
*
* @exception ExtendedIllegalStateException
* If the property cannot be changed due
* to the current state.
*
*/
void setMaxRefreshes(int max) {
validatePropertyChange("maxRefreshes");
maxRefreshes_ = max;
}
/**
* Sets the number of seconds to pause between attempts.
*
*
This property cannot be changed when active.
*
* @param seconds
* The number of seconds between refresh attempts.
* The first refresh will occur immediately;
* the second will occur this many seconds after
* the first, and so on.
*
* @exception ExtendedIllegalStateException
* If the property cannot be changed due
* to the current state.
*
*/
void setRefreshInterval(int seconds) {
validatePropertyChange("refreshInterval");
refreshInterval_ = seconds;
}
/**
* Sets the target for automatic refresh actions.
*
*
This property cannot be changed when active.
*
* @param impl
* The target object.
*
* @exception ExtendedIllegalStateException
* If the property cannot be changed due
* to the current state.
*
*/
void setTarget(AS400Credential c) {
validatePropertyChange("target");
target_ = c;
}
/**
* Instructs the thread to stop any automatic refresh in progress.
*
*
Does nothing if not running.
*
*/
public void stopRefresh() {
stop_ = true;
if (isAlive())
interrupt();
}
/**
* Validates that the given property can be changed.
*
*
Properties cannot be changed while active.
*
* @param propertyName
* The property to be validated.
*
* @exception ExtendedIllegalStateException
* If the agent is in an active state, indicating
* that attributes cannot be modified.
*
*/
void validatePropertyChange(String propertyName) {
if (isAlive()) {
Trace.log(Trace.ERROR, "Property " + propertyName + " not changed (active=true).");
throw new ExtendedIllegalStateException(propertyName,
ExtendedIllegalStateException.PROPERTY_NOT_CHANGED);
}
}
/**
* Validates that the given property has been set.
*
*
Performs a simple null check, used to
* centralize exception handling.
*
* @param propertyName
* The property to validate.
*
* @param value
* The property value.
*
* @exception ExtendedIllegalStateException
* If the property is not set.
*
*/
void validatePropertySet(String propertyName, Object value) {
if (value == null) {
Trace.log(Trace.ERROR, "Required property " + propertyName + " not set.");
throw new ExtendedIllegalStateException(
ExtendedIllegalStateException.PROPERTY_NOT_SET);
}
}
}