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

com.scudata.server.odbc.OdbcWorker Maven / Gradle / Ivy

Go to download

SPL(Structured Process Language) A programming language specially for structured data computing.

There is a newer version: 20241126
Show newest version
package com.scudata.server.odbc;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import com.esproc.jdbc.JDBCUtil;
import com.scudata.cellset.datamodel.PgmCellSet;
import com.scudata.common.Logger;
import com.scudata.common.StringUtils;
import com.scudata.dm.Context;
import com.scudata.dm.ParamList;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.server.ConnectionProxyManager;
import com.scudata.util.CellSetUtil;

/**
 * ODBC?????????߳?
 * @author Joancy
 *
 */
class OdbcWorker extends Thread {
	static final int Buffer_Size = 1024 * 64; // ????????С
	
	private Socket sckt;
	private volatile boolean stop = false;
	OutputStream out;
	InputStream in;

	/**
	 * ????һ??????????
	 * @param tg ?߳???
	 * @param name ????
	 */
	public OdbcWorker(ThreadGroup tg, String name) {
		super(tg, name);
	}

	/**
	 * ????ͨѶ?׽???
	 * @param socket ?׽???
	 * @throws Exception
	 */
	public void setSocket(Socket socket) throws Exception{
			socket.setTcpNoDelay(true);
			socket.setKeepAlive(true);
			socket.setReceiveBufferSize(Buffer_Size);
			socket.setSendBufferSize(Buffer_Size);
			socket.setSoLinger(true, 1);
			socket.setReuseAddress(true);
			socket.setSoTimeout(3000);
			this.sckt = socket;
			holdBufferStream();
	}
	
	private void holdBufferStream() throws IOException{
		OutputStream os = sckt.getOutputStream();
		out = new BufferedOutputStream(os);
		out.flush();
		
		InputStream is = sckt.getInputStream();
		in = new BufferedInputStream(is);
	}

	private void writeOdbcResponse(OutputStream os, int code, String returnMsg)
			throws Exception {
		DataTypes.writeInt(os, code);
		if (returnMsg == null)
			return;
		if (code < 0) {
			DataTypes.writeString(os, returnMsg);
		}
	}

	private ConnectionProxy getConnectionProxy(ConnectionProxyManager cpm,int connId) throws Exception{
		return (ConnectionProxy)cpm.getConnectionProxy(connId);
	}

