diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java index 1858474a8..b8b208ea0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataService.java @@ -9,12 +9,16 @@ import org.mifosng.platform.api.data.GenericResultsetData; public interface GenericDataService { - public CachedRowSet getCachedResultSet(String sql, String errorMsg); + CachedRowSet getCachedResultSet(String sql, String errorMsg); + + void updateSQL(String sql, String sqlErrorMsg); GenericResultsetData fillGenericResultSet(final String sql); String replace(String str, String pattern, String replace); + String wrapSQL(String sql); + void dbClose(Statement db_statement, Connection db_connection); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java index 23ec3cf04..023f3dd69 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/GenericDataServiceImpl.java @@ -40,17 +40,19 @@ public class GenericDataServiceImpl implements GenericDataService { @Override public CachedRowSet getCachedResultSet(String sql, String sqlErrorMsg) { + long startTime = System.currentTimeMillis(); Connection db_connection = null; Statement db_statement = null; + CachedRowSet crs = null; try { db_connection = dataSource.getConnection(); db_statement = db_connection.createStatement(); ResultSet rs = db_statement.executeQuery(sql); + crs = new CachedRowSetImpl(); - CachedRowSet crs = new CachedRowSetImpl(); crs.populate(rs); - //logger.info("RS Size: " + crs.size() + " getCachedResultSet sql: " + sql); - return crs; + // logger.info("RS Size: " + crs.size() + + // " getCachedResultSet sql: " + sql); } catch (SQLException e) { throw new PlatformDataIntegrityException("error.msg.sql.error", e.getMessage(), sqlErrorMsg); @@ -59,6 +61,30 @@ public class GenericDataServiceImpl implements GenericDataService { } + long elapsed = System.currentTimeMillis() - startTime; + logger.info("Elapsed Time: " + elapsed + " SQL: " + sql); + return crs; + } + + @Override + public void updateSQL(String sql, String sqlErrorMsg) { + + long startTime = System.currentTimeMillis(); + Connection db_connection = null; + Statement db_statement = null; + try { + db_connection = dataSource.getConnection(); + db_statement = db_connection.createStatement(); + db_statement.executeUpdate(sql); + } catch (SQLException e) { + throw new PlatformDataIntegrityException("error.msg.sql.error", + e.getMessage(), sqlErrorMsg); + } finally { + dbClose(db_statement, db_connection); + } + + long elapsed = System.currentTimeMillis() - startTime; + logger.info("Elapsed Time FOR UPDATE: " + elapsed + " SQL: " + sql); } @Override @@ -120,6 +146,17 @@ public class GenericDataServiceImpl implements GenericDataService { return result.toString(); } + @Override + public String wrapSQL(String sql) { + // wrap sql to prevent JDBC sql errors, prevent malicious sql and a + // CachedRowSetImpl bug + + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7046875 - prevent + // Invalid Column Name bug in sun's CachedRowSetImpl where it doesn't + // pick up on label names, only column names + return "select x.* from (" + sql + ") x"; + } + @Override public void dbClose(Statement db_statement, Connection db_connection) { logger.debug("dbClose"); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadReportingServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadReportingServiceImpl.java index 899b44759..b1c9e903b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadReportingServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadReportingServiceImpl.java @@ -209,27 +209,17 @@ public class ReadReportingServiceImpl implements ReadReportingService { sql = genericDataService.replace(sql, "${currentUserId}", currentUser .getId().toString()); - sql = wrapSQL(sql); + sql = genericDataService.wrapSQL(sql); return sql; } - private String wrapSQL(String sql) { - // wrap sql to prevent JDBC sql errors, prevent malicious sql and a - // CachedRowSetImpl bug - - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7046875 - prevent - // Invalid Column Name bug in sun's CachedRowSetImpl where it doesn't - // pick up on label names, only column names - return "select x.* from (" + sql + ") x"; - } - private String getSql(String name, String type) { String inputSql = "select " + type + "_sql as the_sql from stretchy_" + type + " where " + type + "_name = '" + name + "'"; - inputSql = wrapSQL(inputSql); + inputSql = genericDataService.wrapSQL(inputSql); String sqlErrorMsg = "Sql: " + inputSql; CachedRowSet rs = genericDataService.getCachedResultSet(inputSql, @@ -254,7 +244,7 @@ public class ReadReportingServiceImpl implements ReadReportingService { String sql = "SELECT ifnull(report_type,'') as report_type FROM `stretchy_report` where report_name = '" + reportName + "'"; - sql = wrapSQL(sql); + sql = genericDataService.wrapSQL(sql); String sqlErrorMsg = "Report Name: " + reportName + " Sql: " + sql; CachedRowSet rs = genericDataService.getCachedResultSet(sql, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java index cce277fda..f5f0416b1 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/noncore/ReadWriteNonCoreDataServiceImpl.java @@ -1,15 +1,11 @@ package org.mifosng.platform.noncore; -import java.sql.Connection; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; -import javax.sql.DataSource; import javax.sql.rowset.CachedRowSet; import org.mifosng.platform.api.data.AdditionalFieldsSetData; @@ -18,7 +14,6 @@ import org.mifosng.platform.api.data.ResultsetColumnHeader; import org.mifosng.platform.api.data.ResultsetDataRow; import org.mifosng.platform.exceptions.AdditionalFieldsNotFoundException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException; -import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.user.domain.AppUser; import org.slf4j.Logger; @@ -35,15 +30,9 @@ public class ReadWriteNonCoreDataServiceImpl implements private final static Logger logger = LoggerFactory .getLogger(ReadWriteNonCoreDataServiceImpl.class); - private final DataSource dataSource; - @Autowired - public ReadWriteNonCoreDataServiceImpl( - final PlatformSecurityContext context, - final TenantAwareRoutingDataSource dataSource) { - + public ReadWriteNonCoreDataServiceImpl(final PlatformSecurityContext context) { this.context = context; - this.dataSource = dataSource; } @Autowired @@ -52,36 +41,36 @@ public class ReadWriteNonCoreDataServiceImpl implements @Override public List retrieveExtraDatasetNames(String type) { + long startTime = System.currentTimeMillis(); List additionalFieldsSets = new ArrayList(); - Connection db_connection = null; - Statement db_statement = null; + String andClause; + if (type == null) { + andClause = ""; + } else { + andClause = " and t.`name` = '" + type + "'"; + } + // PERMITTED ADDITIONAL FIELDS datasets + String sql = "select d.id, d.`name` as 'set', t.`name` as 'type' " + + " from stretchydata_dataset d join stretchydata_datasettype t on t.id = d.datasettype_id " + + " where exists" + + " (select 'f'" + + " from m_appuser_role ur " + + " join m_role r on r.id = ur.role_id" + + " left join m_role_permission rp on rp.role_id = r.id" + + " left join m_permission p on p.id = rp.permission_id" + + " where ur.appuser_id = " + + context.authenticatedUser().getId() + + " and (r.name = 'Super User' or r.name = 'Read Only') or p.code = concat('CAN_READ_', t.`name`, '_x', d.`name`)) " + + andClause + " order by d.`name`"; + + sql = genericDataService.wrapSQL(sql); + String sqlErrorMsg = "Additional Fields Type: " + type + " sql: " + + sql; + CachedRowSet rs = genericDataService.getCachedResultSet(sql, + sqlErrorMsg); + try { - db_connection = dataSource.getConnection(); - db_statement = db_connection.createStatement(); - - String andClause; - if (type == null) { - andClause = ""; - } else { - andClause = " and t.`name` = '" + type + "'"; - } - // PERMITTED ADDITIONAL FIELDS datasets - String sql = "select d.id, d.`name` as 'set', t.`name` as 'type' " - + " from stretchydata_dataset d join stretchydata_datasettype t on t.id = d.datasettype_id " - + " where exists" - + " (select 'f'" - + " from m_appuser_role ur " - + " join m_role r on r.id = ur.role_id" - + " left join m_role_permission rp on rp.role_id = r.id" - + " left join m_permission p on p.id = rp.permission_id" - + " where ur.appuser_id = " - + context.authenticatedUser().getId() - + " and (r.name = 'Super User' or r.name = 'Read Only') or p.code = concat('CAN_READ_', t.`name`, '_x', d.`name`)) " - + andClause + " order by d.`name`"; - - ResultSet rs = db_statement.executeQuery(sql); - while (rs.next()) { additionalFieldsSets.add(new AdditionalFieldsSetData(rs .getInt("id"), rs.getString("set"), rs @@ -90,11 +79,13 @@ public class ReadWriteNonCoreDataServiceImpl implements } catch (SQLException e) { throw new PlatformDataIntegrityException("error.msg.sql.error", - e.getMessage(), "Additional Fields Type: " + type); - } finally { - genericDataService.dbClose(db_statement, db_connection); + e.getMessage(), sqlErrorMsg); } + long elapsed = System.currentTimeMillis() - startTime; + logger.info("FINISHING retrieveExtraDatasetNames: Elapsed Time: " + + elapsed); + return additionalFieldsSets; } @@ -244,8 +235,8 @@ public class ReadWriteNonCoreDataServiceImpl implements @Override public void updateExtraData(String type, String set, Long id, Map queryParams) { - logger.info("updateExtraData - type: " + type + " set: " + set - + " id: " + id); + + long startTime = System.currentTimeMillis(); checkResourceTypeThere(type, set); String fullDatasetName = getFullDatasetName(type, set); @@ -253,35 +244,26 @@ public class ReadWriteNonCoreDataServiceImpl implements String saveSql = getSaveSql(fullDatasetName, id, transType, queryParams); - logger.info("saveSQL: " + saveSql); - Connection db_connection = null; - Statement db_statement = null; - try { - db_connection = dataSource.getConnection(); - db_statement = db_connection.createStatement(); - db_statement.executeUpdate(saveSql); - - } catch (SQLException e) { - throw new PlatformDataIntegrityException("error.msg.sql.error", - e.getMessage(), "Additional Fields Type: " + type - + " Set: " + set + " Id: " + id); - } finally { - genericDataService.dbClose(db_statement, db_connection); - } + String sqlErrorMsg = "Additional Fields Type: " + type + " Set: " + + set + " Id: " + id; + genericDataService.updateSQL(saveSql, sqlErrorMsg); + long elapsed = System.currentTimeMillis() - startTime; + logger.info("FINISHING updateExtraData: Elapsed Time: " + elapsed + + " - type: " + type + " set: " + set + " id: " + id); } private void checkResourceTypeThere(String type, String set) { - String sql = "select 'f' from stretchydata_datasettype t join stretchydata_dataset d on d.datasettype_id = t.id where d.`name` = '" + String sql = "select t.id from stretchydata_datasettype t join stretchydata_dataset d on d.datasettype_id = t.id where d.`name` = '" + set + "' and t.`name` = '" + type + "'"; - Connection db_connection = null; - Statement db_statement = null; + String sqlErrorMsg = "Additional Fields Type: " + type + " Set: " + + set + " Sql: " + sql; + CachedRowSet rs = genericDataService.getCachedResultSet(sql, + sqlErrorMsg); + try { - db_connection = dataSource.getConnection(); - db_statement = db_connection.createStatement(); - ResultSet rs = db_statement.executeQuery(sql); if (!(rs.next())) { throw new AdditionalFieldsNotFoundException(type, set); @@ -289,47 +271,37 @@ public class ReadWriteNonCoreDataServiceImpl implements } catch (SQLException e) { throw new PlatformDataIntegrityException("error.msg.sql.error", - e.getMessage(), "Additional Fields Type: " + type - + " Set: " + set + " Sql: " + sql); - } finally { - genericDataService.dbClose(db_statement, db_connection); + e.getMessage(), sqlErrorMsg); } } private String getTransType(String type, String fullDatasetName, Long id) { - String transType = null; String sql = "select s.id from `" + type + "` t left join `" + fullDatasetName + "` s on s.id = t.id where t.id = " + id; - Connection db_connection = null; - Statement db_statement = null; + String sqlErrorMsg = "Additional Fields Type: " + type + + " Full Set Name: " + fullDatasetName + " Sql: " + sql; + CachedRowSet rs = genericDataService.getCachedResultSet(sql, + sqlErrorMsg); + try { - db_connection = dataSource.getConnection(); - db_statement = db_connection.createStatement(); - ResultSet rs = db_statement.executeQuery(sql); if (rs.next()) { String idValue = rs.getString("id"); - if (idValue != null) { - transType = "E"; - } else { - transType = "A"; - } - } else { - throw new AdditionalFieldsNotFoundException(type, id); + if (idValue != null) + return "E"; // update (edit) + + return "A"; // create (add) } + throw new AdditionalFieldsNotFoundException(type, id); + } catch (SQLException e) { throw new PlatformDataIntegrityException("error.msg.sql.error", - e.getMessage(), "Additional Fields Type: " + type - + " Full Set Name: " + fullDatasetName - + " Sql: " + sql); - } finally { - genericDataService.dbClose(db_statement, db_connection); + e.getMessage(), sqlErrorMsg); } - return transType; } private String getSaveSql(String fullSetName, Long id, String transType,