/*
* Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.dal.proxy;
import org.apache.log4j.Logger;
import org.csstudio.dal.context.ConnectionState;
import org.csstudio.dal.context.Identifier;
import org.csstudio.dal.context.IdentifierUtilities;
import com.cosylab.util.ListenerList;
/**
* Simulation implementation of Proxy interface.
*
* @author Igor Kriznar (igor.kriznarATcosylab.com)
*/
public abstract class AbstractProxyImpl<P extends AbstractPlug> implements Proxy<P>{
protected boolean debug = false;
protected String name;
protected ListenerList proxyListeners;
protected ConnectionStateMachine connectionStateMachine = new ConnectionStateMachine();
protected Identifier identifier;
protected P plug;
private String connectionInfo;
/* (non-Javadoc)
* @see org.csstudio.dal.context.Identifiable#getIdentifier()
*/
@Override
public Identifier getIdentifier(){
if (identifier == null)
identifier = IdentifierUtilities.createIdentifier(this);
return identifier;
}
/* (non-Javadoc)
* @see org.csstudio.dal.context.Identifiable#isDebug()
*/
@Override
public boolean isDebug(){
return debug;
}
/**
* Default construcor.
*/
public AbstractProxyImpl(String name, P plug){
super();
this.name = name;
this.plug = plug;
}
@Override
public P getPlug() {
return plug;
}
/* (non-Javadoc)
* @see org.csstudio.dal.proxy.Proxy#getUniqueName()
*/
@Override
public String getUniqueName(){
return name;
}
/* (non-Javadoc)
* @see org.csstudio.dal.proxy.Proxy#destroy()
*/
@Override
public void destroy(){
}
/* (non-Javadoc)
* @see org.csstudio.dal.proxy.Proxy#addProxyListener(org.csstudio.dal.proxy.ProxyListener)
*/
@Override
public void addProxyListener(ProxyListener<?> l){
if (proxyListeners == null)
proxyListeners = new ListenerList(ProxyListener.class);
proxyListeners.add(l);
ProxyEvent<Proxy<?>> e = new ProxyEvent<Proxy<?>>(this, null, connectionStateMachine.getConnectionState(), null);
try {
l.connectionStateChange(e);
} catch (Exception ex) {
Logger.getLogger(this.getClass()).error("Failed to forward listener.", ex);
}
}
/* (non-Javadoc)
* @see org.csstudio.dal.proxy.Proxy#removeProxyListener(org.csstudio.dal.proxy.ProxyListener)
*/
@Override
public void removeProxyListener(ProxyListener<?> l){
if (proxyListeners != null)
proxyListeners.remove(l);
}
/* (non-Javadoc)
* @see org.csstudio.dal.proxy.Proxy#getConnectionState()
*/
@Override
public ConnectionState getConnectionState(){
return connectionStateMachine.getConnectionState();
}
/**
* Intended for only within plug.
*
* @param s new connection state.
*/
public void setConnectionState(final ConnectionState s, final Throwable error){
if (connectionStateMachine.requestNextConnectionState(s)) {
if (connectionStateMachine.getConnectionState()==ConnectionState.CONNECTED) {
connectionInfo=null;
getConnectionInfo();
}
handleConnectionState(s);
fireConnectionState(s,error);
}
}
/**
* Intended for only within plug.
*
* @param s new connection state.
*/
public void setConnectionState(ConnectionState s){
setConnectionState(s, null);
}
/**
* This method is called after connection state was changed but change was not jet
* fired to listeners.
* Plug implementation may want to override this method to provide internal
* synchronization of proxy with new state.
* @param s the new connection state
*/
protected void handleConnectionState(ConnectionState s) {
}
/**
* Fires new connection event.
*/
protected void fireConnectionState(ConnectionState c, Throwable error){
if (proxyListeners == null)
return;
ProxyListener<?>[] l = (ProxyListener<?>[])proxyListeners.toArray();
ProxyEvent<Proxy<?>> e = new ProxyEvent<Proxy<?>>(this, null, c, error);
for (int i = 0; i < l.length; i++) {
try {
l[i].connectionStateChange(e);
} catch (Exception ex) {
Logger.getLogger(this.getClass()).error("Exception in event handler, continuing.", ex);
}
}
}
@Override
public String getConnectionInfo() {
if (connectionInfo == null) {
if (connectionStateMachine.isConnected()) {
StringBuilder sb= new StringBuilder(128);
sb.append(name);
sb.append('@');
if (plug!=null)
sb.append(plug.getPlugType());
else
sb.append("UKNOWN_PLUG");
sb.append('/');
sb.append(getRemoteHostInfo());
connectionInfo= sb.toString();
}
else {
StringBuilder sb= new StringBuilder(128);
sb.append(name);
sb.append('@');
if (plug!=null)
sb.append(plug.getPlugType());
else
sb.append("UKNOWN_PLUG");
sb.append('/');
sb.append("(NOT_CONNECTED)");
connectionInfo= sb.toString();
}
}
return connectionInfo;
}
/**
* Plug implementation should override this to provide remote host information.
* Something like: HOST_NAME:PORT or HOST_IP:PORT.
* @return remote host information
*/
protected String getRemoteHostInfo() {
return "UKNOWN_HOST";
}
}