diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java index 9cbd199..c87a17c 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.sql.Array; import java.sql.ResultSet; import java.sql.SQLException; @@ -9,6 +11,7 @@ import java.util.Map; * @author Yichen Dai * @date 2022/8/31 16:52 */ +@BindClass public class AgentArray implements Array { Array array; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java index 67be231..26d0874 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; @@ -9,6 +11,7 @@ import java.sql.SQLException; * @author Yichen Dai * @date 2022/8/29 20:33 */ +@BindClass public class AgentBlob implements Blob { private Blob blob; @@ -28,7 +31,7 @@ public class AgentBlob implements Blob { @Override public InputStream getBinaryStream() throws SQLException { - return blob.getBinaryStream(); + return new AgentInputStream(blob.getBinaryStream()); } @Override @@ -68,6 +71,6 @@ public class AgentBlob implements Blob { @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { - return blob.getBinaryStream(pos, length); + return new AgentInputStream(blob.getBinaryStream()); } } diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java index 2f91512..12022c7 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; @@ -11,6 +13,7 @@ import java.sql.SQLException; * @author Yichen Dai * @date 2022/8/29 20:34 */ +@BindClass public class AgentClob implements Clob { private Clob clob; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java index b07e7d3..19447fd 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java @@ -1,6 +1,7 @@ package com.fanruan.agent.jdbc; import com.fanruan.agent.jdbc.resultset.AgentResultSet; +import com.fanruan.annotation.BindClass; import java.sql.*; @@ -8,6 +9,7 @@ import java.sql.*; * @author Yichen Dai * @date 2022/8/25 11:22 */ +@BindClass public class AgentDataBaseMetaData implements DatabaseMetaData { DatabaseMetaData metaData; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentInputStream.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentInputStream.java new file mode 100644 index 0000000..2fa2eff --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentInputStream.java @@ -0,0 +1,64 @@ +package com.fanruan.agent.jdbc; + +import com.fanruan.annotation.BindClass; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Yichen Dai + * @date 2022/9/8 18:15 + */ +@BindClass +public class AgentInputStream extends InputStream { + private InputStream inputStream; + + public AgentInputStream(InputStream inputStream){ + this.inputStream = inputStream; + } + + @Override + public int read() throws IOException { + return inputStream.read(); + } + + @Override + public int read(byte b[]) throws IOException { + return inputStream.read(b); + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + return inputStream.read(b, off, len); + } + + @Override + public long skip(long n) throws IOException { + return inputStream.skip(n); + } + + @Override + public int available() throws IOException { + return inputStream.available(); + } + + @Override + public void close() throws IOException { + inputStream.close(); + } + + @Override + public synchronized void mark(int readlimit) { + inputStream.mark(readlimit); + } + + @Override + public synchronized void reset() throws IOException { + inputStream.reset(); + } + + @Override + public boolean markSupported() { + return inputStream.markSupported(); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java index 9f32467..44596e9 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.sql.ParameterMetaData; import java.sql.SQLException; @@ -8,7 +10,7 @@ import java.sql.SQLException; * @date 2022/8/25 16:41 */ - +@BindClass public class AgentParameterMetaData implements ParameterMetaData { private ParameterMetaData metaData; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentReader.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentReader.java new file mode 100644 index 0000000..9bdbbc3 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentReader.java @@ -0,0 +1,71 @@ +package com.fanruan.agent.jdbc; + +import com.fanruan.annotation.BindClass; +import io.socket.client.IO; + +import java.io.IOException; +import java.io.Reader; + +/** + * @author Yichen Dai + * @date 2022/9/8 16:55 + */ +@BindClass +public class AgentReader extends Reader { + + Reader reader; + + public AgentReader(Reader reader){ + this.reader = reader; + } + + @Override + public int read(java.nio.CharBuffer target) throws IOException { + return reader.read(target); + } + + @Override + public int read() throws IOException{ + return reader.read(); + } + + @Override + public int read(char cbuf[]) throws IOException { + return reader.read(cbuf); + } + + @Override + public long skip(long n) throws IOException { + return reader.skip(n); + } + + @Override + public boolean ready() throws IOException{ + return reader.ready(); + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + return reader.read(cbuf, off, len); + } + + @Override + public boolean markSupported() { + return reader.markSupported(); + } + + @Override + public void mark(int readAheadLimit) throws IOException { + reader.mark(readAheadLimit); + } + + @Override + public void reset() throws IOException { + reader.reset(); + } + + @Override + public void close() throws IOException { + reader.close(); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java index bf84091..98b4ff9 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.sql.ResultSetMetaData; import java.sql.SQLException; @@ -7,6 +9,7 @@ import java.sql.SQLException; * @author Yichen Dai * @date 2022/9/1 14:45 */ +@BindClass public class AgentResultSetMetaData implements ResultSetMetaData { private ResultSetMetaData metaData; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java index 0fd76fb..61797d3 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc; +import com.fanruan.annotation.BindClass; + import java.sql.SQLException; import java.sql.Struct; import java.util.Map; @@ -8,6 +10,7 @@ import java.util.Map; * @author Yichen Dai * @date 2022/8/31 17:04 */ +@BindClass public class AgentStruct implements Struct { Struct struct; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java b/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java index def727a..5b724be 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java @@ -4,6 +4,7 @@ import com.fanruan.agent.jdbc.AgentDataBaseMetaData; import com.fanruan.agent.jdbc.statement.AgentCallableStatement; import com.fanruan.agent.jdbc.statement.AgentPreparedStatement; import com.fanruan.agent.jdbc.statement.AgentStatement; +import com.fanruan.annotation.BindClass; import java.sql.*; import java.util.Map; @@ -13,6 +14,7 @@ import java.util.concurrent.Executor; /** * @author Yichen Dai */ +@BindClass public class AgentConnection implements Connection { final private Connection conn; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/driver/AgentDriver.java b/agent/src/main/java/com/fanruan/agent/jdbc/driver/AgentDriver.java index 4c1624e..66d4970 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/driver/AgentDriver.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/driver/AgentDriver.java @@ -1,6 +1,7 @@ package com.fanruan.agent.jdbc.driver; import com.fanruan.agent.jdbc.connection.AgentConnection; +import com.fanruan.annotation.BindClass; import java.sql.*; import java.util.Enumeration; @@ -10,6 +11,7 @@ import java.util.logging.Logger; /** * @author Yichen Dai */ +@BindClass public class AgentDriver implements Driver { diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/resultset/AgentResultSet.java b/agent/src/main/java/com/fanruan/agent/jdbc/resultset/AgentResultSet.java index dce62d1..f687ee3 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/resultset/AgentResultSet.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/resultset/AgentResultSet.java @@ -1,5 +1,8 @@ package com.fanruan.agent.jdbc.resultset; +import com.fanruan.agent.jdbc.*; +import com.fanruan.annotation.BindClass; + import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; @@ -8,6 +11,7 @@ import java.sql.*; import java.util.Calendar; import java.util.Map; +@BindClass public class AgentResultSet implements ResultSet { final private ResultSet resultSet; @@ -98,17 +102,17 @@ public class AgentResultSet implements ResultSet { @Override public InputStream getAsciiStream(int columnIndex) throws SQLException { - return resultSet.getAsciiStream(columnIndex); + return new AgentInputStream(resultSet.getAsciiStream(columnIndex)); } @Override public InputStream getUnicodeStream(int columnIndex) throws SQLException { - return resultSet.getUnicodeStream(columnIndex); + return new AgentInputStream(resultSet.getUnicodeStream(columnIndex)); } @Override public InputStream getBinaryStream(int columnIndex) throws SQLException { - return resultSet.getBinaryStream(columnIndex); + return new AgentInputStream(resultSet.getBinaryStream(columnIndex)); } @Override @@ -178,17 +182,17 @@ public class AgentResultSet implements ResultSet { @Override public InputStream getAsciiStream(String columnLabel) throws SQLException { - return resultSet.getAsciiStream(columnLabel); + return new AgentInputStream(resultSet.getAsciiStream(columnLabel)); } @Override public InputStream getUnicodeStream(String columnLabel) throws SQLException { - return resultSet.getUnicodeStream(columnLabel); + return new AgentInputStream(resultSet.getUnicodeStream(columnLabel)); } @Override public InputStream getBinaryStream(String columnLabel) throws SQLException { - return resultSet.getBinaryStream(columnLabel); + return new AgentInputStream(resultSet.getBinaryStream(columnLabel)); } @Override @@ -228,12 +232,12 @@ public class AgentResultSet implements ResultSet { @Override public Reader getCharacterStream(int columnIndex) throws SQLException { - return resultSet.getCharacterStream(columnIndex); + return new AgentReader(resultSet.getCharacterStream(columnIndex)); } @Override public Reader getCharacterStream(String columnLabel) throws SQLException { - return resultSet.getCharacterStream(columnLabel); + return new AgentReader(resultSet.getCharacterStream(columnLabel)); } @Override @@ -593,17 +597,17 @@ public class AgentResultSet implements ResultSet { @Override public Blob getBlob(int columnIndex) throws SQLException { - return resultSet.getBlob(columnIndex); + return new AgentBlob(resultSet.getBlob(columnIndex)); } @Override public Clob getClob(int columnIndex) throws SQLException { - return resultSet.getClob(columnIndex); + return new AgentClob(resultSet.getClob(columnIndex)); } @Override public Array getArray(int columnIndex) throws SQLException { - return resultSet.getArray(columnIndex); + return new AgentArray(resultSet.getArray(columnIndex)); } @Override @@ -618,17 +622,17 @@ public class AgentResultSet implements ResultSet { @Override public Blob getBlob(String columnLabel) throws SQLException { - return resultSet.getBlob(columnLabel); + return new AgentBlob(resultSet.getBlob(columnLabel)); } @Override public Clob getClob(String columnLabel) throws SQLException { - return resultSet.getClob(columnLabel); + return new AgentClob(resultSet.getClob(columnLabel)); } @Override public Array getArray(String columnLabel) throws SQLException { - return resultSet.getArray(columnLabel); + return new AgentArray(resultSet.getArray(columnLabel)); } @Override @@ -803,12 +807,12 @@ public class AgentResultSet implements ResultSet { @Override public Reader getNCharacterStream(int columnIndex) throws SQLException { - return resultSet.getNCharacterStream(columnIndex); + return new AgentReader(resultSet.getNCharacterStream(columnIndex)); } @Override public Reader getNCharacterStream(String columnLabel) throws SQLException { - return resultSet.getNCharacterStream(columnLabel); + return new AgentReader(resultSet.getNCharacterStream(columnLabel)); } @Override diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java index 763d563..0ee3c20 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java @@ -4,6 +4,7 @@ import com.fanruan.agent.jdbc.AgentArray; import com.fanruan.agent.jdbc.AgentBlob; import com.fanruan.agent.jdbc.AgentClob; import com.fanruan.agent.jdbc.AgentParameterMetaData; +import com.fanruan.annotation.BindClass; import java.io.InputStream; import java.io.Reader; @@ -17,6 +18,7 @@ import java.util.Map; * @author Yichen Dai * @date 2022/8/24 16:18 */ +@BindClass public class AgentCallableStatement implements java.sql.CallableStatement { final private CallableStatement cst; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java index 56c5e83..c168a02 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java @@ -4,6 +4,7 @@ package com.fanruan.agent.jdbc.statement; import com.fanruan.agent.jdbc.AgentParameterMetaData; import com.fanruan.agent.jdbc.AgentResultSetMetaData; import com.fanruan.agent.jdbc.resultset.AgentResultSet; +import com.fanruan.annotation.BindClass; import java.io.InputStream; import java.io.Reader; @@ -15,6 +16,7 @@ import java.util.Calendar; /** * @author Yichen Dai */ +@BindClass public class AgentPreparedStatement implements PreparedStatement { final PreparedStatement pst; diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java index 9943837..c138473 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java @@ -1,12 +1,14 @@ package com.fanruan.agent.jdbc.statement; import com.fanruan.agent.jdbc.resultset.AgentResultSet; +import com.fanruan.annotation.BindClass; import java.sql.*; /** * @author Yichen Dai */ +@BindClass public class AgentStatement implements Statement { final private Statement st; diff --git a/agent/src/main/java/com/fanruan/annotation/BindClass.java b/agent/src/main/java/com/fanruan/annotation/BindClass.java new file mode 100644 index 0000000..e32767b --- /dev/null +++ b/agent/src/main/java/com/fanruan/annotation/BindClass.java @@ -0,0 +1,13 @@ +package com.fanruan.annotation; + +import java.lang.annotation.*; + +/** + * @author Yichen Dai + * @date 2022/9/9 10:19 + */ +@Inherited +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface BindClass { +} diff --git a/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java b/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java index 0e03968..02de331 100644 --- a/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java +++ b/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java @@ -1,6 +1,8 @@ package com.fanruan.handler; +import com.fanruan.annotation.BindClass; + import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; @@ -24,35 +26,13 @@ public class DispatcherHelper { } }; - public final static String[] CACHE_LIST = new String[]{ - "Driver", - "Connection", - "Statement", - "PreparedStatement", - "ResultSet", - "MetaData", - "Clob", - "Blob", - "Array", - "Struct" - - }; - public static boolean isInCacheList(Object obj){ if(obj == null) { return false; } - return isInCacheList(obj.getClass().getName()); - } - - public static boolean isInCacheList(String className){ - if (className == null){ - return false; - } - for(String s : CACHE_LIST){ - if(Pattern.matches(".*" + s + ".*", className)){ - return true; - } + Class clazz = obj.getClass(); + if(clazz.isAnnotationPresent(BindClass.class)){ + return true; } return false; } diff --git a/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java b/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java index 2359ce5..5abb286 100644 --- a/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java +++ b/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java @@ -16,8 +16,6 @@ import java.lang.reflect.Method; public class DispatcherImpl implements Dispatcher{ protected static final Logger logger = LogManager.getLogger(); - public final static String CLOSE_NAME = "close"; - public DispatcherImpl(){} @Override @@ -32,7 +30,7 @@ public class DispatcherImpl implements Dispatcher{ RESPONSE_EMITTER_IMPL.sendError(CACHE.getSocket(dbName), rpcRequest, t); } - if(res != null && !DispatcherHelper.isInCacheList(res.getClass().getName())){ + if(res != null && !DispatcherHelper.isInCacheList(res)){ RESPONSE_EMITTER_IMPL.replyWithData(CACHE.getSocket(dbName), rpcRequest, res); }else { RESPONSE_EMITTER_IMPL.sendOk(CACHE.getSocket(dbName), rpcRequest); diff --git a/agent/src/test/java/HSQLTest.java b/agent/src/test/java/HSQLTest.java index 2886889..ccb1710 100644 --- a/agent/src/test/java/HSQLTest.java +++ b/agent/src/test/java/HSQLTest.java @@ -73,15 +73,18 @@ public class HSQLTest { public void test() throws SQLException { Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:test;sql.syntax_mys=true", "sa", ""); Statement statement = conn.createStatement(); - statement.executeUpdate("CREATE TABLE city (id INTEGER, name varchar(20)); "); - statement.executeUpdate("INSERT INTO city VALUES (1, '成都'), (2, '上海'); "); - - statement.execute(createStoredProcedure); - CallableStatement callableStatement = conn.prepareCall("{call get_city_name(?, ?)}"); - callableStatement.setInt(1, 2); - callableStatement.registerOutParameter(2, Types.VARCHAR); - callableStatement.execute(); - System.out.println(callableStatement.getString(2)); + statement.execute("create table TestTable " + + " (" + + " testString varchar(20), " + + " testBoolean BOOLEAN, " + + " testByte NUMERIC(10), " + + " testShort NUMERIC(10), " + + " testInt INTEGER, " + + " testLong BIGINT, " + + " testFloat FLOAT, " + + " testDouble DOUBLE, " + + " testDecimal DECIMAL);" + ); } /** diff --git a/service/src/main/java/com/fanruan/annotation/RemoteClass.java b/service/src/main/java/com/fanruan/annotation/RemoteClass.java index f1ef6c9..5fe27bd 100644 --- a/service/src/main/java/com/fanruan/annotation/RemoteClass.java +++ b/service/src/main/java/com/fanruan/annotation/RemoteClass.java @@ -1,14 +1,12 @@ package com.fanruan.annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import java.lang.annotation.*; /** * @author Yichen Dai * @date 2022/8/19 10:50 */ +@Inherited @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RemoteClass { diff --git a/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java b/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java index ea7749f..108575d 100644 --- a/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java +++ b/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java @@ -8,11 +8,15 @@ import com.fanruan.cache.ClientWrapper; import com.fanruan.cache.LockAndCondition; import com.fanruan.pojo.message.RpcRequest; import com.fanruan.service.jdbc.AbstractBind; +import com.fanruan.service.jdbc.ServiceInputStream; +import com.fanruan.service.jdbc.ServiceReader; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.io.InputStream; +import java.io.Reader; import java.lang.reflect.Method; import java.util.Properties; import java.util.concurrent.FutureTask; @@ -99,8 +103,7 @@ public class Interceptor implements MethodInterceptor { // If the return instance is corresponding with another instance in agent, set the binding ID. if (InterceptorUtils.isInBindList(returnObj)){ - AbstractBind ab = (AbstractBind) returnObj; - ab.setID(rpcRequest.getID()); + InterceptorUtils.setBindID(returnObj, rpcRequest.getID()); } return returnObj; } diff --git a/service/src/main/java/com/fanruan/proxy/interceptor/InterceptorUtils.java b/service/src/main/java/com/fanruan/proxy/interceptor/InterceptorUtils.java index cf54cd9..12186b8 100644 --- a/service/src/main/java/com/fanruan/proxy/interceptor/InterceptorUtils.java +++ b/service/src/main/java/com/fanruan/proxy/interceptor/InterceptorUtils.java @@ -5,8 +5,11 @@ import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; import com.fanruan.pojo.message.RpcRequest; import com.fanruan.service.jdbc.AbstractBind; +import com.fanruan.service.jdbc.ServiceInputStream; +import com.fanruan.service.jdbc.ServiceReader; import com.fanruan.utils.Commons; +import java.io.Reader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.regex.Pattern; @@ -15,10 +18,6 @@ import java.util.regex.Pattern; * @author Yichen Dai */ public class InterceptorUtils { - private static final String[] EXCLUDED_METHOD_LIST = new String[]{ - "toString", - "hashCode", - }; private static final String[] WRAPPER_CLASS_LIST = new String[]{ "Boolean", @@ -30,28 +29,6 @@ public class InterceptorUtils { "Short", "Float" }; - - private final static String[] BIND_LIST = new String[]{ - "Driver", - "Connection", - "Statement", - "PreparedStatement", - "ResultSet", - "MetaData", - "Clob", - "Blob", - "Array", - "Struct" - }; - - public static boolean isInExcludedList(String methodName){ - for(String ex : EXCLUDED_METHOD_LIST){ - if(ex.equals(methodName)){ - return true; - } - } - return false; - } public static boolean isWraps(Object o){ for(String ex : WRAPPER_CLASS_LIST){ @@ -75,22 +52,42 @@ public class InterceptorUtils { if (o == null) { return false; } - return isInBindList(o.getClass().getName()); + Class clazz = o.getClass(); + if(clazz.isAnnotationPresent(RemoteClass.class)){ + return true; + } + return false; } - public static boolean isInBindList(String className){ - for(String pattern : BIND_LIST){ - if(Pattern.matches(".*" + pattern + ".*", className)){ - return true; - } + public static void setBindID(Object returnObj, String ID){ + if(returnObj instanceof AbstractBind){ + AbstractBind ab = (AbstractBind) returnObj; + ab.setID(ID); + }else if(returnObj instanceof ServiceReader){ + ServiceReader sr = (ServiceReader) returnObj; + sr.setID(ID); + }else if(returnObj instanceof ServiceInputStream){ + ServiceInputStream sis = (ServiceInputStream) returnObj; + sis.setID(ID); } - return false; } + public static String getBindID(Object o){ + String idToInvoke = null; + if(o instanceof AbstractBind){ + AbstractBind ab = (AbstractBind) o; + idToInvoke = ab.getID(); + }else if(o instanceof Reader){ + ServiceReader sr = (ServiceReader) o; + idToInvoke = sr.getID(); + }else if(o instanceof ServiceInputStream){ + ServiceInputStream sis = (ServiceInputStream) o; + idToInvoke = sis.getID(); + } + return idToInvoke; + } public static RpcRequest generateRequest(Class clazz, Object o, Method method, Object[] objects){ - - RpcRequest rpcRequest = new RpcRequest(); rpcRequest .setID(Commons.getID()) @@ -109,8 +106,7 @@ public class InterceptorUtils { // IDtoInvoke is an unique ID to identify an one-to-one binding relation. // It comes from rpcRequest in which the instance in the agent is created. - AbstractBind ab = (AbstractBind) o; - String idToInvoke = ab.getID(); + String idToInvoke = getBindID(o); if(idToInvoke != null){ rpcRequest.setIDToInvoke(idToInvoke); diff --git a/service/src/main/java/com/fanruan/service/jdbc/ServiceBlob.java b/service/src/main/java/com/fanruan/service/jdbc/ServiceBlob.java index 8325b72..65c3fe6 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/ServiceBlob.java +++ b/service/src/main/java/com/fanruan/service/jdbc/ServiceBlob.java @@ -1,6 +1,7 @@ package com.fanruan.service.jdbc; import com.fanruan.annotation.RemoteClass; +import com.fanruan.proxy.ProxyFactory; import com.fanruan.service.jdbc.AbstractBind; import java.io.InputStream; @@ -28,7 +29,7 @@ public class ServiceBlob extends BasedBind implements Blob { @Override public InputStream getBinaryStream() throws SQLException { - return null; + return (InputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override @@ -68,6 +69,6 @@ public class ServiceBlob extends BasedBind implements Blob { @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { - return null; + return (InputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } } diff --git a/service/src/main/java/com/fanruan/service/jdbc/ServiceInputStream.java b/service/src/main/java/com/fanruan/service/jdbc/ServiceInputStream.java new file mode 100644 index 0000000..0b34819 --- /dev/null +++ b/service/src/main/java/com/fanruan/service/jdbc/ServiceInputStream.java @@ -0,0 +1,67 @@ +package com.fanruan.service.jdbc; + +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.RemoteClass; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Yichen Dai + * @date 2022/9/8 18:11 + */ +@RemoteClass(remoteClassName = "com.fanruan.agent.jdbc.AgentInputStream") +public class ServiceInputStream extends InputStream { + + private String ID; + + @LocalMethod + public String getID(){ + return this.ID; + } + + @LocalMethod + public void setID(String ID){ + this.ID = ID; + } + + @Override + public int read() throws IOException { + return 0; + } + + @Override + public void close() throws IOException { + + } + + @LocalMethod + @Override + public int hashCode(){ + return super.hashCode(); + } + + @LocalMethod + @Override + public boolean equals(Object obj) { + return super.equals(obj); + } + + @LocalMethod + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + @LocalMethod + @Override + public String toString() { + return super.toString(); + } + + @LocalMethod + @Override + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/service/src/main/java/com/fanruan/service/jdbc/ServiceReader.java b/service/src/main/java/com/fanruan/service/jdbc/ServiceReader.java new file mode 100644 index 0000000..77368e0 --- /dev/null +++ b/service/src/main/java/com/fanruan/service/jdbc/ServiceReader.java @@ -0,0 +1,68 @@ +package com.fanruan.service.jdbc; + +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.RemoteClass; + +import java.io.IOException; +import java.io.Reader; +import java.util.Properties; + +/** + * @author Yichen Dai + * @date 2022/9/8 16:45 + */ +@RemoteClass(remoteClassName = "com.fanruan.agent.jdbc.AgentReader") +public class ServiceReader extends Reader { + + private String ID; + + @LocalMethod + public String getID(){ + return this.ID; + } + + @LocalMethod + public void setID(String ID){ + this.ID = ID; + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + return 0; + } + + @Override + public void close() throws IOException { + + } + + @LocalMethod + @Override + public int hashCode(){ + return super.hashCode(); + } + + @LocalMethod + @Override + public boolean equals(Object obj) { + return super.equals(obj); + } + + @LocalMethod + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + @LocalMethod + @Override + public String toString() { + return super.toString(); + } + + @LocalMethod + @Override + protected void finalize() throws Throwable { + super.finalize(); + } +} diff --git a/service/src/main/java/com/fanruan/service/jdbc/connection/ServiceConnection.java b/service/src/main/java/com/fanruan/service/jdbc/connection/ServiceConnection.java index 222e58b..3a6fe08 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/connection/ServiceConnection.java +++ b/service/src/main/java/com/fanruan/service/jdbc/connection/ServiceConnection.java @@ -3,8 +3,7 @@ package com.fanruan.service.jdbc.connection; import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; -import com.fanruan.service.jdbc.BasedBind; -import com.fanruan.service.jdbc.ServiceDatabaseMetaData; +import com.fanruan.service.jdbc.*; import com.fanruan.service.jdbc.statement.ServiceCallableStatement; import com.fanruan.service.jdbc.statement.ServicePreparedStatement; import com.fanruan.service.jdbc.statement.ServiceStatement; @@ -235,12 +234,16 @@ public class ServiceConnection extends BasedBind implements Connection { @Override public Clob createClob() throws SQLException { - return null; + ServiceClob clob = (ServiceClob) ProxyFactory.getProxy(ServiceClob.class, info); + clob.setInfo(info); + return clob; } @Override public Blob createBlob() throws SQLException { - return null; + ServiceBlob blob = (ServiceBlob) ProxyFactory.getProxy(ServiceBlob.class, info); + blob.setInfo(info); + return blob; } @Override @@ -280,12 +283,16 @@ public class ServiceConnection extends BasedBind implements Connection { @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { - return null; + ServiceArray array = (ServiceArray) ProxyFactory.getProxy(ServiceArray.class, info); + array.setInfo(info); + return array; } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { - return null; + ServiceStruct struct = (ServiceStruct) ProxyFactory.getProxy(ServiceStruct.class, info); + struct.setInfo(info); + return struct; } @Override diff --git a/service/src/main/java/com/fanruan/service/jdbc/resultset/ServiceResultSet.java b/service/src/main/java/com/fanruan/service/jdbc/resultset/ServiceResultSet.java index 0e99ed2..31a057f 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/resultset/ServiceResultSet.java +++ b/service/src/main/java/com/fanruan/service/jdbc/resultset/ServiceResultSet.java @@ -1,10 +1,11 @@ package com.fanruan.service.jdbc.resultset; +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; import com.fanruan.proxy.ProxyFactory; -import com.fanruan.service.jdbc.BasedBind; -import com.fanruan.service.jdbc.ServiceResultSetMetaData; +import com.fanruan.service.jdbc.*; import java.io.InputStream; import java.io.Reader; @@ -102,17 +103,17 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public InputStream getAsciiStream(int columnIndex) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override public InputStream getUnicodeStream(int columnIndex) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override public InputStream getBinaryStream(int columnIndex) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override @@ -182,17 +183,17 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public InputStream getAsciiStream(String columnLabel) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override public InputStream getUnicodeStream(String columnLabel) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override public InputStream getBinaryStream(String columnLabel) throws SQLException { - return null; + return (ServiceInputStream) ProxyFactory.getProxy(ServiceInputStream.class, info); } @Override @@ -233,12 +234,12 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public Reader getCharacterStream(int columnIndex) throws SQLException { - return null; + return (Reader) ProxyFactory.getProxy(ServiceReader.class, info); } @Override public Reader getCharacterStream(String columnLabel) throws SQLException { - return null; + return (Reader) ProxyFactory.getProxy(ServiceReader.class, info); } @Override @@ -598,17 +599,23 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public Blob getBlob(int columnIndex) throws SQLException { - return null; + ServiceBlob blob = (ServiceBlob) ProxyFactory.getProxy(ServiceBlob.class, info); + blob.setInfo(info); + return blob; } @Override public Clob getClob(int columnIndex) throws SQLException { - return null; + ServiceClob clob = (ServiceClob) ProxyFactory.getProxy(ServiceClob.class, info); + clob.setInfo(info); + return clob; } @Override public Array getArray(int columnIndex) throws SQLException { - return null; + ServiceArray array = (ServiceArray) ProxyFactory.getProxy(ServiceArray.class, info); + array.setInfo(info); + return array; } @Override @@ -623,17 +630,23 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public Blob getBlob(String columnLabel) throws SQLException { - return null; + ServiceBlob blob = (ServiceBlob) ProxyFactory.getProxy(ServiceBlob.class, info); + blob.setInfo(info); + return blob; } @Override public Clob getClob(String columnLabel) throws SQLException { - return null; + ServiceClob clob = (ServiceClob) ProxyFactory.getProxy(ServiceClob.class, info); + clob.setInfo(info); + return clob; } @Override public Array getArray(String columnLabel) throws SQLException { - return null; + ServiceArray array = (ServiceArray) ProxyFactory.getProxy(ServiceArray.class, info); + array.setInfo(info); + return array; } @Override @@ -808,12 +821,12 @@ public class ServiceResultSet extends BasedBind implements ResultSet { @Override public Reader getNCharacterStream(int columnIndex) throws SQLException { - return null; + return (Reader) ProxyFactory.getProxy(Reader.class, info); } @Override public Reader getNCharacterStream(String columnLabel) throws SQLException { - return null; + return (Reader) ProxyFactory.getProxy(Reader.class, info); } @Override @@ -967,8 +980,10 @@ public class ServiceResultSet extends BasedBind implements ResultSet { } @Override + @LocalMethod + @NotImplemented public T unwrap(Class iface) throws SQLException { - return null; + throw new SQLException("Not Implemented!"); } @Override diff --git a/test/src/test/java/com/fanruan/ConnectionTest.java b/test/src/test/java/com/fanruan/ConnectionTest.java index a4707fc..00b9216 100644 --- a/test/src/test/java/com/fanruan/ConnectionTest.java +++ b/test/src/test/java/com/fanruan/ConnectionTest.java @@ -311,4 +311,10 @@ public class ConnectionTest extends BaseJDBCTest{ void testGetMetaData() throws SQLException { DatabaseMetaData metaData = connection.getMetaData(); } + + @Test + void testCreate() throws SQLException{ + Assertions.assertNotNull(connection.createClob()); + + } } diff --git a/test/src/test/java/com/fanruan/ResultSetTest.java b/test/src/test/java/com/fanruan/ResultSetTest.java index 4ed89fe..378c8c4 100644 --- a/test/src/test/java/com/fanruan/ResultSetTest.java +++ b/test/src/test/java/com/fanruan/ResultSetTest.java @@ -4,17 +4,23 @@ import com.fanruan.cache.BeanCacheImpl; import com.fanruan.handler.DispatcherImpl; import com.fanruan.pojo.message.RpcRequest; import com.fanruan.service.jdbc.AbstractBind; +import com.fanruan.service.jdbc.ServiceBlob; +import com.fanruan.service.jdbc.ServiceReader; +import com.fanruan.service.jdbc.resultset.ServiceResultSet; import com.fanruan.service.jdbc.statement.ServiceStatement; +import org.hsqldb.jdbc.JDBCBlob; +import org.hsqldb.jdbc.JDBCClob; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; import java.net.URL; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; +import java.sql.*; /** * @author Yichen Dai @@ -24,11 +30,17 @@ import java.sql.Statement; public class ResultSetTest extends BaseJDBCTest{ private Connection connection = null; + ResultSet resultSet = null; @BeforeAll public void setUp() throws SQLException { openSocket(); connection = getConnection(); + + } + + @Test + public void testDate() throws SQLException{ Statement statement = connection.createStatement(); statement.execute("create table DemoTable\n" + " (\n" + @@ -40,12 +52,8 @@ public class ResultSetTest extends BaseJDBCTest{ statement.executeUpdate("insert into DEMOTABLE(TESTTIME,TESTDATE,TESTSTAMP) " + "values('15:50:37', '2022-09-07', '2022-09-07 15:50:37');"); - } - @Test - public void testDate() throws SQLException{ - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery("select TestTime, TestDate, TestStamp from DemoTable;"); + this.resultSet = statement.executeQuery("select TestTime, TestDate, TestStamp from DemoTable;"); while(resultSet.next()){ Assertions.assertEquals("15:50:37", resultSet.getTime(1).toString()); @@ -53,5 +61,115 @@ public class ResultSetTest extends BaseJDBCTest{ Assertions.assertEquals("2022-09-07 15:50:37.0", resultSet.getTimestamp(3).toString()); } + Assertions.assertFalse(resultSet.isClosed()); + } + + @Test + public void testGet() throws SQLException, IOException { + Statement statement = connection.createStatement(); + + statement.execute("create table TestTable " + + " (" + + " testString varchar(20), " + + " testBoolean BOOLEAN, " + + " testByte NUMERIC(3), " + + " testShort NUMERIC(5), " + + " testInt INTEGER, " + + " testLong BIGINT, " + + " testFloat FLOAT, " + + " testDouble DOUBLE, " + + " testDecimal DECIMAL," + + " testBlob BLOB(1024)," + + " testClob varchar(100));" + ); + + PreparedStatement prepareStatement = connection.prepareStatement("INSERT INTO TestTable VALUES( " + + "?, " + + "?," + + "?," + + "?," + + "?," + + "?," + + "?, " + + "?, " + + "?," + + "?," + + "?);"); + + prepareStatement.setString(1, "testString"); + prepareStatement.setBoolean(2, true); + prepareStatement.setByte(3, Byte.MAX_VALUE); + prepareStatement.setShort(4, Short.MAX_VALUE); + prepareStatement.setInt(5, Integer.MAX_VALUE); + prepareStatement.setLong(6, Long.MAX_VALUE); + prepareStatement.setFloat(7, 0.2f); + prepareStatement.setDouble(8, 0.2D); + prepareStatement.setBigDecimal(9, new BigDecimal(1000)); + + byte[] chuck = { + (byte)0x0f, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00 + }; + + Blob blob = new JDBCBlob(chuck); + + prepareStatement.setBlob(10, blob); + prepareStatement.setClob(11, new JDBCClob("abcd")); + prepareStatement.executeUpdate(); + + ResultSet resultSet = statement.executeQuery("SELECT * FROM TestTable;"); + + resultSet.next(); + Assertions.assertEquals("testString", resultSet.getString(1)); + Assertions.assertEquals("testString", resultSet.getString("testString")); + Assertions.assertEquals(true, resultSet.getBoolean(2)); + Assertions.assertEquals(true, resultSet.getBoolean("testBoolean")); + Assertions.assertEquals(Byte.MAX_VALUE, resultSet.getByte(3)); + Assertions.assertEquals(Byte.MAX_VALUE, resultSet.getByte("testByte")); + Assertions.assertEquals(Short.MAX_VALUE, resultSet.getShort(4)); + Assertions.assertEquals(Short.MAX_VALUE, resultSet.getShort("testShort")); + Assertions.assertEquals(Integer.MAX_VALUE, resultSet.getInt(5)); + Assertions.assertEquals(Integer.MAX_VALUE, resultSet.getInt("testInt")); + Assertions.assertEquals(Long.MAX_VALUE, resultSet.getLong(6)); + Assertions.assertEquals(Long.MAX_VALUE, resultSet.getLong("testLong")); + Assertions.assertEquals(0.2f, resultSet.getFloat(7)); + Assertions.assertEquals(0.2f, resultSet.getFloat("testFloat")); + Assertions.assertEquals(0.2d, resultSet.getDouble(8)); + Assertions.assertEquals(0.2d, resultSet.getDouble("testDouble")); + + Assertions.assertEquals(1000, resultSet.getBigDecimal(9).intValue()); + Assertions.assertEquals(1000, resultSet.getBigDecimal("testDecimal").intValue()); + + + Assertions.assertEquals(chuck.length, resultSet.getBytes(10).length); + Assertions.assertEquals(chuck.length, resultSet.getBytes("testBlob").length); + + + Assertions.assertEquals(chuck[0], resultSet.getBinaryStream("testBlob").read()); + Assertions.assertEquals(chuck[0], resultSet.getBinaryStream("testBlob").read()); + + Assertions.assertEquals('a', resultSet.getAsciiStream(11).read()); + Assertions.assertEquals('a', resultSet.getAsciiStream("testClob").read()); + Assertions.assertEquals('a', resultSet.getCharacterStream(11).read()); + Assertions.assertEquals('a', resultSet.getCharacterStream("testClob").read()); + + + Assertions.assertNull(resultSet.getCursorName()); + Assertions.assertNotNull(resultSet.getMetaData()); + } + + @Test + public void testWrap() throws SQLException { + String SQL_INSERT = "INSERT INTO EMPLOYEE VALUES 'Tim';"; + + String SQL_CREATE = "CREATE TABLE EMPLOYEE (NAME varchar(100));"; + + Statement statement = connection.createStatement(); + statement.execute(SQL_CREATE); + statement.executeUpdate(SQL_INSERT); + ResultSet resultSet = statement.executeQuery("select * from EMPLOYEE"); + + Assertions.assertThrows(SQLException.class, () -> resultSet.unwrap(null)); + Assertions.assertFalse(resultSet.isWrapperFor(null)); } }