/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/basiclti/trunk/basiclti-impl/src/java/org/sakaiproject/lti/impl/DBLTIService.java $ * $Id: DBLTIService.java 132636 2013-12-16 18:51:41Z csev@umich.edu $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.sakaiproject.lti.impl; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.db.api.SqlService; import org.sakaiproject.lti.api.LTIService; import org.springframework.jdbc.core.ColumnMapRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.sql.DataSource; import org.sakaiproject.lti.impl.FoormMapRowMapper; /** * <p> * DBLTIService extends the BaseLTIService. * </p> */ public class DBLTIService extends BaseLTIService implements LTIService { /** Our log (commons). */ private static Log M_log = LogFactory.getLog(DBLTIService.class); /** * */ private PropertiesConfiguration statements; /** Dependency: SqlService */ protected SqlService m_sql = null; /** * Dependency: SqlService. * * @param service * The SqlService. */ public void setSqlService(SqlService service) { m_sql = service; } /** Configuration: to run the ddl on init or not. */ protected boolean m_autoDdl = false; /** * Configuration: to run the ddl on init or not. * * @param value * the auto ddl value. */ public void setAutoDdl(String value) { m_autoDdl = Boolean.valueOf(value); } /** * */ private javax.sql.DataSource dataSource = null; /** * */ private org.springframework.jdbc.core.JdbcTemplate jdbcTemplate = null; /********************************************************************************************************************************************************************************************************************************************************** * Init and Destroy *********************************************************************************************************************************************************************************************************************************************************/ /** * Final initialization, once all dependencies are set. */ public void init() { if (m_sql == null) m_sql = (SqlService) ComponentManager.get("org.sakaiproject.db.api.SqlService"); if (dataSource == null) dataSource = (DataSource) ComponentManager.get("javax.sql.DataSource"); if (jdbcTemplate == null && dataSource != null) jdbcTemplate = new JdbcTemplate(dataSource); try { boolean doReset = false; if (doReset) M_log.error("DO NOT RUN IN PRODUCTION WITH doReset TRUE"); foorm.autoDDL("lti_content", LTIService.CONTENT_MODEL, m_sql, m_autoDdl, doReset, M_log); foorm.autoDDL("lti_tools", LTIService.TOOL_MODEL, m_sql, m_autoDdl, doReset, M_log); foorm.autoDDL("lti_deploy", LTIService.DEPLOY_MODEL, m_sql, m_autoDdl, doReset, M_log); foorm.autoDDL("lti_binding", LTIService.BINDING_MODEL, m_sql, m_autoDdl, doReset, M_log); super.init(); } catch (Exception t) { M_log.warn("init(): ", t); } } /** * */ public Object insertToolDao(Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { return insertThingDao("lti_tools", LTIService.TOOL_MODEL, null, newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getToolDao(java.lang.Long, java.lang.String, boolean) */ protected Map<String, Object> getToolDao(Long key, String siteId, boolean isAdminRole) { return getThingDao("lti_tools", LTIService.TOOL_MODEL, key, siteId, isAdminRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#deleteToolDao(java.lang.Long, java.lang.String, boolean) */ public boolean deleteToolDao(Long key, String siteId, boolean isAdminRole, boolean isMaintainRole) { return deleteThingDao("lti_tools", LTIService.TOOL_MODEL, key, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.impl.BaseLTIService#updateToolDao(java.lang.Long, * java.lang.Object, java.lang.String, boolean) */ public Object updateToolDao(Long key, Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { return updateThingDao("lti_tools", LTIService.TOOL_MODEL, null, key, (Object) newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getToolsDao(java.lang.String, java.lang.String, * int, int, java.lang.String, boolean) */ public List<Map<String, Object>> getToolsDao(String search, String order, int first, int last, String siteId, boolean isAdminRole) { String extraSelect = "COUNT(DISTINCT lti_content.id) AS lti_content_count, COUNT(DISTINCT lti_content.SITE_ID) AS lti_site_count"; String joinClause = "LEFT OUTER JOIN lti_content ON lti_content.tool_id = lti_tools.id"; String groupBy = "lti_tools.id"; if ( order != null ) order = "lti_tools.id"; // Oracle needs all the selected values in the GROUP_BY if ("mysql".equals(m_sql.getVendor())) { return getThingsDao("lti_tools", LTIService.TOOL_MODEL, extraSelect, joinClause, search, groupBy, order, first, last, siteId, isAdminRole); } else { List<Map<String, Object>> mainList = getThingsDao("lti_tools", LTIService.TOOL_MODEL, null, null, search, null, order, first, last, siteId, isAdminRole); String[] id_model = { "id:key", "visible:radio", "SITE_ID:text" } ; groupBy = "lti_tools.id, lti_tools.visible, lti_tools.SITE_ID"; List<Map<String, Object>> countList = getThingsDao("lti_tools", id_model, extraSelect, joinClause, search, groupBy, order, first, last, siteId, isAdminRole); // Merge the lists... Map<Object, Map<String, Object>> countMap = new HashMap<Object, Map<String, Object>> (); for (Map<String, Object> count : countList) { Object id = count.get("id"); countMap.put(id, count); } for (Map<String, Object> row : mainList) { Object id = row.get("id"); if ( id == null ) continue; Map<String, Object> count = countMap.get(id); if ( count == null ) continue; Object contentCount = count.get("LTI_CONTENT_COUNT"); row.put("lti_content_count", contentCount); Object siteCount = count.get("LTI_SITE_COUNT"); row.put("lti_site_count", siteCount); } return mainList; } } /** * @return Returns String (falure) or Long (key on success) */ protected Object insertContentDao(Properties newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if ( newProps == null ) { throw new IllegalArgumentException( "newProps must be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } if (!isMaintainRole) return null; String toolId = newProps.getProperty(LTI_TOOL_ID); if (toolId == null) return rb.getString("error.missing.toolid"); Long toolKey = null; try { toolKey = new Long(toolId); } catch (Exception e) { return rb.getString("error.invalid.toolid"); } // Load the tool we are aiming for Using DAO Map<String, Object> tool = null; tool = getToolDao(toolKey, siteId, isAdminRole); if ( tool == null ) { return rb.getString("error.invalid.toolid"); } Long visible = foorm.getLongNull(tool.get(LTI_VISIBLE)); if ( visible == null ) visible = new Long(0); if ( ! isAdminRole ) { if ( visible == 1 ) { return rb.getString("error.invalid.toolid"); } } String[] contentModel = getContentModelDao(tool, isAdminRole); String[] columns = foorm.getFields(contentModel); // Since page title and title are both required and dynamically hideable, // They may not be in the model. If they are not there, add them for the purpose // of the insert, and then copy the values from the tool. List<String> contentModelList = new ArrayList<String>(Arrays.asList(contentModel)); List<String> contentModelColumns = new ArrayList<String>(Arrays.asList(columns)); if (!contentModelColumns.contains(LTI_TITLE) || !contentModelColumns.contains(LTI_PAGETITLE)) { String toolTitle = (String) tool.get(LTI_TITLE); if ( toolTitle == null ) toolTitle = "..."; // should not happen if (!contentModelColumns.contains(LTI_TITLE)) { contentModelList.add(LTI_TITLE + ":text"); newProps.put(LTI_TITLE, toolTitle); } if (!contentModelColumns.contains(LTI_PAGETITLE)) { // May happen for old / upgraded tool items String pageTitle = (String) tool.get(LTI_PAGETITLE); if ( pageTitle == null ) pageTitle = toolTitle; contentModelList.add(LTI_PAGETITLE + ":text"); newProps.put(LTI_PAGETITLE, pageTitle); } contentModel = contentModelList.toArray(new String[contentModelList.size()]); } // If resource_handler is not in content and is in the tool, copy it if ( newProps.getProperty(LTI_RESOURCE_HANDLER) == null && tool.get(LTI_RESOURCE_HANDLER) != null ) { newProps.put(LTI_RESOURCE_HANDLER, (String) tool.get(LTI_RESOURCE_HANDLER)); contentModelList.add(LTI_RESOURCE_HANDLER + ":text"); contentModel = contentModelList.toArray(new String[contentModelList.size()]); } if (contentModel == null) return rb.getString("error.invalid.toolid"); return insertThingDao("lti_content", contentModel, LTIService.CONTENT_MODEL, newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getContentDao(java.lang.Long, java.lang.String, boolean) */ public Map<String, Object> getContentDao(Long key, String siteId, boolean isAdminRole) { Map<String, Object> retval = getThingDao("lti_content", LTIService.CONTENT_MODEL, key, siteId, isAdminRole); if (retval == null) return retval; retval.put("launch_url", getContentLaunch(retval)); return retval; } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#deleteContent(java.lang.Long, java.lang.String, boolean) */ public boolean deleteContentDao(Long key, String siteId, boolean isAdminRole, boolean isMaintainRole) { deleteContentLinkDao(key, siteId, isAdminRole, isMaintainRole); return deleteThingDao("lti_content", LTIService.CONTENT_MODEL, key, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.impl.BaseLTIService#updateContentDao(java.lang.Long, * java.lang.Object, java.lang.String, boolean) */ public Object updateContentDao(Long key, Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if ( key == null || newProps == null ) { throw new IllegalArgumentException( "both key and newProps must be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } // Load the content item Map<String,Object> content = getContentDao(key, siteId, isAdminRole); if ( content == null ) { return rb.getString("error.content.not.found"); } Long oldToolKey = foorm.getLongNull(content.get(LTI_TOOL_ID)); Object oToolId = (Object) foorm.getField(newProps, LTI_TOOL_ID); Long newToolKey = null; if ( oToolId != null && oToolId instanceof Number ) { newToolKey = new Long( ((Number) oToolId).longValue()); } else if ( oToolId != null ) { try { newToolKey = new Long((String) oToolId); } catch (Exception e) { return rb.getString("error.invalid.toolid"); } } if ( newToolKey == null || newToolKey < 0 ) newToolKey = oldToolKey; // Load the tool we are aiming for Map<String, Object> tool = getToolDao(newToolKey, siteId, isAdminRole); if ( tool == null ) { return rb.getString("error.invalid.toolid"); } // If the user is not an admin, they cannot switch to // a tool that is stealthed Long visible = foorm.getLongNull(tool.get(LTI_VISIBLE)); if ( visible == null ) visible = new Long(0); if ( ( !isAdminRole ) && ( ! oldToolKey.equals(newToolKey) ) ) { if ( visible == 1 ) { return rb.getString("error.invalid.toolid"); } } String[] contentModel = getContentModelDao(tool, isAdminRole); if (contentModel == null) return rb.getString("error.invalid.toolid"); return updateThingDao("lti_content", contentModel, LTIService.CONTENT_MODEL, key, newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getContentsDao(java.lang.String, * java.lang.String, int, int) */ public List<Map<String, Object>> getContentsDao(String search, String order, int first, int last, String siteId, boolean isAdminRole) { List<Map<String, Object>> contents = getThingsDao("lti_content", LTIService.CONTENT_MODEL, null, null, search, null, order, first, last, siteId, isAdminRole); for (Map<String, Object> content : contents) { content.put("launch_url", getContentLaunch(content)); } return contents; } /** * */ public Object insertDeployDao(Properties newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if ( ! isAdminRole ) throw new IllegalArgumentException("Currently we support admins/Dao access"); return insertThingDao("lti_deploy", LTIService.DEPLOY_MODEL, null, newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#deleteDeployDao(java.lang.Long, java.lang.String, boolean) */ public boolean deleteDeployDao(Long key, String siteId, boolean isAdminRole, boolean isMaintainRole) { if ( ! isAdminRole ) throw new IllegalArgumentException("Currently we support admins/Dao access"); return deleteThingDao("lti_deploy", LTIService.DEPLOY_MODEL, key, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.impl.BaseLTIService#updateDeployDao(java.lang.Long, * java.lang.Object, java.lang.String, boolean) */ public Object updateDeployDao(Long key, Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if ( ! isAdminRole ) throw new IllegalArgumentException("Currently we support admins/Dao access"); return updateThingDao("lti_deploy", LTIService.DEPLOY_MODEL, null, key, newProps, siteId, isAdminRole, isMaintainRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getDeployDao(java.lang.Long, java.lang.String, boolean) */ protected Map<String, Object> getDeployDao(Long key, String siteId, boolean isAdminRole) { if ( ! isAdminRole ) throw new IllegalArgumentException("Currently we support admins/Dao access"); return getThingDao("lti_deploy", LTIService.DEPLOY_MODEL, key, siteId, isAdminRole); } /** * * {@inheritDoc} * * @see org.sakaiproject.lti.api.LTIService#getDeploysDao(java.lang.String, java.lang.String, * int, int, java.lang.String, boolean) */ protected List<Map<String, Object>> getDeploysDao(String search, String order, int first, int last, String siteId, boolean isAdminRole) { if ( ! isAdminRole ) throw new IllegalArgumentException("Currently we support admins/Dao access"); String extraSelect = "COUNT(DISTINCT lti_tools.id) AS lti_tool_count, COUNT(DISTINCT lti_content.SITE_ID) AS lti_site_count, COUNT(DISTINCT lti_content.id) AS lti_content_count"; String joinClause = "LEFT OUTER JOIN lti_tools ON lti_tools.deployment_id = lti_deploy.id LEFT OUTER JOIN lti_content ON lti_content.tool_id = lti_tools.id"; String groupBy = "lti_deploy.id"; if ( order != null ) order = "lti_deploy.id"; // Oracle needs all the selected values in the GROUP_BY if ("mysql".equals(m_sql.getVendor())) { return getThingsDao("lti_deploy", LTIService.DEPLOY_MODEL, extraSelect, joinClause, search, groupBy, order, first, last, siteId, isAdminRole); } else { List<Map<String, Object>> mainList = getThingsDao("lti_deploy",LTIService.DEPLOY_MODEL, null, null, search, null, order, first, last, siteId, isAdminRole); String[] id_model = { "id:key", "visible:radio" } ; groupBy = "lti_tools.id, lti_tools.visible"; List<Map<String, Object>> countList = getThingsDao("lti_deploy", id_model, extraSelect, joinClause, search, groupBy, order, first, last, siteId, isAdminRole); // Merge the lists... Map<Object, Map<String, Object>> countMap = new HashMap<Object, Map<String, Object>> (); for (Map<String, Object> count : countList) { Object id = count.get("id"); countMap.put(id, count); } for (Map<String, Object> row : mainList) { Object id = row.get("id"); if ( id == null ) continue; Map<String, Object> count = countMap.get(id); if ( count == null ) continue; Object contentCount = count.get("LTI_CONTENT_COUNT"); row.put("lti_content_count", contentCount); Object toolCount = count.get("LTI_TOOL_COUNT"); row.put("lti_tool_count", toolCount); Object siteCount = count.get("LTI_SITE_COUNT"); row.put("lti_site_count", siteCount); } return mainList; } } public Object insertProxyBindingDao(Properties newProps) { return insertThingDao("lti_binding", LTIService.BINDING_MODEL, null, newProps, null, true, true); } public Object updateProxyBindingDao(Long key, Object newProps) { return updateThingDao("lti_binding", LTIService.BINDING_MODEL, null, key, newProps, null, true, true); } public boolean deleteProxyBindingDao(Long key) { return deleteThingDao("lti_binding", LTIService.BINDING_MODEL, key, null, true, true); } public Map<String, Object> getProxyBindingDao(Long key) { return getThingDao("lti_binding", LTIService.BINDING_MODEL, key, null, true); } public Map<String, Object> getProxyBindingDao(Long tool_id, String siteId) { if (tool_id == null || siteId == null) { throw new IllegalArgumentException("tool_id and siteId must be non-null"); } String[] model = LTIService.BINDING_MODEL; String[] columns = foorm.getFields(model); String statement = "SELECT " + foorm.formSelect(model) + " FROM lti_binding WHERE " + LTI_SITE_ID + " = ? AND " + LTI_TOOL_ID + " = ?"; Object [] fields = new Object[2]; fields[0] = siteId; fields[1] = tool_id; M_log.debug(statement); List rv = getResultSet(statement, fields, columns); if ((rv != null) && (rv.size() > 0)) { if ( rv.size() > 1 ) { M_log.warn("Warning more than one row returned: "+statement); } return (Map<String, Object>) rv.get(0); } return null; } /** * @param table * The name of the table to use * @param formModel * The filtered model(required) * @param fullModel * The full model (or null) * @param newProps * The key/value pairs for this object. * @param siteId * The siteId that this item is being inserted into. If isAdmin is true, * this should be null and the siteId is expected be in the newProps variable. * @param isAdminRole * This is true if we are doing this as an administrator (i.e. we can bypass * rules about SITE_ID being null in the inserted object. * @param isMaintainRole * This is true if we are doing this as a site maintainer. This will return * null if we are not the site maintainer. * @return Returns String (failure) or Long (key on success) */ public Object insertThingDao(String table, String[] formModel, String[] fullModel, Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if (table == null || formModel == null || newProps == null ) { throw new IllegalArgumentException( "table, model, and newProps must all be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } if ( ! (newProps instanceof Properties || newProps instanceof Map ) ) { throw new IllegalArgumentException("newProps must Properties or Map<String, Object>"); } // TODO: Remove this as a parameter if (!isMaintainRole) return null; HashMap<String, Object> newMapping = new HashMap<String, Object>(); String[] columns = null; String theKey = null; if (fullModel == null) { columns = foorm.getFields(formModel); theKey = foorm.formSqlKey(formModel); } else { columns = foorm.getFields(fullModel); theKey = foorm.formSqlKey(fullModel); } // Insert the SITE_ID if it is not present in case it is required if (!isAdminRole && (Arrays.asList(columns).contains(LTI_SITE_ID))) { ((Map) newProps).put(LTI_SITE_ID, siteId); } // Check to see if this insert has all required fields in the proper format String errors = foorm.formExtract(newProps, formModel, rb, true, newMapping, null); if (errors != null) return errors; // Only admins can insert things into sites other than the current site if (!isAdminRole && (Arrays.asList(columns).contains(LTI_SITE_ID))) { newMapping.put(LTI_SITE_ID, siteId); } String seqName = foorm.getSqlSequence(table, theKey, m_sql.getVendor()); String[] insertInfo = foorm.insertForm(newMapping); String makeSql = "INSERT INTO " + table + " ( " + insertInfo[0] + " ) VALUES ( " + insertInfo[1] + " )"; if ("oracle".equals(m_sql.getVendor()) && theKey != null && seqName != null) { makeSql = "INSERT INTO " + table + " ( " + theKey + ", " + insertInfo[0] + " ) VALUES ( " + seqName + ".NextVal, " + insertInfo[1] + " )"; } final String sql = makeSql; // System.out.println("Insert SQL="+sql); final Object[] fields = foorm.getInsertObjects(newMapping); Long retval = m_sql.dbInsert(null, sql, fields, LTI_ID); M_log.debug("Count="+retval+" Insert="+sql); return retval; } /** * * @param table * @param model * @param key * @param siteId - This is allowed to be null * @param isMaintainRole * @return */ private Map<String, Object> getThingDao(String table, String[] model, Long key, String siteId, boolean isAdminRole) { if (table == null || model == null || key == null) { throw new IllegalArgumentException("table, model, and key must all be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } String statement = "SELECT " + foorm.formSelect(model) + " from " + table + " WHERE id = ?"; Object fields[] = null; String[] columns = foorm.getFields(model); // Non-admins only see global (SITE_ID IS NULL) or in their site if (!isAdminRole && Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0 ) { statement += " AND (SITE_ID = ? OR SITE_ID IS NULL)"; fields = new Object[2]; fields[0] = key; fields[1] = siteId; } else { fields = new Object[1]; fields[0] = key; } M_log.debug(statement); List rv = getResultSet(statement, fields, columns); if ((rv != null) && (rv.size() > 0)) { if ( rv.size() > 1 ) { M_log.warn("Warning more than one row returned: "+statement); } return (Map<String, Object>) rv.get(0); } return null; } /** * * @param table * @param model * @param search * @param order * @param first * @param last * @param siteId * @param isMaintainRole * @return */ public List<Map<String, Object>> getThingsDao(String table, String[] model, String extraSelect, String joinClause, String search, String groupBy, String order, int first, int last, String siteId, boolean isAdminRole) { if (table == null || model == null ) { throw new IllegalArgumentException("table and model must be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } String statement = "SELECT " + foorm.formSelect(table, model, true); if ( extraSelect != null ) { statement += ", " + extraSelect; } statement += " FROM " + table; if ( joinClause != null ) { statement += " " + joinClause; } String[] columns = foorm.getFields(model); String whereClause = ""; // Only admins can see invisible items and items from any site Object fields[] = null; if ( ! isAdminRole ) { if (Arrays.asList(columns).indexOf(LTI_VISIBLE) >= 0 && Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0 ) { whereClause = " ("+table+'.'+LTI_SITE_ID+" = ? OR "+ "("+table+'.'+LTI_SITE_ID+" IS NULL AND "+table+'.'+LTI_VISIBLE+" != 1 ) ) "; fields = new Object[1]; fields[0] = siteId; } else if (Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0) { whereClause = " ("+table+'.'+LTI_SITE_ID+" = ? OR "+table+'.'+LTI_SITE_ID+" IS NULL)"; fields = new Object[1]; fields[0] = siteId; } } if ( search != null && search.length() > 0 ) { if ( whereClause.length() > 0 ) { whereClause += " AND (" + search + ") "; } else { whereClause += " (" + search + ") "; } } if ( whereClause.length() > 0 ) statement += " WHERE " + whereClause; if ( groupBy != null ) { statement += " GROUP BY "; if ("oracle".equals(m_sql.getVendor()) ) { statement += foorm.formSelect(table, model, false); } else { statement += groupBy; } } if ( order != null ) { statement += " ORDER BY " + order; } if (last != 0) { String pagedStatement = foorm.getPagedSelect(statement, first, last, m_sql.getVendor()); if (pagedStatement != null) statement = pagedStatement; } M_log.debug(statement); return getResultSet(statement, fields, columns); } /** * * @param table * @param model * @param key * @param siteId * @param isMaintainRole * @return */ public boolean deleteThingDao(String table, String[] model, Long key, String siteId, boolean isAdminRole, boolean isMaintainRole) { if (table == null || model == null || key == null) { throw new IllegalArgumentException("table, model, and key must all be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } if (!isMaintainRole) return false; String statement = "DELETE FROM " + table + " WHERE id = ?"; Object fields[] = null; String[] columns = foorm.getFields(model); // Only admins can delete by id irrespective of the current site if (!isAdminRole && Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0 ) { statement += " AND SITE_ID = ?"; fields = new Object[2]; fields[0] = key; fields[1] = siteId; } else { fields = new Object[1]; fields[0] = key; } int count = m_sql.dbWriteCount(statement, fields, null, null, false); M_log.debug("Count="+count+" Delete="+statement); return count == 1; } /** * * @param table * @param formModel * @param fullModel * @param key * @param newProps * @param siteId * @return */ public Object updateThingDao(String table, String[] formModel, String[] fullModel, Long key, Object newProps, String siteId) { return updateThingDao(table, formModel, fullModel, key, newProps, siteId, isAdmin(siteId), isMaintain(siteId)); } /** * * @param table * @param formModel * @param fullModel * @param key * @param newProps * @param siteId * @param isMaintainRole * @return */ public Object updateThingDao(String table, String[] formModel, String[] fullModel, Long key, Object newProps, String siteId, boolean isAdminRole, boolean isMaintainRole) { if (table == null || formModel == null || key == null || newProps == null) { throw new IllegalArgumentException( "table, model, key, and newProps must all be non-null"); } if (siteId == null && !isAdminRole ) { throw new IllegalArgumentException("siteId must be non-null for non-admins"); } if ( ! (newProps instanceof Properties || newProps instanceof Map) ) { throw new IllegalArgumentException("newProps must Properties or Map<String, Object>"); } if (!isMaintainRole) return false; HashMap<String, Object> newMapping = new HashMap<String, Object>(); String errors = foorm.formExtract(newProps, formModel, rb, false, newMapping, null); if (errors != null) return errors; String[] columns = null; if (fullModel == null) { columns = foorm.getFields(formModel); } else { columns = foorm.getFields(fullModel); } // Only admins can update *into* a site if ( !isAdminRole && (Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0)) { newMapping.put(LTI_SITE_ID, siteId); } String sql = "UPDATE " + table + " SET " + foorm.updateForm(newMapping) + " WHERE id=" + key.toString(); if ( isMaintainRole && !isAdminRole && (Arrays.asList(columns).indexOf(LTI_SITE_ID) >= 0)) { sql += " AND SITE_ID = '" + siteId + "'"; foorm.setField(newMapping, LTI_SITE_ID, siteId); } // System.out.println("Upate="+sql); Object[] fields = foorm.getUpdateObjects(newMapping); // System.out.println("Fields="+Arrays.toString(fields)); int count = m_sql.dbWriteCount(sql, fields, null, null, false); M_log.debug("Count="+count+" Update="+sql); return count == 1; } /*-- Straight-up API methods ------------------------*/ public Map<String, Object> getToolForResourceHandlerDao(String resourceType) { if (resourceType == null ) { throw new IllegalArgumentException("resourceType must be non-null"); } String[] model = LTIService.TOOL_MODEL; String[] columns = foorm.getFields(model); String statement = "SELECT " + foorm.formSelect(model) + " FROM lti_tools WHERE " + LTI_RESOURCE_HANDLER + " = ? "; Object [] fields = new Object[1]; fields[0] = resourceType; M_log.debug(statement); List rv = getResultSet(statement, fields, columns); if ((rv != null) && (rv.size() > 0)) { if ( rv.size() > 1 ) { M_log.warn("Warning more than one row returned: "+statement); } return (Map<String, Object>) rv.get(0); } return null; } public Map<String, Object> getDeployForConsumerKeyDao(String consumerKey) { if (consumerKey == null ) { throw new IllegalArgumentException("consumerKey must be non-null"); } String[] model = LTIService.DEPLOY_MODEL; String[] columns = foorm.getFields(model); String statement = "SELECT " + foorm.formSelect(model) + " FROM lti_deploy WHERE " + LTI_CONSUMERKEY + " = ? "; Object [] fields = new Object[1]; fields[0] = consumerKey; M_log.debug(statement); List rv = getResultSet(statement, fields, columns); if ((rv != null) && (rv.size() > 0)) { if ( rv.size() > 1 ) { M_log.warn("Warning more than one row returned: "+statement); } return (Map<String, Object>) rv.get(0); } return null; } // Utility to return a resultset public List<Map<String, Object>> getResultSet(String statement, Object[] fields, final String[] columns) { // System.out.println("getResultSet sql="+statement+" fields="+fields); List rv = jdbcTemplate.query(statement, fields, new FoormMapRowMapper(columns)); // System.out.println("getResultSet size="+rv.size()+" sql="+statement); return (List<Map<String, Object>>) rv; } }