import java.sql.DatabaseMetaData;\r
import java.sql.Connection;\r
import java.sql.DriverManager;\r
+import java.sql.PreparedStatement;\r
import java.sql.ResultSet;\r
import java.sql.ResultSetMetaData;\r
import java.sql.SQLException;\r
public static String NUXEO_MANAGER_DATASOURCE_NAME = "NuxeoMgrDS";\r
public static String NUXEO_READER_DATASOURCE_NAME = "NuxeoReaderDS";\r
public static String NUXEO_USER_NAME = "nuxeo";\r
+ public static String SQL_WILDCARD = "%";\r
+ \r
//\r
// Private constants\r
//\r
conn = getConnection(dataSourceName, repositoryName);\r
stmt = conn.createStatement();\r
\r
- RowSetFactory rowSetFactory = RowSetProvider.newFactory();\r
+ RowSetFactory rowSetFactory = RowSetProvider.newFactory();\r
CachedRowSet crs = rowSetFactory.createCachedRowSet();\r
\r
stmt = conn.createStatement();\r
try (ResultSet resultSet = stmt.executeQuery(sql)) {\r
crs.populate(resultSet);\r
}\r
- stmt.close(); // also closes resultSet\r
return crs;\r
} catch (SQLException sqle) {\r
SQLException tempException = sqle;\r
throw new RuntimeException("SQL problem in executeQuery: ", sqle);\r
} finally {\r
try {\r
+ if (stmt != null) {\r
+ stmt.close();\r
+ }\r
if (conn != null) {\r
conn.close();\r
}\r
- if (stmt != null) {\r
- stmt.close();\r
+ } catch (SQLException sqle) {\r
+ logger.debug("SQL Exception closing statement/connection in executeQuery: " + sqle.getLocalizedMessage());\r
+ return null;\r
+ }\r
+ }\r
+ }\r
+ \r
+ public static CachedRowSet executePreparedQuery(final PreparedStatementBuilder builder,\r
+ String dataSourceName, String repositoryName, String sql) throws Exception {\r
+ Connection conn = null;\r
+ PreparedStatement ps = null;\r
+ try {\r
+ conn = getConnection(dataSourceName, repositoryName);\r
+ RowSetFactory rowSetFactory = RowSetProvider.newFactory();\r
+ CachedRowSet crs = rowSetFactory.createCachedRowSet();\r
+ ps = builder.build(conn);\r
+ // FIXME: transition this log statement to DEBUG level when appropriate\r
+ if (logger.isInfoEnabled()) {\r
+ logger.info("prepared statement=" + ps.toString());\r
+ }\r
+ try (ResultSet resultSet = ps.executeQuery()) {\r
+ crs.populate(resultSet);\r
+ }\r
+ return crs;\r
+ } finally {\r
+ try {\r
+ if (ps != null) {\r
+ ps.close();\r
+ }\r
+ if (conn != null) {\r
+ conn.close();\r
}\r
} catch (SQLException sqle) {\r
logger.debug("SQL Exception closing statement/connection in executeQuery: " + sqle.getLocalizedMessage());\r
throw new RuntimeException("SQL problem in executeUpdate: " + msg, sqle);\r
} finally {\r
try {\r
- if (conn != null) {\r
- conn.close();\r
- }\r
if (stmt != null) {\r
stmt.close();\r
}\r
+ if (conn != null) {\r
+ conn.close();\r
+ }\r
} catch (SQLException sqle) {\r
logger.debug("SQL Exception closing statement/connection in executeUpdate: " + sqle.getLocalizedMessage());\r
return -1;\r
import java.io.Serializable;
import java.sql.Connection;
+import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.collectionspace.services.common.query.QueryContext;
import org.collectionspace.services.common.repository.RepositoryClient;
import org.collectionspace.services.common.storage.JDBCTools;
+import org.collectionspace.services.common.storage.PreparedStatementBuilder;
import org.collectionspace.services.lifecycle.TransitionDef;
import org.collectionspace.services.nuxeo.util.NuxeoUtils;
public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
private static final String ID_COLUMN_NAME = "id";
-
+
/**
* Instantiates a new repository java client impl.
*/
}
}
- private DocumentModelList getFilteredJDBC(RepositoryInstance repoSession, ServiceContext ctx, DocumentHandler handler, QueryContext queryContext)
- throws Exception {
+ private DocumentModelList getFilteredJDBC(RepositoryInstance repoSession, ServiceContext ctx,
+ DocumentHandler handler, QueryContext queryContext) throws Exception {
DocumentModelList result = new DocumentModelListImpl();
String dataSourceName = JDBCTools.NUXEO_DATASOURCE_NAME;
String repositoryName = ctx.getRepositoryName();
- // Connection connection = JDBCTools.getConnection(dataSourceName, repositoryName);
-
MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
- String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
+ final String partialTerm = queryParams.getFirst(IQueryManager.SEARCH_TYPE_PARTIALTERM);
// FIXME: Replace this placeholder with an appropriate per-authority value
// obtained from the relevant document handler
- String termInfoGroupTableName = "loctermgroup";
+ final String termGroupTableName = "loctermgroup";
+
+ // AuthorityItemDocModelHandler authHandler = (AuthorityItemDocModelHandler) handler;
// FIXME: Replace this placeholder query with an actual query from CSPACE-5945
- // FIXME: Consider using a prepared statement here
+
+ // IMPORTANT FIXME: Guard against SQL injection attacks, since partialTerm
+ // is obtained from user-supplied query parameters
+ // See, for example: http://stackoverflow.com/a/7127189
String sql =
- "SELECT DISTINCT hierarchy.id as id " // For debugging add: ", ltg.termdisplayname"
+ "SELECT DISTINCT hierarchy.id as id "
+ " FROM hierarchy "
+ " LEFT JOIN hierarchy h1 "
+ " ON h1.parentid = hierarchy.id "
- + " AND h1.name = 'locations_common:locTermGroupList' "
- + " LEFT JOIN loctermgroup ltg "
- + " ON ltg.id = h1.id "
- + " WHERE (ltg.termdisplayname ILIKE '" + partialTerm + "%')";
-
- // Make sure autocommit is off. See:
- // http://jdbc.postgresql.org/documentation/80/query.html#query-with-cursor
- // http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
- // connection.setAutoCommit(false);
-
- // FIXME: Add exception handling and 'finally' blocks to ensure we close resources
- // FIXME: Identify whether we can piggyback on existing JDBC method(s) in common.storage,
- // and if so, add whatever additional functionality may be required to those method(s)
- // FIXME: Add pagination handling
-
- /*
- Statement st = connection.createStatement();
- // Enable use of the cursor for pagination
- st.setFetchSize(50);
- List<String> docIds = new ArrayList<String>();
- ResultSet rs = st.executeQuery(sql);
- String id;
- while (rs.next()) {
- id = rs.getString("id");
- if (Tools.notBlank(id)) {
- docIds.add(id);
- }
- }
- rs.close();
-
- // Close the statement.
- st.close();
- */
+ + " LEFT JOIN ? tg "
+ + " ON tg.id = h1.id "
+ + " WHERE tg.termdisplayname ILIKE ?";
+
+ PreparedStatementBuilder partialTermMatchStatementBuilder = new PreparedStatementBuilder(sql){
+ @Override
+ protected void preparePrepared(PreparedStatement preparedStatement)
+ throws SQLException
+ {
+ preparedStatement.setString(1, termGroupTableName);
+ preparedStatement.setString(2, partialTerm + JDBCTools.SQL_WILDCARD);
+ }};
List<String> docIds = new ArrayList<String>();
- CachedRowSet crs = null;
- try {
- crs = JDBCTools.executeQuery(dataSourceName, repositoryName, sql);
+ try (CachedRowSet crs = JDBCTools.executePreparedQuery(partialTermMatchStatementBuilder,
+ dataSourceName, repositoryName, sql)) {
// If the response to the query is null or contains zero rows,
// return an empty list of document models
// Otherwise, get the document IDs from the results of the query
String id;
- /*
- int idColumnIndex;
- try {
- idColumnIndex = crs.findColumn(ID_COLUMN_NAME);
- } catch (SQLException sqle) {
- logger.warn("Could not find expected column '" + ID_COLUMN_NAME + "' in query results.");
- return result; // return an empty list of document models
- } finally {
- crs.close();
- }
- */
crs.beforeFirst();
while (crs.next()) {
- // id = crs.getString(idColumnIndex);
id = crs.getString(1);
if (Tools.notBlank(id)) {
docIds.add(id);
} catch (SQLException sqle) {
logger.warn("Could not obtain document IDs via SQL query '" + sql + "': " + sqle.getMessage());
return result; // return an empty list of document models
- } finally {
- crs.close();
}
// Get a list of document models, using the IDs obtained from the query
return result;
}
+
private DocumentModelList getFilteredCMIS(RepositoryInstance repoSession, ServiceContext ctx, DocumentHandler handler, QueryContext queryContext)
throws DocumentNotFoundException, DocumentException {