由于最近的工作需要,需要对jdbc的数据库连接的内部逻辑做研究,在此将研究过程中的一些关键函数的内容在此以日志的形式保存下来,以便后续继续完善。
1、一段字符串获取它的UTF8的字节长度函数:
private static int stringUTF8Length(char ac[]) { int i = 0; int j = ac.length; for(int k = 0; k < j; k++) { char c = ac[k]; if(c >= 0 && c <= '\177') i++; else if(c >= '\200' && c <= '\u07FF') i += 2; else i += 3; } return i; }
2、java中的字节数组转换成Utf8格式的字节:
3、 DriverManager.getConnection(url,"system","****")的内部逻辑如下:
private static byte[] javaCharsToUtf8Bytes(char ac[]) { int k = ac.length; int l = stringUTF8Length(ac); byte abyte0[] = new byte[l]; int i = 0; int j = 0; for(; i < k; i++) { char c = ac[i]; if((c & 0xff80) == 0) abyte0[j++] = (byte)c; else if((c & 0xf800) == 0) { abyte0[j++] = (byte)(0xc0 | c >> 6 & 0x1f); abyte0[j++] = (byte)(0x80 | c & 0x3f); } else { abyte0[j++] = (byte)(0xe0 | c >> 12 & 0xf); abyte0[j++] = (byte)(0x80 | c >> 6 & 0x3f); abyte0[j++] = (byte)(0x80 | c & 0x3f); } } return abyte0; }
首先调用了如下的方法返回了一个连接:
public Connection connect(String s, Properties properties) throws SQLException { if(s.regionMatches(0, "jdbc:default:connection", 0, 23)) { String s1 = "jdbc:oracle:kprb"; int j = s.length(); if(j > 23) s = s1.concat(s.substring(23, s.length())); else s = s1.concat(":"); s1 = null; } int i = oracleAcceptsURL(s); if(i == 1) return null; if(i == 2) { DBError.throwSqlException(67); return null; } Hashtable hashtable = parseUrl(s); if(hashtable == null) return null; String s2 = properties.getProperty("user"); String s3 = properties.getProperty("password"); String s4 = properties.getProperty("database"); if(s4 == null) s4 = properties.getProperty("server"); if(s2 == null) s2 = (String)hashtable.get("user"); s2 = parseLoginOption(s2, properties); if(s3 == null) s3 = (String)hashtable.get("password"); if(s4 == null) s4 = (String)hashtable.get("database"); String s5 = (String)hashtable.get("protocol"); properties.put("protocol", s5); if(s5 == null) { DBError.throwSqlException(40, "Protocol is not specified in URL"); return null; } String s6 = properties.getProperty("dll"); if(s6 == null) properties.put("dll", "ocijdbc9"); String s7 = properties.getProperty("prefetch"); if(s7 == null) s7 = properties.getProperty("rowPrefetch"); if(s7 == null) s7 = properties.getProperty("defaultRowPrefetch"); if(s7 != null && Integer.parseInt(s7) <= 0) s7 = null; String s8 = properties.getProperty("batch"); if(s8 == null) s8 = properties.getProperty("executeBatch"); if(s8 == null) s8 = properties.getProperty("defaultExecuteBatch"); if(s8 != null && Integer.parseInt(s8) <= 0) s8 = null; String s9 = properties.getProperty("remarks"); if(s9 == null) s9 = properties.getProperty("remarksReporting"); String s10 = properties.getProperty("synonyms"); if(s10 == null) s10 = properties.getProperty("includeSynonyms"); String s11 = properties.getProperty("restrictGetTables"); String s12 = properties.getProperty("fixedString"); String s13 = properties.getProperty("dataSizeUnits"); String s14 = properties.getProperty("AccumulateBatchResult"); if(s14 == null) s14 = "true"; Enumeration enumeration; for(enumeration = DriverManager.getDrivers(); enumeration.hasMoreElements();) { Driver driver = (Driver)enumeration.nextElement(); if(driver instanceof OracleDriver) break; } while(enumeration.hasMoreElements()) { Driver driver1 = (Driver)enumeration.nextElement(); if(driver1 instanceof OracleDriver) DriverManager.deregisterDriver(driver1); } Connection connection = getConnectionInstance(s5, s, s2, s3, s4, properties); if(s7 != null) ((oracle.jdbc.driver.OracleConnection)connection).setDefaultRowPrefetch(Integer.parseInt(s7)); if(s8 != null) ((oracle.jdbc.driver.OracleConnection)connection).setDefaultExecuteBatch(Integer.parseInt(s8)); if(s9 != null) ((oracle.jdbc.driver.OracleConnection)connection).setRemarksReporting(s9.equalsIgnoreCase("true")); if(s10 != null) ((oracle.jdbc.driver.OracleConnection)connection).setIncludeSynonyms(s10.equalsIgnoreCase("true")); if(s11 != null) ((oracle.jdbc.driver.OracleConnection)connection).setRestrictGetTables(s11.equalsIgnoreCase("true")); if(s12 != null) ((oracle.jdbc.driver.OracleConnection)connection).setDefaultFixedString(s12.equalsIgnoreCase("true")); if(s13 != null) ((oracle.jdbc.driver.OracleConnection)connection).setDataSizeUnits(s13); ((oracle.jdbc.driver.OracleConnection)connection).setAccumulateBatchResult(s14.equalsIgnoreCase("true")); hashtable = null; return connection; }
- 在logon中设置了Oall7等参数:
- MEngine是在上面的connect(s2, properties)中初始化的
public synchronized DBConversion logon(String s, String s1, String s2, Properties properties) throws SQLException, IOException { try { if(state > 0) DBError.check_error(428); if(s == null || s1 == null) DBError.check_error(433); if(s.length() == 0 || s1.length() == 0) DBError.check_error(443); if(s2 == null) s2 = "localhost:1521:orcl"; <span style="color:#ff0000;"> connect(s2, properties); all7 = new Oall7(MEngine);</span> commoncall = new Ocommoncall(MEngine); opencall = new Oopen(MEngine); close = new Oclose(MEngine); TTCTypeRep _tmp = MEngine.types; describe = (Odscrarr)MEngine.types.newTTIFunObject((byte)1, MEngine); bfileMsg = new v8TTIBfile(MEngine); blobMsg = new v8TTIBlob(MEngine);
- 39行的connectpacket.send()将数据库的连接字符串发送给服务器:
public void connect(String s, Properties properties) throws IOException, NetException { if(sAtts.connected) throw new NetException(201); if(s == null) throw new NetException(208); addrRes = new AddrResolution(s, properties); if(addrRes.connection_revised) { s = addrRes.getTNSAddress(); properties = addrRes.getUp(); } if(addrRes.jndi) sAtts.profile = new ClientProfile(properties, addrRes.getJndi()); else sAtts.profile = new ClientProfile(properties); establishConnection(s); Object obj4 = null; try { obj4 = Class.forName("oracle.net.ano.Ano").newInstance(); sAtts.anoEnabled = true; } catch(Exception _ex) { sAtts.anoEnabled = false; } if(obj4 != null) { ((Ano)obj4).init(sAtts); sAtts.ano = (Ano)obj4; sAtts.anoEnabled = true; } label0: do { ConnectPacket connectpacket = new ConnectPacket(sAtts); connectpacket.send(); packet = new Packet(sAtts); packet.receive(); switch(packet.type) { case 2: // '\002' AcceptPacket acceptpacket = new AcceptPacket(packet); break label0; case 11: // '\013' break; case 5: // '\005' RedirectPacket redirectpacket = new RedirectPacket(packet); sAtts.cOption.nt.disconnect(); sAtts = establishConnection(redirectpacket.getData()); break; case 4: // '\004' RefusePacket refusepacket = new RefusePacket(packet); throw new NetException(206, refusepacket.getData()); case 3: // '\003' case 6: // '\006' case 7: // '\007' case 8: // '\b' case 9: // '\t' case 10: // '\n' default: sAtts.cOption.nt.disconnect(); throw new NetException(205); } } while(true); setNetStreams(); sAtts.connected = true; if(sAtts.ano != null) sAtts.ano.negotiation(); packet = null; Object obj = null; Object obj1 = null; Object obj3 = null; Object obj2 = null; }