All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.spardat.xma.baserpc.BaseRPCClient Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

// @(#) $Id: BaseRPCClient.java 2089 2007-11-28 13:56:13Z s3460 $
package at.spardat.xma.baserpc;

import java.util.Collection;
import java.util.StringTokenizer;

import at.spardat.enterprise.exc.SysException;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.transport.ConnectException;
import at.spardat.xma.boot.transport.Transport;
import at.spardat.xma.boot.transport.XMA_URI;
import at.spardat.xma.exception.Codes;
import at.spardat.xma.serializer.Deserializer;
import at.spardat.xma.serializer.Serializer;
import at.spardat.xma.serializer.SerializerFactory;
import at.spardat.xma.session.XMASessionClient;
import at.spardat.xma.util.ByteArray;

/**
 * Client side class to make a base RPC. Usage:
 * 
 *     BaseRPCClient        rpc = new BaseRPCClient ("myRPC");
 *     // set parameters
 *     rpc.setParameter (1, "toServer");
 *     // execute
 *     rpc.execute();
 *     // read output parameters
 *     ... getParameter (1, "fromServer");
 * 
* * This class is for framework-internal use only. */ public class BaseRPCClient { /** * Name of the RPC */ private String fName; /** * The resource at the server (a servlet) that is responsible for handling the RPC * at the server. */ private String fServerRessource; /** * The session */ private XMASessionClient fSession; /** * Models the data sent to the server */ private ClientToServerData fCallData = new ClientToServerData(); /** * Models the data sent from the server */ private ServerToClientData fReplyData; /** * communicate encrypted (use SSL) */ private boolean fNeedEncryption = false; /** * Constructor. * * @param name the name of the base rpc. Used at the server side to discriminate * among different calls. * @param serverRessource the name of the servlet-ressource that is responsible * for handling the request at the server. * @param session the client's session. */ public BaseRPCClient (String name, String serverRessource, XMASessionClient session) { if (name == null) throw new IllegalArgumentException(); fName = name; fCallData.setName (name); fSession = session; fServerRessource = serverRessource; } /** * Sets a parameter transferred that is to be transferred to the server. * * @param id a numeric id of the parameter. Must not be less than zero and greater than 127. * @param value serializable object. Must not be null. */ public void setParameter (int id, Object value) { fCallData.setParameter (id, value); } /** * Returns a parameter set at the server side. * * @param id numeric id of the parameter * @return object or null if there is no such parameter. */ public Object getParameter (int id) { return fReplyData.getParameter(id); } /** * Sets a parameter that should be transferred to the server which is * a collection that should not be serialized directly. * * @param id a numeric id of the parameter. Must not be less than zero and greater than 127. * @param value collection of objects that must be serializable themselves. */ public void setUnserializableCollection (int id, Collection value) { fCallData.setUnserializableCollection(id, value); } /** * Returns a Collection from the server. Please not that the concrete subtype of * Collection may be different from that provided via setUnserializableCollection * at the server side. * * @param id numeric id of the parameter. * @return collection of objects. You cannot make any assumptions on the concrete type * of the returned value. */ public Collection getUnserializableCollection (int id) { return fReplyData.getUnserializableCollection(id); } /** * Executes this RPC. */ public void execute () { /** * serialize parameters */ SerializerFactory fac = new BaseRpcSerFactory (false); boolean isBinaryMode = fac.isModeBinary(null); Serializer ser = fac.createSerializer(null, 1024); ByteArray serResult = null; ser.addHeader(); try { fCallData.externalize (ser); serResult = ser.getResult(); } catch (Exception ex) { throw new SysException (ex, "Cannot externalize parameters at client").setCode (Codes.BASERPC_CLIENT_EXTERNALIZE); } /** * compress */ if (isBinaryMode && doCompress (serResult.size())) { serResult = serResult.getCompressed(); } if (!isBinaryMode) serResult.setComputeHeaderLength (false); /** * Do the RPC using a Transport object */ Transport transport = Transport.getTransport(); XMA_URI uri = fSession.getUri(); uri.setResource(fServerRessource); byte [] transportOutputBytes = null; if(fNeedEncryption&&!"https".equals(uri.getProtocol_())) { uri.setProtocol("https"); String ports = fSession.getRuntimeProperty("SSLPort","443"); for(StringTokenizer tok=new StringTokenizer(ports,",;|");tok.hasMoreTokens();) { String port = tok.nextToken().trim(); uri.setPort(new Integer(port).intValue()); try { transportOutputBytes = transport.callServerEvent (fSession, uri, serResult.getBytes()); break; } catch (ConnectException ex) { if(tok.hasMoreTokens()) { // exception allready logged by Transport fSession.getLogger().log(LogLevel.INFO,"Server not reachable at port "+port+" trying next secure port"); } else { throw new SysException (ex, "Server returned error or is not reachable.").setCode(Codes.BASEPRC_CLIENT_TRANSPORT_ERROR); } } catch (Exception ex) { throw new SysException (ex, "Server returned error or is not reachable.").setCode(Codes.BASEPRC_CLIENT_TRANSPORT_ERROR); } } } else { try { transportOutputBytes = transport.callServerEvent (fSession, uri, serResult.getBytes()); } catch (Exception ex) { throw new SysException (ex, "Server returned error or is not reachable.").setCode(Codes.BASEPRC_CLIENT_TRANSPORT_ERROR); } } /** * First 4 bytes in transportOutputBytes is the length. This must match with * the length of the array. */ if (transportOutputBytes == null || transportOutputBytes.length < 4) { throw new SysException ("server returned less than 4 bytes").setCode(Codes.BASERPC_CLIENT_READ_LENGTH); } ByteArray transportOutputByteArray = new ByteArray (transportOutputBytes); transportOutputByteArray.setHeader(true); int expectedLength = transportOutputByteArray.getLengthInHeader(); if (expectedLength != -1 && expectedLength != transportOutputBytes.length) { throw new SysException ("expected result of "+expectedLength+", but got "+transportOutputBytes.length) .setCode(Codes.BASERPC_CLIENT_LENGTH_MISMATCH); } /** * uncompress if compressed */ if (transportOutputByteArray.isCompressed()) { transportOutputByteArray = transportOutputByteArray.getUncompressed(); } /** * Deserialize RemoteReplyData from byte array */ try { Deserializer deser = fac.createDeserializer(null, transportOutputByteArray.getBuffer(), ByteArray.HEADER_LEN, transportOutputByteArray.size()-ByteArray.HEADER_LEN); fReplyData = new ServerToClientData (); fReplyData.internalize (deser); } catch (Exception ex) { throw new SysException (ex, "cannot deserialize reply from server").setCode (Codes.BASERPC_INTERNALIZE_RESPONSE); } /** * if the reply contained an Exception from the server, throw it */ if (fReplyData.getException() != null) throw fReplyData.getException(); } /** * Determines if data sent to the server of length should be compressed. */ private boolean doCompress (int length) { String comprThrAsString = fSession.getRuntimeProperty("RpcCompressionThreshold"); if (comprThrAsString == null) return false; int compressionThreshold = Integer.parseInt (comprThrAsString); if (compressionThreshold == -1) return false; else return length > compressionThreshold; } /** * Determines if data has to be send encrypted. * @param needEncryption if true https will be used for transport. * @author s2877 */ public void setNeedEncryption(boolean needEncryption) { fNeedEncryption = needEncryption; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy