diff --git a/src/com/wentch/redkale/convert/ObjectDecoder.java b/src/com/wentch/redkale/convert/ObjectDecoder.java index 072ee8c46..6d41324fb 100644 --- a/src/com/wentch/redkale/convert/ObjectDecoder.java +++ b/src/com/wentch/redkale/convert/ObjectDecoder.java @@ -5,7 +5,6 @@ */ package com.wentch.redkale.convert; - import static com.wentch.redkale.convert.ObjectEncoder.TYPEZERO; import com.wentch.redkale.util.Creator; import java.lang.reflect.*; @@ -34,7 +33,7 @@ public final class ObjectDecoder implements Decodeable= CHANGE_CIPHER_SPECT_CONTENT_TYPE && byte0 <= APPLICATION_DATA_CONTENT_TYPE) { + if (byte0 >= 20 && byte0 <= 23) { /* * Last sanity check that it's not a wild record */ @@ -99,14 +111,14 @@ public class SSLBuilder { // Check if too old (currently not possible) // or if the major version does not match. // The actual version negotiation is in the handshaker classes - if ((v < MIN_VERSION) || (major > MAX_MAJOR_VERSION)) { + if ((v < 0x0300) || (major > 0x03)) { throw new SSLException("Unsupported record version major=" + major + " minor=" + minor); } /* * One of the SSLv3/TLS message types. */ - len = ((byte3 & 0xff) << 8) + (byte4 & 0xff) + SSLV3_RECORD_HEADER_SIZE; + len = ((byte3 & 0xff) << 8) + (byte4 & 0xff) + 5; // SSLv3 record header } else { /* @@ -127,10 +139,9 @@ public class SSLBuilder { // Check if too old (currently not possible) // or if the major version does not match. // The actual version negotiation is in the handshaker classes - if ((v < MIN_VERSION) || (major > MAX_MAJOR_VERSION)) { + if ((v < 0x0300) || (major > 0x03)) { // if it's not SSLv2, we're out of here. - if (v != SSL20_HELLO_VERSION) throw new SSLException("Unsupported record version major=" + major + " minor=" + minor); - + if (v != 0x0002) throw new SSLException("Unsupported record version major=" + major + " minor=" + minor); } /* diff --git a/src/com/wentch/redkale/net/http/HttpRequest.java b/src/com/wentch/redkale/net/http/HttpRequest.java index f3f534ce1..458ba1a4a 100644 --- a/src/com/wentch/redkale/net/http/HttpRequest.java +++ b/src/com/wentch/redkale/net/http/HttpRequest.java @@ -229,7 +229,10 @@ public final class HttpRequest extends Request { String val = getHeader(remoteAddrHeader); if (val != null) return val; } - return String.valueOf(getRemoteAddress()); + SocketAddress addr = getRemoteAddress(); + if (addr == null) return ""; + if (addr instanceof InetSocketAddress) return ((InetSocketAddress) addr).getAddress().getHostAddress(); + return String.valueOf(addr); } public SocketAddress getRemoteAddress() { @@ -376,6 +379,10 @@ public final class HttpRequest extends Request { } //------------------------------------------------------------------------------ + public String[] getHeaderNames() { + return header.getNames(); + } + public String getHeader(String name) { return header.getValue(name); } @@ -414,6 +421,11 @@ public final class HttpRequest extends Request { } //------------------------------------------------------------------------------ + public String[] getParameterNames() { + parseBody(); + return params.getNames(); + } + public String getParameter(String name) { parseBody(); return params.getValue(name); diff --git a/src/com/wentch/redkale/source/DataJDBCSource.java b/src/com/wentch/redkale/source/DataJDBCSource.java index 49a918836..807ee6208 100644 --- a/src/com/wentch/redkale/source/DataJDBCSource.java +++ b/src/com/wentch/redkale/source/DataJDBCSource.java @@ -1048,6 +1048,16 @@ public final class DataJDBCSource implements DataSource { return getSingleResult(ReckonType.COUNT, entityClass, null, bean); } + @Override + public Number getCountDistinctSingleResult(final Class entityClass, String column) { + return getCountDistinctSingleResult(entityClass, column, null); + } + + @Override + public Number getCountDistinctSingleResult(final Class entityClass, String column, FilterBean bean) { + return getSingleResult(ReckonType.COUNT, entityClass, true, column, bean); + } + //-----------------------------AVG----------------------------- @Override public Number getAvgSingleResult(final Class entityClass, final String column) { @@ -1060,11 +1070,15 @@ public final class DataJDBCSource implements DataSource { } private Number getSingleResult(final ReckonType type, final Class entityClass, final String column, FilterBean bean) { + return getSingleResult(type, entityClass, false, column, bean); + } + + private Number getSingleResult(final ReckonType type, final Class entityClass, final boolean distinct, final String column, FilterBean bean) { final Connection conn = createReadSQLConnection(); try { final EntityXInfo info = EntityXInfo.load(this, entityClass); - final String sql = "SELECT " + type.getReckonColumn("a." + column) + " FROM " + info.getTable() + " a" + createWhereExpression(info, null, bean); - if (debug.get()) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); + final String sql = "SELECT " + type.getReckonColumn((distinct ? "DISTINCT " : "") + "a." + column) + " FROM " + info.getTable() + " a" + createWhereExpression(info, null, bean); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); final PreparedStatement prestmt = conn.prepareStatement(sql); Number rs = null; ResultSet set = prestmt.executeQuery(); @@ -1104,7 +1118,7 @@ public final class DataJDBCSource implements DataSource { } final Connection conn = createReadSQLConnection(); try { - if (debug.get()) logger.finest(clazz.getSimpleName() + " find sql=" + info.query.sql.replace("?", String.valueOf(pk))); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + info.query.sql.replace("?", String.valueOf(pk))); final PreparedStatement prestmt = conn.prepareStatement(info.query.sql); prestmt.setObject(1, pk); T rs = null; @@ -1178,7 +1192,7 @@ public final class DataJDBCSource implements DataSource { final Connection conn = createReadSQLConnection(); try { final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column1) + " = ? AND " + info.getSQLColumn(column2) + " = ?"; - if (debug.get()) logger.finest(clazz.getSimpleName() + " find sql=" + sql.replaceFirst("\\?", String.valueOf(key1)).replaceFirst("\\?", String.valueOf(key2))); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + sql.replaceFirst("\\?", String.valueOf(key1)).replaceFirst("\\?", String.valueOf(key2))); final PreparedStatement prestmt = conn.prepareStatement(sql); prestmt.setObject(1, key1); prestmt.setObject(2, key2); @@ -1269,7 +1283,7 @@ public final class DataJDBCSource implements DataSource { final Connection conn = createReadSQLConnection(); try { final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + sqlcolumn + " = ?"; - if (debug.get()) logger.finest(clazz.getSimpleName() + " query sql=" + sql); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql); final PreparedStatement prestmt = conn.prepareStatement(sql); T[] rs = (T[]) Array.newInstance(clazz, keys.length); for (int i = 0; i < keys.length; i++) { @@ -1327,7 +1341,7 @@ public final class DataJDBCSource implements DataSource { try { final List list = new ArrayList(); final String sql = "SELECT " + info.getSQLColumn(selectedColumn) + " FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column) + " = ?"; - if (debug.get()) logger.finest(clazz.getSimpleName() + " query sql=" + sql.replaceFirst("\\?", String.valueOf(key))); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql.replaceFirst("\\?", String.valueOf(key))); final PreparedStatement ps = conn.prepareStatement(sql); ps.setObject(1, key); final ResultSet set = ps.executeQuery(); @@ -1451,7 +1465,7 @@ public final class DataJDBCSource implements DataSource { final SelectColumn sels = selects; final List list = new ArrayList(); final String sql = "SELECT * FROM " + info.getTable() + " WHERE " + info.getSQLColumn(column) + " " + express.value() + " ?"; - if (debug.get()) logger.finest(clazz.getSimpleName() + " query sql=" + sql); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql); final PreparedStatement ps = conn.prepareStatement(sql); ps.setObject(1, key); final ResultSet set = ps.executeQuery(); @@ -1550,7 +1564,7 @@ public final class DataJDBCSource implements DataSource { final SelectColumn sels = selects; final List list = new ArrayList(); final String sql = "SELECT a.* FROM " + info.getTable() + " a" + createWhereExpression(info, flipper, bean); - if (debug.get()) logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize()))); + if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize()))); final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); final ResultSet set = ps.executeQuery(); if (flipper != null && flipper.index() > 0) set.absolute(flipper.index()); @@ -1914,6 +1928,8 @@ public final class DataJDBCSource implements DataSource { //表字段与字段名是否全部一致 private final boolean same; + private final int logLevel; + private class ActionInfo { final String sql; @@ -1937,6 +1953,9 @@ public final class DataJDBCSource implements DataSource { DistributeTables dt = type.getAnnotation(DistributeTables.class); this.distributeTables = dt == null ? null : dt.value(); + LogLevel ll = type.getAnnotation(LogLevel.class); + this.logLevel = ll == null ? Integer.MIN_VALUE : Level.parse(ll.value()).intValue(); + Class cltmp = type; Set fields = new HashSet<>(); boolean auto = false; @@ -2037,6 +2056,10 @@ public final class DataJDBCSource implements DataSource { } } + public boolean isLoggable(Level l) { + return l.intValue() >= this.logLevel; + } + public T createInstance() { return inner.getCreator().create(); } @@ -2086,7 +2109,7 @@ public final class DataJDBCSource implements DataSource { MAX, MIN, SUM, COUNT, AVG; public String getReckonColumn(String col) { - if (this == COUNT) return this.name() + "(*)"; + if (this == COUNT && !col.contains("DISTINCT")) return this.name() + "(*)"; return this.name() + "(" + col + ")"; } } diff --git a/src/com/wentch/redkale/source/DataJPASource.java b/src/com/wentch/redkale/source/DataJPASource.java index 096071e2b..d7ac29d71 100644 --- a/src/com/wentch/redkale/source/DataJPASource.java +++ b/src/com/wentch/redkale/source/DataJPASource.java @@ -49,6 +49,16 @@ final class DataJPASource implements DataSource { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } + @Override + public Number getCountDistinctSingleResult(Class entityClass, String column) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public Number getCountDistinctSingleResult(Class entityClass, String column, FilterBean bean) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + private static class DataJPAConnection extends DataConnection { private final EntityManager manager; diff --git a/src/com/wentch/redkale/source/DataSource.java b/src/com/wentch/redkale/source/DataSource.java index 40f14392e..ced5c3f4d 100644 --- a/src/com/wentch/redkale/source/DataSource.java +++ b/src/com/wentch/redkale/source/DataSource.java @@ -243,6 +243,10 @@ public interface DataSource { public Number getCountSingleResult(final Class entityClass, FilterBean bean); + public Number getCountDistinctSingleResult(final Class entityClass, String column); + + public Number getCountDistinctSingleResult(final Class entityClass, String column, FilterBean bean); + //-----------------------------AVG----------------------------- public Number getAvgSingleResult(final Class entityClass, final String column); diff --git a/src/com/wentch/redkale/source/FilterInfo.java b/src/com/wentch/redkale/source/FilterInfo.java index 8a454e46f..98c2708be 100644 --- a/src/com/wentch/redkale/source/FilterInfo.java +++ b/src/com/wentch/redkale/source/FilterInfo.java @@ -73,8 +73,10 @@ final class FilterInfo { fields.add(field.getName()); FilterItem item = new FilterItem(field, "a", null); FilterJoinColumn joinCol = field.getAnnotation(FilterJoinColumn.class); + boolean again = true; if (joinCol != null) { if (!joinTables.containsKey(joinCol.table())) { + again = false; joinTables.put(joinCol.table(), String.valueOf((char) ('a' + (++index)))); } String alias = joinTables.get(joinCol.table()); @@ -87,9 +89,11 @@ final class FilterInfo { } item = new FilterItem(field, alias, cache); EntityInfo secinfo = EntityInfo.load(joinCol.table(), null); - joinsb.append(" ").append(joinCol.type().name()).append(" JOIN ").append(secinfo.getTable()).append(" ").append(alias) - .append(" ON a.# = ").append(alias).append(".") - .append(joinCol.column().isEmpty() ? secinfo.getPrimary().field() : joinCol.column()); + if (!again) { + joinsb.append(" ").append(joinCol.type().name()).append(" JOIN ").append(secinfo.getTable()) + .append(" ").append(alias).append(" ON a.# = ").append(alias).append(".") + .append(joinCol.column().isEmpty() ? secinfo.getPrimary().field() : joinCol.column()); + } } getters.put(field.getName(), item); FilterGroup[] refs = field.getAnnotationsByType(FilterGroup.class); diff --git a/src/com/wentch/redkale/util/LogLevel.java b/src/com/wentch/redkale/util/LogLevel.java new file mode 100644 index 000000000..f5e675530 --- /dev/null +++ b/src/com/wentch/redkale/util/LogLevel.java @@ -0,0 +1,24 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.util; + +import java.lang.annotation.*; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * 被标记的日志级别以上的才会被记录 + * + * @author zhangjx + */ +@Inherited +@Documented +@Target({TYPE}) +@Retention(RUNTIME) +public @interface LogLevel { + + String value(); +}