	/*
	 * Э?? int:high byte first char:unicode big endian ????ֵ?? ??ȷʱ??4byte(>=0
	 * ??Ӧ????Ĵ?????)+[??????Ϣ] ????ʱ??4byte(-1)+4byte(???󳤶?)+[??????Ϣ]
	 */
	private boolean serveODBC(int reqType, InputStream is, OutputStream os) {
		try {
			OdbcServer server = OdbcServer.getInstance();
			OdbcContext context = server.getContext();
			ConnectionProxyManager cpm = ConnectionProxyManager.getInstance();
			switch (reqType) {
			// 1000??odbclogin:
			// 4byte(1000)+4byte(user????) + [user] + 4byte(password????) +
			// [password]
			// return: ??ȷʱ??4byte(???Ӻ?)
			// ????ʱ??4byte(-1)+4byte(???󳤶?)+[??????Ϣ]
			case 1000:
				String user = DataTypes.readString(is);
				String password = DataTypes.readString(is);
				if (!context.isUserExist(user)) {
					writeOdbcResponse(os, -1, "Login error: invalid user "
							+ user);
				} else {
					try {
						boolean success = context.checkUser(user, password);
						if (success) {
							int connId = OdbcServer.nextId();
							ConnectionProxy connProxy = new ConnectionProxy(
									cpm, connId, user);
							cpm.addProxy(connProxy);
							writeOdbcResponse(os, connId,
									"Login OK, current odbc user: " + user);
						}
					} catch (Exception x) {
						writeOdbcResponse(os, -1, x.getMessage());
					}
				}
				break;
			// * 1001??prepare statement dfx or dql:
			// * 4byte(1001) + 4byte(???Ӻ?) + 4byte(dfx????) + [dfx] +[ArgRowData]
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte( Statement?? )
			case 1001:
				int connId = DataTypes.readInt(is);
				String dfx = DataTypes.readString(is);
				Object[] args = DataTypes.readRowData(is);
				ArrayList argList = new ArrayList();
				if (args != null) {
					for (int i = 0; i < args.length; i++) {
						argList.add(args[i]);
					}
				}
				ConnectionProxy connProxy = getConnectionProxy(cpm,connId);
				int stateId = OdbcServer.nextId();
				StatementProxy sp = new StatementProxy(connProxy, stateId, dfx,
						argList);
				connProxy.addProxy(sp);
				writeOdbcResponse(os, stateId, null);
				break;
			// * 1002??execute statement dfx or dql:
			// * 4byte(1002) + 4byte(???Ӻ?) + 4byte(statement??)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte( ????????? )+ 4byte( ??????? )...
			case 1002:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				int[] resultIds = sp.execute();
				DataTypes.writeInt(os, resultIds.length);
				for (int i = 0; i < resultIds.length; i++) {
					DataTypes.writeInt(os, resultIds[i]);
				}
				break;
			// * 1003??cancel execute dfx:
			// * 4byte(1003) + 4byte(???Ӻ?) + 4byte(statement??)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte( 0 )
			case 1003:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				sp.cancel();
				DataTypes.writeInt(os, 0);
				break;
			// * 1010????ȡ??????ṹ
			// * 4byte(1010) + 4byte(???Ӻ?) + 4byte(statement??) + 4byte(???????ʶ??)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte(?ֶ???Ŀ)+4byte(?ֶ?1????)+[?ֶ?1??Ϣ]...
			// *
			case 1010:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				int resultId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				ResultSetProxy rsp = sp.getResultSetProxy(resultId);
				String[] columns = rsp.getColumns();
				if (columns == null) {
					DataTypes.writeInt(os, 0);
					return true;
				}
				// ?ɹ???־
				int size = columns.length;
				DataTypes.writeInt(os, size);
				for (int i = 0; i < size; i++) {
					DataTypes.writeString(os, columns[i]);
				}
				break;
			// * 1011???????ȡ??
			// * 4byte(1011) + 4byte(???Ӻ?)+4byte(statement??)+4byte(???????ʶ??) +
			// 4byte(fetchSize)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte(0)+[???ݱ?]
			// *
			case 1011:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				resultId = DataTypes.readInt(is);
				int n = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				rsp = sp.getResultSetProxy(resultId);
				Sequence data = rsp.fetch(n);
				DataTypes.checkTable(data);
				
				// ?ɹ???־
				DataTypes.writeInt(os, 0);
				DataTypes.writeTable(os, data);
				break;
//				????sqlfirst?????õ?cmd=1012(???ij?????Ҳ??)
//						????Ϊstring(??:a=1;b=2),ÿ??????Ϊk=v??ʽ???÷ֺŸ???????Ҫ?ǿ??ǽ????????ø???????ԡ?
//						??ǰsqlfirst???????ó?sqlfirst=simple??sqlfirst=plus???ݸ?server.
				// * 1012??????????
				// * 4byte(1012) + 4byte(?ֽڴ?????)+[?ֽڴ?]
				// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
				// * ???óɹ?, 4byte(0)
				// *
			case 1012://????sql+
				String properties = DataTypes.readString(is);
				// ?ɹ???־
				DataTypes.writeInt(os, 0);
				break;
			// * 1018???ر?Statement
			// * 4byte(1018) + 4byte(???Ӻ?)+4byte(statement??)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte(0)
			// *
			case 1018:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				sp.destroy();
				writeOdbcResponse(os, 0, "Statement:" + stateId + " is closed.");
				break;
			// * 1020???رս????
			// * 4byte(1020) + 4byte(???Ӻ?)+4byte(statement??)+4byte(???????ʶ??)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte(0)
			// *
			case 1020:
				connId = DataTypes.readInt(is);
				stateId = DataTypes.readInt(is);
				resultId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				sp = connProxy.getStatementProxy(stateId);
				rsp = sp.getResultSetProxy(resultId);
				rsp.destroy();
				writeOdbcResponse(os, 0, "ResultSet:" + resultId
						+ " is closed.");
				break;
//				 * 1050???г??洢???̣?????ͨ?????????dfx????
//				 * 4byte(1050) + 4byte(???Ӻ?) + 4byte(??????????) + [??????]
//				 * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
//				 *         ??ȷʱ, 4byte(0)+[?̶???ʽ?洢?????б???Ϣ??]
//				 *
			case 1050:
				connId = DataTypes.readInt(is);
				String filter = DataTypes.readString(is);
				Map m = com.esproc.jdbc.JDBCUtil.getSplList(filter);
				String spCols = "PROCEDURE_CAT,PROCEDURE_SCHEM,PROCEDURE_NAME,NUM_INPUT_PARAMS,NUM_OUTPUT_PARAMS,NUM_RESULT_SETS,REMARKS,PROCEDURE_TYPE";
				StringTokenizer st = new StringTokenizer(spCols, ",");
				ArrayList cols = new ArrayList();
				while (st.hasMoreTokens()) {
					String name = st.nextToken();
					cols.add(name);
				}

				Table storeInfos = new Table(StringUtils.toStringArray(cols));
				Iterator files = m.keySet().iterator();
				while (files.hasNext()){
					String path = files.next();
					String dfxName = m.get(path);
					int paramCount = getParamCount(path);
					storeInfos.newLast(new Object[]{"","",dfxName,paramCount,-1,-1,"",2});
				}
				// ?ɹ???־
				DataTypes.writeInt(os, 0);
				DataTypes.writeTable(os, storeInfos);
				break;
//				 * 1051????ȡ?洢??????ϸ??Ϣ??
//				 * 4byte(1051) + 4byte(?洢??????????) + [????]
//				 * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
//				 *         ??ȷʱ, 4byte(0)+[?̶???ʽ?洢??????Ϣ??]
//				 *
				
				
//				 * 1060???г?????Ϣ??
//				 * 4byte(1060) + 4byte(???Ӻ?) + 4byte(?????Ƴ???) + [??????]
//				 * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
//				 *         ??ȷʱ, 4byte(?ֶ???Ŀ)+4byte(?ֶ?1????)+[?ֶ?1??Ϣ]...+[????Ϣ???ݱ?]
			case 1060:
				connId = DataTypes.readInt(is);
				String tableName = DataTypes.readString(is);
				connProxy = getConnectionProxy(cpm,connId);
				Table table = JDBCUtil.getTables(tableName);
				DataTypes.writeDatastructAndData(os, table);
				break;
				
//				 * 1061???г??ֶ???Ϣ??
//				 * 4byte(1061) + 4byte(???Ӻ?) + 4byte(?????Ƴ???) + [??????]+ 4byte(?ֶγ???) + [?ֶ?]
//				 * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
//				 *         ??ȷʱ, 4byte(?ֶ???Ŀ)+4byte(?ֶ?1????)+[?ֶ?1??Ϣ]...+[????Ϣ???ݱ?]
			case 1061:
				connId = DataTypes.readInt(is);
				tableName = DataTypes.readString(is);
				String columnName = DataTypes.readString(is);
				connProxy = getConnectionProxy(cpm,connId);
				table = JDBCUtil.getColumns(tableName, columnName, new Context());
				DataTypes.writeDatastructAndData(os, table);
				break;
				
			// * 1111???ر?????
			// * 4byte(1111) + 4byte(???Ӻ?)
			// * return: ????ʱ, 4byte(-1:???????)+4byte(???󳤶?)+[??????Ϣ]
			// * ??ȷʱ, 4byte(0)
			// *
			case 1111:
				connId = DataTypes.readInt(is);
				connProxy = getConnectionProxy(cpm,connId);
				writeOdbcResponse(os, 0, null);
				os.flush();
				connProxy.destroy();
				return false;
				// ?ر?Socket
			case 2222:
				return false;
			}
		} catch (Throwable x) {
			String msg = x.getMessage();
			while(msg==null && x.getCause()!=null){
				 x = x.getCause();
				 msg = x.getMessage();
			}
			try {
				writeOdbcResponse(os, -1, msg);
			} catch (Exception e) {
			}
			x.printStackTrace();
			Logger.debug("Service exception:"+msg);
		}
		return true;
	}
	
	private int getParamCount(String dfx) throws Exception{
		int c = -1;
		FileInputStream in=null;
		try{
			in = new FileInputStream(dfx);
			PgmCellSet cs = CellSetUtil.readPgmCellSet(in);
			ParamList pl = cs.getParamList();
			if(pl!=null){
				c = pl.count();
			}
		}finally{
			if(in!=null) in.close();
		}
		return c;
	}

	public void shutDown() {
		stop = true;
	}

	/**
	 * ???й???????
	 */
	public void run() {
		try {
			InputStream is = in;
			OutputStream os = out;
			while (!stop) {
				int reqType = 0;
				try{
					reqType = DataTypes.readInt(is);
				}catch (java.net.SocketTimeoutException e) {
					continue;
				}

				if (reqType == -1) {
					// ?رշ?????
					OdbcServer.getInstance().shutDown();
					return;
				}

				// ?رշ????߳?
				if (reqType == -2) {
					break;
				}

				if (reqType > 0) {
					if (serveODBC(reqType, is, os)) {
						os.flush();
						continue;
					}
					break;
				}
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			in.close();
			out.close();
			sckt.close();
		} catch (IOException e) {
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy