package gov.va.med.edp.rpc; import gov.va.med.edp.vo.BigBoardDebugInfoVO; import gov.va.med.exception.FoundationsException; import gov.va.med.vistalink.adapter.cci.VistaLinkAppProxyConnectionSpec; import gov.va.med.vistalink.adapter.cci.VistaLinkConnection; import gov.va.med.vistalink.adapter.cci.VistaLinkConnectionSpec; import gov.va.med.vistalink.adapter.cci.VistaLinkDuzConnectionSpec; import gov.va.med.vistalink.adapter.record.LoginsDisabledFaultException; import gov.va.med.vistalink.adapter.record.VistaLinkFaultException; import gov.va.med.vistalink.adapter.spi.VistaLinkServerInfo; import gov.va.med.vistalink.rpc.*; import gov.va.med.vistalink.security.m.SecurityFaultException; import gov.va.med.vistalink.security.m.SecurityDivisionDeterminationFaultException; import org.apache.log4j.Logger; import org.springframework.dao.*; import org.springframework.jca.cci.core.CciTemplate; import org.springframework.jca.cci.core.ConnectionCallback; import org.springframework.util.Assert; import javax.resource.ResourceException; import javax.resource.cci.Connection; import javax.resource.cci.ConnectionFactory; import java.sql.SQLException; import java.text.MessageFormat; import java.util.List; /** * This is the central class in the rpc package. It simplifies the use of VistaLink RPCs and helps to avoid common errors. * It executes core RPC workflow, leaving application code to provide RPC names and parameters and extract results. This * class executes RPCs with VistaLink, initiating iteration over RPC results and catching VistaLink exceptions and * translating them to the generic data access exception hierarchy defined in the org.springframework.dao package. */ public class VistaLinkRpcTemplate { private static final int USER_TYPE_DUZ = 1; private static final int USER_TYPE_APPLICATION_PROXY = 2; static final int DEFAULT_TIMEOUT = 10000; private static Logger log = Logger.getLogger(VistaLinkRpcTemplate.class); private int timeOut = DEFAULT_TIMEOUT; private String rpcContext; private ConnectionFactoryLocator connectionFactoryLocator; private static final String UNABLE_TO_EXECUTE_RPC = "Unable to execute RPC"; public VistaLinkRpcTemplate(ConnectionFactoryLocator connectionFactoryLocator) { this.connectionFactoryLocator = connectionFactoryLocator; } public String rpcAsUser(final String division, final String duz, final String rpcContext, final String rpcName) throws DataAccessException { return rpcAsUser(division, duz, rpcContext, rpcName, null); } public String rpcAsUser(final String division, final String duz, final String rpcContext, final String rpcName, final List params) throws DataAccessException { return rpc(division, duz, rpcContext, rpcName, params, USER_TYPE_DUZ); } public String rpcAsApplication(final String division, final String applicationProxyName, final String rpcContext, final String rpcName) throws DataAccessException { return rpcAsApplication(division, applicationProxyName, rpcContext, rpcName, null); } public String rpcAsApplication(final String division, final String applicationProxyName, final String rpcContext, final String rpcName, final List params) throws DataAccessException { return rpc(division, applicationProxyName, rpcContext, rpcName, params, USER_TYPE_APPLICATION_PROXY); } public BigBoardDebugInfoVO getVistaLinkConnectionInfo(final String division, final String user) throws DataAccessException { return getConnectionInfo(division, user, USER_TYPE_APPLICATION_PROXY); } public String rpc(final String division, final String user, final String rpcContext, final String rpcName, final List params, final int userType) throws DataAccessException { if (log.isDebugEnabled()) log.debug(MessageFormat.format("''{0}'' called in context ''{1}'' by ''{2}'' at facility ''{3}'' with params: {4}", new Object[]{rpcName, rpcContext, user, division, params})); ConnectionFactory connectionFactory = connectionFactoryLocator.getConnectionFactory(division); try { CciTemplate t = new CciTemplate(connectionFactory, createConnectionSpec(division, user, userType)); RpcResponse response = (RpcResponse) t.execute(new ConnectionCallback() { public Object doInConnection(Connection connection, ConnectionFactory connectionFactory) throws ResourceException, SQLException, DataAccessException { try { Assert.isInstanceOf(VistaLinkConnection.class, connection); VistaLinkConnection conn = (VistaLinkConnection) connection; conn.setTimeOut(getTimeOut()); RpcRequest request = RpcRequestFactory.getRpcRequest(rpcContext, rpcName); request.setUseProprietaryMessageFormat(true); request.setXmlResponse(false); if (params != null) { request.setParams(params); } return conn.executeRPC(request); } catch (IllegalArgumentException e) { throw new InvalidDataAccessApiUsageException(UNABLE_TO_EXECUTE_RPC, e); } catch (NoRpcContextFaultException e) { throw new VistaLinkRpcInvalidApiUsageException(e); } catch (RpcNotOkForProxyUseException e) { throw new VistaLinkRpcInvalidApiUsageException(e); } catch (RpcNotInContextFaultException e) { throw new VistaLinkRpcPermissionDeniedException(e); } catch (LoginsDisabledFaultException e) { throw new DataAccessResourceFailureException(UNABLE_TO_EXECUTE_RPC, e); } catch (SecurityDivisionDeterminationFaultException e) { throw new VistaLinkRpcInvalidApiUsageException(e); } catch (SecurityFaultException e) { throw new VistaLinkRpcPermissionDeniedException(e); } catch (VistaLinkFaultException e) { throw new DataRetrievalFailureException(UNABLE_TO_EXECUTE_RPC, e); } catch (FoundationsException e) { throw new DataRetrievalFailureException(UNABLE_TO_EXECUTE_RPC, e); } } }); String result = response.getResults(); if (log.isDebugEnabled()) { log.debug(MessageFormat.format("''{0}'' returned: {1}", new Object[]{rpcName, result})); } return result; } catch (IllegalArgumentException e) { throw new InvalidDataAccessApiUsageException(UNABLE_TO_EXECUTE_RPC, e); } } private BigBoardDebugInfoVO getConnectionInfo(final String division, final String user, final int userType) throws DataAccessException { VistaLinkConnection conn = null; ConnectionFactory connectionFactory = connectionFactoryLocator.getConnectionFactory(division); try { conn = (VistaLinkConnection)connectionFactory.getConnection(createConnectionSpec(division, user, userType)); } catch (ResourceException e) { throw new DataAccessResourceFailureException("error getting connection info", e); } VistaLinkServerInfo vistaLinkServerInfo = conn.getConnectionInfo(); BigBoardDebugInfoVO bbd = new BigBoardDebugInfoVO(vistaLinkServerInfo.getAddress().toString(), new Integer(vistaLinkServerInfo.getPort()).toString()); return bbd; } private VistaLinkConnectionSpec createConnectionSpec(String division, String user, int userType) { switch (userType) { case USER_TYPE_APPLICATION_PROXY: return new VistaLinkAppProxyConnectionSpec(division, user); case USER_TYPE_DUZ: default: return new VistaLinkDuzConnectionSpec(division, user); } } public int getTimeOut() { return timeOut; } public void setTimeOut(int timeOut) { this.timeOut = timeOut; } public String getRpcContext() { return rpcContext; } public void setRpcContext(String rpcContext) { this.rpcContext = rpcContext; } public ConnectionFactoryLocator getConnectionFactoryLocator() { return connectionFactoryLocator; } }