/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/basiclti/trunk/basiclti-tool/src/java/org/sakaiproject/blti/tool/LTIAdminTool.java $
* $Id: LTIAdminTool.java 132669 2013-12-17 15:05:17Z csev@umich.edu $
***********************************************************************************
*
* Copyright (c) 2011 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.blti.tool;
import java.io.Writer;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Properties;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.sakaiproject.cheftool.Context;
import org.sakaiproject.cheftool.JetspeedRunData;
import org.sakaiproject.cheftool.RunData;
import org.sakaiproject.cheftool.VelocityPortlet;
import org.sakaiproject.cheftool.VelocityPortletPaneledAction;
import org.sakaiproject.cheftool.api.Menu;
import org.sakaiproject.cheftool.menu.MenuEntry;
import org.sakaiproject.cheftool.menu.MenuImpl;
import org.sakaiproject.event.api.SessionState;
import org.sakaiproject.util.ResourceLoader;
import org.sakaiproject.tool.api.Placement;
import org.sakaiproject.tool.api.ToolManager;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.api.SitePage;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.site.api.ToolConfiguration;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.util.FormattedText;
// TODO: FIX THIS
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.lti.api.LTIService;
import org.sakaiproject.basiclti.util.SakaiBLTIUtil;
import org.imsglobal.basiclti.BasicLTIUtil;
import org.imsglobal.lti2.LTI2Config;
import org.imsglobal.lti2.LTI2Util;
import org.sakaiproject.lti2.SakaiLTI2Config;
// import org.sakaiproject.lti.impl.DBLTIService; // HACK
import org.sakaiproject.util.foorm.SakaiFoorm;
/**
* <p>
* LTIAdminTool is a Simple Velocity-based Tool
* </p>
*/
public class LTIAdminTool extends VelocityPortletPaneledAction
{
private static Log M_log = LogFactory.getLog(LTIAdminTool.class);
/** Resource bundle using current language locale */
protected static ResourceLoader rb = new ResourceLoader("ltitool");
private boolean inHelper = false;
private static String STATE_POST = "lti:state_post";
private static String STATE_SUCCESS = "lti:state_success";
private static String STATE_ID = "lti:state_id";
private static String STATE_TOOL_ID = "lti:state_tool_id";
private static String STATE_CONTENT_ID = "lti:state_content_id";
private static String STATE_REDIRECT_URL = "lti:state_redirect_url";
private static String STATE_LTI2_TOOL_ID = "lti2:state_tool_id";
private static String SECRET_HIDDEN = "***************";
private static String ALLOW_MAINTAINER_ADD_SYSTEM_TOOL = "lti:allow_maintainer_add_system_tool";
/** Service Implementations */
protected static ToolManager toolManager = null;
protected static LTIService ltiService = null;
protected static ServerConfigurationService serverConfigurationService = null;
protected static SakaiFoorm foorm = new SakaiFoorm();
/**
* Pull in any necessary services using factory pattern
*/
protected void getServices()
{
if ( toolManager == null ) toolManager = (ToolManager) ComponentManager.get("org.sakaiproject.tool.api.ToolManager");
/* HACK to save many restarts during development
if ( ltiService == null ) {
ltiService = (LTIService) new DBLTIService();
((org.sakaiproject.lti.impl.DBLTIService) ltiService).setAutoDdl("true");
((org.sakaiproject.lti.impl.DBLTIService) ltiService).init();
}
End of HACK */
if ( ltiService == null ) ltiService = (LTIService) ComponentManager.get("org.sakaiproject.lti.api.LTIService");
if ( serverConfigurationService == null ) serverConfigurationService = (ServerConfigurationService) ComponentManager.get("org.sakaiproject.component.api.ServerConfigurationService");
}
/**
* Populate the state with configuration settings
*/
protected void initState(SessionState state, VelocityPortlet portlet, JetspeedRunData rundata)
{
super.initState(state, portlet, rundata);
getServices();
Placement placement = toolManager.getCurrentPlacement();
String toolReg = placement.getToolId();
inHelper = ! ( "sakai.basiclti.admin".equals(toolReg));
}
/**
* Setup the velocity context and choose the template for the response.
*/
public String buildErrorPanelContext(VelocityPortlet portlet, Context context,
RunData rundata, SessionState state)
{
context.put("tlang", rb);
state.removeAttribute(STATE_ID);
state.removeAttribute(STATE_TOOL_ID);
state.removeAttribute(STATE_POST);
state.removeAttribute(STATE_SUCCESS);
state.removeAttribute(STATE_REDIRECT_URL);
return "lti_error";
}
public String buildMainPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
// default to site view
return buildToolSitePanelContext(portlet, context, data, state);
}
public String buildToolSitePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
String returnUrl = data.getParameters().getString("returnUrl");
// if ( returnUrl != null ) state.setAttribute(STATE_REDIRECT_URL, returnUrl);
context.put("ltiService", ltiService);
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("inHelper",new Boolean(inHelper));
context.put("getContext",toolManager.getCurrentPlacement().getContext());
context.put("doEndHelper", BUTTON + "doEndHelper");
state.removeAttribute(STATE_POST);
state.removeAttribute(STATE_SUCCESS);
// this is for the "site tools" panel
List<Map<String,Object>> contents = ltiService.getContents(null,null,0,5000);
for ( Map<String,Object> content : contents ) {
Long tool_id_long = null;
try{
tool_id_long = new Long(content.get(LTIService.LTI_TOOL_ID).toString());
}
catch (Exception e)
{
// log the error
M_log.error("error parsing tool id " + content.get(LTIService.LTI_TOOL_ID));
}
context.put("tool_id_long", tool_id_long);
String plstr = (String) content.get(LTIService.LTI_PLACEMENT);
ToolConfiguration tool = SiteService.findTool(plstr);
if ( tool == null ) {
content.put(LTIService.LTI_PLACEMENT, null);
}
}
context.put("contents", contents);
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("getContext",toolManager.getCurrentPlacement().getContext());
// top navigation menu
Menu menu = new MenuImpl(portlet, data, "LTIAdminTool");
menu.add(new MenuEntry(rb.getString("tool.in.site"), false, "doNav_tool_site"));
menu.add(new MenuEntry(rb.getString("tool.in.system"), true, "doNav_tool_system"));
context.put("menu", menu);
return "lti_tool_site";
}
public String buildToolSystemPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
String contextString = toolManager.getCurrentPlacement().getContext();
String returnUrl = data.getParameters().getString("returnUrl");
// if ( returnUrl != null ) state.setAttribute(STATE_REDIRECT_URL, returnUrl);
context.put("ltiService", ltiService);
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("inHelper",new Boolean(inHelper));
context.put("doEndHelper", BUTTON + "doEndHelper");
state.removeAttribute(STATE_POST);
state.removeAttribute(STATE_SUCCESS);
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
// by default, site maintainer can add system-wide LTI tool
context.put("allowMaintainerAddSystemTool", new Boolean(serverConfigurationService.getBoolean(ALLOW_MAINTAINER_ADD_SYSTEM_TOOL, true)));
context.put("getContext", contextString);
// this is for the system tool panel
List<Map<String,Object>> tools = ltiService.getTools(null,null,0,0);
context.put("ltiTools", tools);
// top navigation menu
Menu menu = new MenuImpl(portlet, data, "LTIAdminTool");
menu.add(new MenuEntry(rb.getString("tool.in.site"), true, "doNav_tool_site"));
menu.add(new MenuEntry(rb.getString("tool.in.system"), false, "doNav_tool_system"));
context.put("menu", menu);
return "lti_tool_system";
}
public void doEndHelper(RunData data, Context context)
{
// Request a shortcut transfer back to the tool we are helping
// This working depends on SAK-20898
SessionManager.getCurrentToolSession().setAttribute(HELPER_LINK_MODE, HELPER_MODE_DONE);
// In case the above fails...
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
switchPanel(state, "Main");
}
public String buildToolViewPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.view"));
return "lti_error";
}
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getToolModel();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_main";
}
Long key = new Long(id);
Map<String,Object> tool = ltiService.getTool(key);
if ( tool == null ) return "lti_main";
// Deal with the differences between LTI 1 and LTI 2
Long version = foorm.getLongNull(tool.get(LTIService.LTI_VERSION));
boolean isLTI1 = version == null || version == LTIService.LTI_VERSION_1;
if ( isLTI1 ) {
mappingForm = foorm.filterForm(mappingForm, null, ".*:only=lti2.*");
} else {
mappingForm = foorm.filterForm(mappingForm, null, ".*:only=lti1.*");
}
// Extract the version to make it view only
String fieldInfo = foorm.getFormField(mappingForm, "version");
fieldInfo = fieldInfo.replace(":hidden=true","");
String formStatus = ltiService.formOutput(tool, fieldInfo);
context.put("formStatus", formStatus);
tool.put(LTIService.LTI_SECRET,SECRET_HIDDEN);
tool.put(LTIService.LTI_CONSUMERKEY,SECRET_HIDDEN);
String formOutput = ltiService.formOutput(tool, mappingForm);
context.put("formOutput", formOutput);
state.removeAttribute(STATE_SUCCESS);
return "lti_tool_view";
}
public String buildToolEditPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
String stateId = (String) state.getAttribute(STATE_ID);
state.removeAttribute(STATE_ID);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
context.put("doToolAction", BUTTON + "doToolPut");
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getToolModel();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) id = stateId;
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_main";
}
Long key = new Long(id);
Map<String,Object> tool = ltiService.getTool(key);
if ( tool == null ) return "lti_main";
// Hide the old tool secret unless it is incomplete
if ( ! LTIService.LTI_SECRET_INCOMPLETE.equals(tool.get(LTIService.LTI_SECRET)) ) {
tool.put(LTIService.LTI_SECRET,SECRET_HIDDEN);
}
// Deal with the differences between LTI 1 and LTI 2
Long version = foorm.getLongNull(tool.get(LTIService.LTI_VERSION));
boolean isLTI1 = version == null || version == LTIService.LTI_VERSION_1;
if ( isLTI1 ) {
mappingForm = foorm.filterForm(mappingForm, null, ".*:only=lti2.*");
} else {
mappingForm = foorm.filterForm(mappingForm, null, ".*:only=lti1.*");
}
// Extract the version to make it view only
String fieldInfo = foorm.getFormField(mappingForm, "version");
fieldInfo = fieldInfo.replace(":hidden=true","");
String formStatus = ltiService.formOutput(tool, fieldInfo);
context.put("formStatus", formStatus);
// If we are not admin, hide url, key, and secret
if ( ! isLTI1 && ! ltiService.isAdmin() ) {
mappingForm = foorm.filterForm(mappingForm, null, "^launch:.*|^consumerkey:.*|^secret:.*");
}
String formInput = ltiService.formInput(tool, mappingForm);
context.put("formInput", formInput);
state.removeAttribute(STATE_SUCCESS);
return "lti_tool_insert";
}
public String buildToolDeletePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
return "lti_error";
}
context.put("doToolAction", BUTTON + "doToolDelete");
String [] mappingForm = foorm.filterForm(ltiService.getToolModel(), "^title:.*|^launch:.*|^id:.*", null);
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_main";
}
Long key = new Long(id);
// Retrieve the tool using a WHERE clause so the counts get computed
List<Map<String,Object>> tools = ltiService.getTools("lti_tools.id = "+key,null,0,0);
if ( tools == null || tools.size() < 1 ) {
addAlert(state,rb.getString("error.tool.not.found"));
return "lti_main";
}
Map<String,Object> tool = tools.get(0);
String formOutput = ltiService.formOutput(tool, mappingForm);
context.put("formOutput", formOutput);
context.put("tool",tool);
context.put("tool_count", tool.get("lti_content_count"));
context.put("tool_unique_site_count", tool.get("lti_site_count"));
state.removeAttribute(STATE_SUCCESS);
return "lti_tool_delete";
}
public void doToolDelete(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
switchPanel(state, "Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
Object retval = null;
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
switchPanel(state, "ToolSystem");
return;
}
Long key = new Long(id);
if ( ltiService.deleteTool(key) )
{
state.setAttribute(STATE_SUCCESS,rb.getString("success.deleted"));
// remove all content object and site links if any
// this is for the "site tools" panel
List<Map<String,Object>> contents = ltiService.getContents(null,null,0,5000);
for ( Map<String,Object> content : contents ) {
Long tool_id_long = null;
try{
tool_id_long = new Long(content.get(LTIService.LTI_TOOL_ID).toString());
if (tool_id_long.equals(key))
{
// the content with same tool id
// remove the content link first
String content_id = content.get(LTIService.LTI_ID).toString();
Long content_key = content_id == null ? null:new Long(content_id);
//TODO: how to handle the errors in content link and content deletion?
// remove the external tool content site link
ltiService.deleteContentLink(content_key);
// remove the external tool content
ltiService.deleteContent(content_key);
}
}
catch (Exception e)
{
// log the error
M_log.error("error parsing tool id " + content.get(LTIService.LTI_TOOL_ID));
}
}
switchPanel(state, "ToolSystem");
} else {
addAlert(state,rb.getString("error.delete.fail"));
switchPanel(state, "ToolSystem");
}
}
public String buildToolInsertPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
context.put("doToolAction", BUTTON + "doToolPut");
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getToolModel();
mappingForm = foorm.filterForm(mappingForm, null, ".*:only=edit.*|.*:only=lti2.*");
Properties previousPost = (Properties) state.getAttribute(STATE_POST);
String formInput = ltiService.formInput(previousPost, mappingForm);
context.put("formInput",formInput);
state.removeAttribute(STATE_POST);
state.removeAttribute(STATE_SUCCESS);
return "lti_tool_insert";
}
// Insert or edit
public void doToolPut(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
switchPanel(state,"Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String newSecret = reqProps.getProperty(LTIService.LTI_SECRET);
if ( SECRET_HIDDEN.equals(newSecret) ) {
reqProps.remove(LTIService.LTI_SECRET);
newSecret = null;
}
if ( newSecret != null ) {
newSecret = SakaiBLTIUtil.encryptSecret(newSecret.trim());
reqProps.setProperty(LTIService.LTI_SECRET, newSecret);
}
String id = data.getParameters().getString(LTIService.LTI_ID);
String success = null;
Object retval = null;
if ( id == null )
{
retval = ltiService.insertTool(reqProps);
success = rb.getString("success.created");
} else {
Long key = new Long(id);
retval = ltiService.updateTool(key, reqProps);
success = rb.getString("success.updated");
}
if ( retval instanceof String )
{
state.setAttribute(STATE_POST,reqProps);
addAlert(state, (String) retval);
state.setAttribute(STATE_ID,id);
return;
}
state.setAttribute(STATE_SUCCESS,success);
switchPanel(state, "ToolSystem");
}
/** Deployment related methods ------------------------------ */
public String buildDeployInsertPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.edit"));
return "lti_error";
}
context.put("doDeployAction", BUTTON + "doDeployPut");
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
context.put("reg_state",new Integer(0));
String [] mappingForm = ltiService.getDeployModel();
mappingForm = foorm.filterForm(mappingForm, null, ".*:hide=insert.*");
Properties previousPost = (Properties) state.getAttribute(STATE_POST);
String formInput = ltiService.formInput(previousPost, mappingForm);
context.put("formInput",formInput);
state.removeAttribute(STATE_POST);
state.removeAttribute(STATE_SUCCESS);
return "lti_deploy_insert";
}
public String buildDeployViewPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.view"));
return "lti_error";
}
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getDeployModel();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_error";
}
Long key = new Long(id);
Map<String,Object> deploy = ltiService.getDeployDao(key);
if ( deploy == null ) return "lti_error";
// Extract the reg_state to make it view only
String fieldInfo = foorm.getFormField(mappingForm, "reg_state");
fieldInfo = fieldInfo.replace(":hidden=true","");
String formStatus = ltiService.formOutput(deploy, fieldInfo);
context.put("formStatus", formStatus);
String formOutput = ltiService.formOutput(deploy, mappingForm);
context.put("formOutput", formOutput);
Long reg_state = foorm.getLongNull(deploy.get(LTIService.LTI_REG_STATE));
context.put("reg_state",reg_state);
context.put("id",id);
state.removeAttribute(STATE_SUCCESS);
return "lti_deploy_view";
}
public String buildDeployEditPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
String stateId = (String) state.getAttribute(STATE_ID);
state.removeAttribute(STATE_ID);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.edit"));
return "lti_error";
}
context.put("doDeployAction", BUTTON + "doDeployPut");
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getDeployModel();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) id = stateId;
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_error";
}
Long key = new Long(id);
Map<String,Object> deploy = ltiService.getDeployDao(key);
if ( deploy == null ) return "lti_error";
// Extract the reg_state to make it view only
String fieldInfo = foorm.getFormField(mappingForm, "reg_state");
fieldInfo = fieldInfo.replace(":hidden=true","");
String formStatus = ltiService.formOutput(deploy, fieldInfo);
context.put("formStatus", formStatus);
Long reg_state = foorm.getLongNull(deploy.get(LTIService.LTI_REG_STATE));
context.put("reg_state",reg_state);
// Remove reg_state from the editable part of the model
mappingForm = foorm.filterForm(mappingForm, null, "^reg_state:.*");
String formInput = ltiService.formInput(deploy, mappingForm);
context.put("formInput", formInput);
state.removeAttribute(STATE_SUCCESS);
return "lti_deploy_insert";
}
// Insert or edit
public void doDeployPut(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.edit"));
switchPanel(state,"Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
// If we are inserting, fill in the blanks
if ( id == null ) {
reqProps.setProperty(LTIService.LTI_REG_KEY, UUID.randomUUID().toString());
// TODO: We should show off and encrypt the REG_PASSWORD too..
reqProps.setProperty(LTIService.LTI_REG_PASSWORD, UUID.randomUUID().toString());
reqProps.setProperty(LTIService.LTI_CONSUMERKEY, UUID.randomUUID().toString());
}
String success = null;
Object retval = null;
boolean lti2Insert = false;
if ( id == null )
{
retval = ltiService.insertDeployDao(reqProps);
success = rb.getString("success.created");
lti2Insert = true;
} else {
Long key = new Long(id);
retval = ltiService.updateDeployDao(key, reqProps);
success = rb.getString("success.updated");
}
if ( retval instanceof String )
{
state.setAttribute(STATE_POST,reqProps);
addAlert(state, (String) retval);
state.setAttribute(STATE_ID,id);
return;
}
state.setAttribute(STATE_SUCCESS,success);
if ( lti2Insert && retval instanceof Long ) {
Long insertedKey = (Long) retval;
switchPanel(state, "DeployRegister&id="+insertedKey);
} else {
switchPanel(state, "DeploySystem");
}
}
public String buildDeployRegisterPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.activate"));
return "lti_error";
}
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = foorm.filterForm(ltiService.getDeployModel(), "^title:.*|^reg_state:.*|^reg_launch:.*|^id:.*", null);
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_error";
}
Long key = new Long(id);
Map<String,Object> deploy = ltiService.getDeployDao(key);
if ( deploy == null ) {
addAlert(state,rb.getString("error.deploy.not.found"));
return "lti_error";
}
Long reg_state = foorm.getLongNull(deploy.get(LTIService.LTI_REG_STATE));
String reg_key = (String) deploy.get(LTIService.LTI_REG_KEY);
String reg_password = (String) deploy.get(LTIService.LTI_REG_PASSWORD);
String consumerkey = (String) deploy.get(LTIService.LTI_CONSUMERKEY);
String secret = (String) deploy.get(LTIService.LTI_SECRET);
if ( reg_state == 0 && reg_key != null && reg_password != null && consumerkey != null) {
// Good news ...
} else if ( (reg_state == 1 || reg_state == 2 ) && secret != null && consumerkey != null) {
// Good news ...
} else {
addAlert(state,rb.getString("error.register.not.ready"));
return "lti_error";
}
// Extract the reg_state to make it view only
String fieldInfo = foorm.getFormField(mappingForm, "reg_state");
fieldInfo = fieldInfo.replace(":hidden=true","");
String formStatus = ltiService.formOutput(deploy, fieldInfo);
context.put("formStatus", formStatus);
String formOutput = ltiService.formOutput(deploy, mappingForm);
context.put("formOutput", formOutput);
Placement placement = toolManager.getCurrentPlacement();
String registerURL = "/access/basiclti/site/~admin/deploy:" + key + "?placement=" + placement.getId();
context.put("registerURL",registerURL);
state.removeAttribute(STATE_SUCCESS);
return "lti_deploy_register";
}
public String buildActivatePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.activate"));
return "lti_error";
}
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
String [] mappingForm = ltiService.getDeployModel();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_error";
}
Long key = null;
try {
key = new Long(id);
} catch(Exception e) {
return "Non-numeric id value "+id;
}
Map<String,Object> deploy = ltiService.getDeployDao(key);
if ( deploy == null ) return "lti_error";
String profileText = (String) deploy.get(LTIService.LTI_REG_PROFILE);
if ( profileText == null || profileText.length() < 1 ) {
addAlert(state,rb.getString("error.activate.not.ready"));
return "lti_error";
}
// Load and check the tools from the profile
List<Map<String,Object>> theTools = new ArrayList<Map<String,Object>> ();
Properties info = new Properties();
String retval = prepareValidate(deploy, theTools, info, state);
if ( retval != null ) return retval;
context.put("info", info);
context.put("deploy", deploy);
context.put("tools", theTools);
context.put("profile", profileText);
context.put("doAction", BUTTON + "doActivate");
return "lti_deploy_activate";
}
public void doActivate(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.activate"));
switchPanel(state, "Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
switchPanel(state, "DeploySystem");
return;
}
Long key = new Long(id);
Map<String,Object> deploy = ltiService.getDeployDao(key);
if ( deploy == null ) {
addAlert(state,rb.getString("error.deploy.not.found"));
switchPanel(state, "DeploySystem");
return;
}
List<Map<String,Object>> theTools = new ArrayList<Map<String,Object>> ();
Properties info = new Properties();
String prepare = prepareValidate(deploy, theTools, info, state);
M_log.info("Starting activation process for id="+key+" title="+info.get("title"));
int inserts = 0;
int updates = 0;
String failures = "";
for ( Map<String, Object> theTool : theTools ) {
Object retval = null;
Long toolId = foorm.getLongNull(theTool.get(LTIService.LTI_ID));
theTool.put(LTIService.LTI_VERSION, LTIService.LTI_VERSION_2);
if ( toolId == null ) {
retval = ltiService.insertTool(theTool);
if ( retval instanceof String ) {
String oops = "Unable to insert "+theTool.get(LTIService.LTI_RESOURCE_HANDLER)+" "+retval;
M_log.error(oops);
failures += "\n" + oops;
} else {
M_log.info("Inserted tool="+retval+" "+theTool.get(LTIService.LTI_RESOURCE_HANDLER));
inserts++;
}
} else {
retval = ltiService.updateTool(toolId, theTool);
if ( retval instanceof String ) {
String oops = "Unable to update "+theTool.get(LTIService.LTI_RESOURCE_HANDLER)+" "+retval;
M_log.error(oops);
failures += "\n" + oops;
} else {
M_log.info("Updated tool="+toolId+" "+theTool.get(LTIService.LTI_RESOURCE_HANDLER));
updates++;
}
}
}
// Update reg_state to indicate we are activated...
Map<String, Object> deployUpdate = new HashMap<String, Object> ();
deployUpdate.put(LTIService.LTI_REG_STATE, "2");
Object obj = ltiService.updateDeployDao(key, deployUpdate);
boolean updated = ( obj instanceof Boolean ) && ( (Boolean) obj == Boolean.TRUE);
if ( !updated ) {
String oops = "Unable to update deployment key="+key;
M_log.error(oops);
failures += "\n" + oops;
}
// We can have a combination of successes and failures...
String success = "";
if ( inserts > 0 ) success = inserts + " tools inserted ";
if ( updates > 0 ) success = updates + " tools updated ";
if ( success.length() > 0 ) state.setAttribute(STATE_SUCCESS,success);
if ( failures.length() > 0 )
{
state.setAttribute(STATE_POST,reqProps);
addAlert(state, failures);
}
switchPanel(state, "DeploySystem");
}
public String prepareValidate(Map<String,Object> deploy, List<Map<String,Object>> theTools,
Properties info, SessionState state)
{
Long reg_state = foorm.getLongNull(deploy.get(LTIService.LTI_REG_STATE));
String profileText = (String) deploy.get(LTIService.LTI_REG_PROFILE);
if ( profileText == null || profileText.length() < 1 ) {
addAlert(state,rb.getString("error.activate.not.ready"));
return "lti_error";
}
JSONObject providerProfile = (JSONObject) JSONValue.parse(profileText);
List<Properties> profileTools = new ArrayList<Properties> ();
try {
String retval = LTI2Util.parseToolProfile(profileTools, info, providerProfile);
if ( retval != null ) {
addAlert(state,rb.getString("deploy.parse.error")+" "+retval);
return "lti_error";
}
}
catch (Exception e ) {
addAlert(state,rb.getString("deploy.parse.exception")+" "+e.getLocalizedMessage());
e.printStackTrace();
return "lti_error";
}
String vendor_code = (String) info.get("vendor_code");
String product_code = (String) info.get("product_code");
if ( profileTools.size() < 1 ) {
addAlert(state,rb.getString("deploy.activate.notools"));
return "lti_error";
}
// Check them all first
for ( Properties profileTool : profileTools ) {
String launch = (String) profileTool.get(LTIService.LTI_LAUNCH);
if ( ! FormattedText.validateURL(launch) ) {
addAlert(state,rb.getString("deploy.activate.badlaunch")+" "+launch);
return "lti_error";
}
}
// Make a copy of the deploy object and clean it up
Map<String, Object> localDeploy = new HashMap<String, Object> ();
localDeploy.putAll(deploy);
localDeploy.remove(LTIService.LTI_ID);
localDeploy.remove(LTIService.LTI_CREATED_AT);
localDeploy.remove(LTIService.LTI_UPDATED_AT);
localDeploy.remove(LTIService.LTI_REG_PROFILE);
// Loop through all of the tools
for ( Properties profileTool : profileTools ) {
String resource_type_code = (String) profileTool.get("resource_type_code");
String resource_handler = vendor_code;
if ( ! resource_handler.endsWith("/") && ! resource_handler.startsWith("/") ) resource_handler = resource_handler + "/" ;
resource_handler = resource_handler + product_code;
if ( ! resource_handler.endsWith("/") && ! resource_handler.startsWith("/") ) resource_handler = resource_handler + "/" ;
resource_handler = resource_handler + resource_type_code;
Map<String,Object> tool = ltiService.getToolForResourceHandlerDao(resource_handler);
// Construct a new tool object
Map<String, Object> newTool = new HashMap<String, Object> ();
if ( tool != null ) {
newTool.putAll(tool);
newTool.putAll(localDeploy); // New settings from the deployment
} else {
newTool.putAll(localDeploy);
}
newTool.put(LTIService.LTI_RESOURCE_HANDLER, resource_handler);
newTool.put(LTIService.LTI_DEPLOYMENT_ID, deploy.get(LTIService.LTI_ID));
// Copy explicitly in case the parser changes slightly
if ( profileTool.get(LTIService.LTI_LAUNCH) != null ) newTool.put(LTIService.LTI_LAUNCH, profileTool.get(LTIService.LTI_LAUNCH));
if ( profileTool.get(LTIService.LTI_TITLE) != null ) newTool.put(LTIService.LTI_TITLE, profileTool.get(LTIService.LTI_TITLE));
if ( profileTool.get(LTIService.LTI_TITLE) != null ) newTool.put(LTIService.LTI_PAGETITLE, profileTool.get(LTIService.LTI_TITLE)); // Duplicate by default
if ( profileTool.get("button") != null ) newTool.put(LTIService.LTI_PAGETITLE, profileTool.get("button")); // Note different fields
if ( profileTool.get(LTIService.LTI_DESCRIPTION) != null ) newTool.put(LTIService.LTI_DESCRIPTION, profileTool.get(LTIService.LTI_DESCRIPTION));
if ( profileTool.get(LTIService.LTI_PARAMETER) != null ) newTool.put(LTIService.LTI_PARAMETER, profileTool.get(LTIService.LTI_PARAMETER));
if ( profileTool.get(LTIService.LTI_ENABLED_CAPABILITY) != null ) newTool.put(LTIService.LTI_ENABLED_CAPABILITY, profileTool.get(LTIService.LTI_ENABLED_CAPABILITY));
System.out.println("newTool="+newTool);
theTools.add(newTool);
}
return null; // Success
}
public String buildDeploySystemPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.admin.view"));
return "lti_error";
}
String contextString = toolManager.getCurrentPlacement().getContext();
context.put("ltiService", ltiService);
state.removeAttribute(STATE_POST);
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
context.put("getContext", contextString);
state.removeAttribute(STATE_SUCCESS);
List<Map<String,Object>> deploys = ltiService.getDeploysDao(null,null,0,5000);
context.put("deploys", deploys);
// Check if we are configured
LTI2Config cnf = new SakaiLTI2Config();
if ( cnf.getGuid() == null ) {
context.put("alertMessage",rb.getString("error.deploy.not.config"));
M_log.error("*********************************************");
M_log.error("* LTI2 NOT CONFIGURED - Using Sample Data *");
M_log.error("* Do not use this in production. Test only *");
M_log.error("*********************************************");
}
return "lti_deploy_system";
}
public String buildDeployDeletePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isAdmin() ) {
addAlert(state,rb.getString("error.maintain.delete"));
return "lti_error";
}
context.put("doAction", BUTTON + "doDeployDelete");
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_deploy_system";
}
Long key = new Long(id);
// Retrieve the tool using a WHERE clause so the counts get computed
List<Map<String,Object>> deploys = ltiService.getDeploysDao("lti_deploy.id = "+key,null,0,0);
if ( deploys == null || deploys.size() < 1 ) {
addAlert(state,rb.getString("error.deploy.not.found"));
return "lti_deploy_system";
}
Map<String,Object> deploy = deploys.get(0);
context.put("deploy",deploy);
String [] mappingForm = foorm.filterForm(ltiService.getDeployModel(), "^title:.*|^reg_launch:.*|^id:.*", null);
String formOutput = ltiService.formOutput(deploy, mappingForm);
context.put("formOutput", formOutput);
String deployData = rb.getString("deploy.data");
deployData = deployData.replace(":tools",""+deploy.get("lti_tool_count"))
.replace(":contents",""+deploy.get("lti_content_count"))
.replace(":sites",""+deploy.get("lti_site_count"));
context.put("deployData", deployData);
state.removeAttribute(STATE_SUCCESS);
return "lti_deploy_delete";
}
public void doDeployDelete(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
switchPanel(state, "Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
Object retval = null;
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
switchPanel(state, "Deploy");
return;
}
Long key = new Long(id);
// also remove the link
if ( ltiService.deleteDeployDao(key) )
{
state.setAttribute(STATE_SUCCESS,rb.getString("success.deleted"));
} else {
addAlert(state,rb.getString("error.delete.fail"));
}
switchPanel(state, "DeploySystem");
}
/** Content related methods ------------------------------ */
public String buildContentPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.view"));
return "lti_error";
}
List<Map<String,Object>> contents = ltiService.getContents(null,null,0,5000);
for ( Map<String,Object> content : contents ) {
String plstr = (String) content.get(LTIService.LTI_PLACEMENT);
ToolConfiguration tool = SiteService.findTool(plstr);
if ( tool == null ) {
content.put(LTIService.LTI_PLACEMENT, null);
}
}
context.put("contents", contents);
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("getContext",toolManager.getCurrentPlacement().getContext());
state.removeAttribute(STATE_SUCCESS);
return "lti_content";
}
public String buildContentPutPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
String contextString = toolManager.getCurrentPlacement().getContext();
context.put("tlang", rb);
String stateToolId = (String) state.getAttribute(STATE_TOOL_ID);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("doAction", BUTTON + "doContentPut");
state.removeAttribute(STATE_SUCCESS);
List<Map<String,Object>> tools = ltiService.getTools(null,null,0,0);
// only list the tools available in the system
List<Map<String,Object>> systemTools = new ArrayList<Map<String,Object>>();
for(Map<String, Object> tool:tools)
{
String siteId = !tool.containsKey(ltiService.LTI_SITE_ID)?null:StringUtils.trimToNull((String) tool.get(ltiService.LTI_SITE_ID));
if (siteId == null)
{
// add tool for whole system
systemTools.add(tool);
}
else if (siteId.equals(contextString))
{
// add the tool for current site only
systemTools.add(tool);
}
else if (ltiService.isAdmin())
{
// if in Admin's my workspace, show all tools
systemTools.add(tool);
}
}
context.put("tools", systemTools);
Object previousData = null;
String toolId = data.getParameters().getString(LTIService.LTI_TOOL_ID);
if ( toolId == null ) toolId = stateToolId;
// output the tool id value to context
context.put("tool_id", toolId);
Long key = null;
if ( toolId != null ) key = new Long(toolId);
Map<String,Object> tool = null;
if ( key != null ) {
tool = ltiService.getTool(key);
if ( tool == null ) {
addAlert(state, rb.getString("error.tool.not.found"));
return "lti_content_insert";
}
}
String contentId = data.getParameters().getString(LTIService.LTI_ID);
if ( contentId == null ) contentId = (String) state.getAttribute(STATE_CONTENT_ID);
if ( contentId == null ) { // Insert
if ( toolId == null ) {
return "lti_content_insert";
}
previousData = (Properties) state.getAttribute(STATE_POST);
// Edit
} else {
Long contentKey = new Long(contentId);
Map<String,Object> content = ltiService.getContent(contentKey);
if ( content == null ) {
addAlert(state, rb.getString("error.content.not.found"));
state.removeAttribute(STATE_CONTENT_ID);
return "lti_content";
}
if ( key == null ) {
key = foorm.getLongNull(content.get(LTIService.LTI_TOOL_ID));
if ( key != null ) tool = ltiService.getTool(key);
}
previousData = content;
// whether the content has a site link created already?
String plstr = (String) content.get(LTIService.LTI_PLACEMENT);
ToolConfiguration siteLinkTool = SiteService.findTool(plstr);
if ( siteLinkTool != null ) {
context.put(LTIService.LTI_PLACEMENT, plstr);
}
}
// We will handle the tool_id field ourselves in the Velocity code
String [] contentForm = foorm.filterForm(null,ltiService.getContentModel(key), null, "^tool_id:.*");
if ( contentForm == null || key == null ) {
addAlert(state,rb.getString("error.tool.not.found"));
return "lti_error";
}
String formInput = ltiService.formInput(previousData, contentForm);
context.put("formInput",formInput);
context.put(LTIService.LTI_TOOL_ID,key);
if ( tool != null ) {
context.put("tool_description", tool.get(LTIService.LTI_DESCRIPTION));
Long visible = foorm.getLong(tool.get(LTIService.LTI_VISIBLE));
context.put("tool_visible", visible);
}
return "lti_content_insert";
}
// Insert or edit
public void doContentPut(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
state.removeAttribute(STATE_POST);
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
String toolId = data.getParameters().getString(LTIService.LTI_TOOL_ID);
Object retval = ltiService.insertToolContent(id, toolId, reqProps);
Long contentKey = null;
Map<String,Object> content = null;
if ( retval instanceof String )
{
addAlert(state, (String) retval);
switchPanel(state, "Error");
state.setAttribute(STATE_POST,reqProps);
state.setAttribute(STATE_CONTENT_ID,id);
return;
}
else if ( retval instanceof Boolean )
{
// TODO: returns boolean
}
else
{
// the return value is the content key Long value
id = ((Long) retval).toString();
contentKey = new Long(id);
content = ltiService.getContent(contentKey);
if ( content == null ) {
addAlert(state, rb.getString("error.content.not.found"));
switchPanel(state, "Error");
state.setAttribute(STATE_POST,reqProps);
state.setAttribute(STATE_CONTENT_ID,id);
return;
}
}
String returnUrl = reqProps.getProperty("returnUrl");
if ( returnUrl != null )
{
if ( id != null ) {
if ( returnUrl.startsWith("about:blank") ) { // Redirect to the item
if ( content != null ) {
String launch = (String) ltiService.getContentLaunch(content);
if ( launch != null ) returnUrl = launch;
}
switchPanel(state, "Forward");
} else {
if ( returnUrl.indexOf("?") > 0 ) {
returnUrl += "<iItemId=/blti/" + retval;
} else {
returnUrl += "?ltiItemId=/blti/" + retval;
}
switchPanel(state, "Redirect");
}
}
state.setAttribute(STATE_REDIRECT_URL,returnUrl);
return;
}
String success = null;
if ( id == null )
{
success = rb.getString("success.created");
} else {
success = rb.getString("success.updated");
}
state.setAttribute(STATE_SUCCESS,success);
String title = data.getParameters().getString(LTIService.LTI_PAGETITLE);
// Take the title from the content (or tool) definition
if (title == null || title.trim().length() < 1 ) {
if ( content != null ) {
title = (String) content.get(ltiService.LTI_PAGETITLE);
}
}
if (reqProps.getProperty("add_site_link") != null)
{
// this is to add site link:
retval = ltiService.insertToolSiteLink(id, title);
if ( retval instanceof String ) {
String prefix = ((String) retval).substring(0,2);
addAlert(state, ((String) retval).substring(2));
if ("0-".equals(prefix))
{
switchPanel(state, "Refresh");
}
else if ("1-".equals(prefix))
{
switchPanel(state, "Error");
}
return;
}
else if ( retval instanceof Boolean ) {
if (((Boolean) retval).booleanValue())
{
switchPanel(state, "Refresh");
}
else
{
switchPanel(state, "Error");
}
return;
}
state.setAttribute(STATE_SUCCESS,rb.getString("success.link.add"));
}
switchPanel(state, "ToolSite");
}
public String buildRedirectPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
String returnUrl = (String) state.getAttribute(STATE_REDIRECT_URL);
state.removeAttribute(STATE_REDIRECT_URL);
if ( returnUrl == null ) return "lti_content_redirect";
// System.out.println("Redirecting parent frame back to="+returnUrl);
if ( ! returnUrl.startsWith("about:blank") ) context.put("returnUrl",returnUrl);
return "lti_content_redirect";
}
public String buildForwardPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
String returnUrl = (String) state.getAttribute(STATE_REDIRECT_URL);
state.removeAttribute(STATE_REDIRECT_URL);
if ( returnUrl == null ) return "lti_content_redirect";
// System.out.println("Forwarding frame to="+returnUrl);
context.put("forwardUrl",returnUrl);
return "lti_content_redirect";
}
// Special panel for Lesson Builder
// Add New: panel=Config&tool_id=14
// Edit existing: panel=Config&id=12
public String buildContentConfigPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
state.removeAttribute(STATE_SUCCESS);
Properties previousPost = (Properties) state.getAttribute(STATE_POST);
state.removeAttribute(STATE_POST);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.edit"));
return "lti_error";
}
String returnUrl = data.getParameters().getString("returnUrl");
if ( returnUrl == null && previousPost != null ) returnUrl = previousPost.getProperty("returnUrl");
if ( returnUrl == null ) {
addAlert(state,rb.getString("error.missing.return"));
return "lti_error";
}
Map<String,Object> content = null;
Map<String,Object> tool = null;
Long toolKey = foorm.getLongNull(data.getParameters().getString(LTIService.LTI_TOOL_ID));
Long contentKey = foorm.getLongNull(data.getParameters().getString(LTIService.LTI_ID));
if ( contentKey == null && previousPost != null ) contentKey = foorm.getLongNull(previousPost.getProperty(LTIService.LTI_ID));
if ( contentKey != null ) {
content = ltiService.getContent(contentKey);
if ( content == null ) {
addAlert(state, rb.getString("error.content.not.found"));
state.removeAttribute(STATE_CONTENT_ID);
return "lti_error";
}
toolKey = foorm.getLongNull(content.get(LTIService.LTI_TOOL_ID));
}
if ( toolKey == null && previousPost != null ) toolKey = foorm.getLongNull(previousPost.getProperty(LTIService.LTI_TOOL_ID));
if ( toolKey != null ) tool = ltiService.getTool(toolKey);
// No matter what, we must have a tool
if ( tool == null ) {
addAlert(state, rb.getString("error.tool.not.found"));
return "lti_error";
}
Object previousData = null;
if ( content != null ) {
previousData = content;
} else {
previousData = (Properties) state.getAttribute(STATE_POST);
}
// We will handle the tool_id field ourselves in the Velocity code
String [] contentForm = foorm.filterForm(null,ltiService.getContentModel(toolKey), null, "^tool_id:.*|^SITE_ID:.*");
if ( contentForm == null ) {
addAlert(state,rb.getString("error.tool.not.found"));
return "lti_error";
}
context.put("isAdmin",new Boolean(ltiService.isAdmin()) );
context.put("doAction", BUTTON + "doContentPut");
if ( ! returnUrl.startsWith("about:blank") ) context.put("cancelUrl", returnUrl);
context.put("returnUrl", returnUrl);
context.put(LTIService.LTI_TOOL_ID,toolKey);
context.put("tool_description", tool.get(LTIService.LTI_DESCRIPTION));
context.put("tool_title", tool.get(LTIService.LTI_TITLE));
context.put("tool_launch", tool.get(LTIService.LTI_LAUNCH));
String key = (String) tool.get(LTIService.LTI_CONSUMERKEY);
String secret = (String) tool.get(LTIService.LTI_SECRET);
if ( LTIService.LTI_SECRET_INCOMPLETE.equals(secret) && LTIService.LTI_SECRET_INCOMPLETE.equals(key) ) {
String keyField = foorm.formInput(null,"consumerkey:text:label=need.tool.key:required=true:maxlength=255", rb);
context.put("keyField", keyField);
String secretField = foorm.formInput(null,"secret:text:required=true:label=need.tool.secret:maxlength=255", rb);
context.put("secretField", secretField);
}
String formInput = ltiService.formInput(previousData, contentForm);
context.put("formInput",formInput);
return "lti_content_config";
}
public String buildContentDeletePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
return "lti_error";
}
context.put("doAction", BUTTON + "doContentDelete");
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_deploy_system";
}
Long key = new Long(id);
Map<String,Object> content = ltiService.getContent(key);
if ( content == null ) {
addAlert(state,rb.getString("error.content.not.found"));
return "lti_deploy_system";
}
Long tool_id_long = null;
try{
tool_id_long = new Long(content.get(LTIService.LTI_TOOL_ID).toString());
}
catch (Exception e)
{
// log the error
M_log.error("error parsing tool id " + content.get(LTIService.LTI_TOOL_ID));
}
context.put("tool_id_long", tool_id_long);
context.put("content",content);
context.put("ltiService", ltiService);
state.removeAttribute(STATE_SUCCESS);
return "lti_content_delete";
}
// Insert or edit
public void doContentDelete(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.delete"));
switchPanel(state, "Error");
return;
}
Properties reqProps = data.getParameters().getProperties();
String id = data.getParameters().getString(LTIService.LTI_ID);
Object retval = null;
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
switchPanel(state, "DeploySystem");
return;
}
Long key = new Long(id);
// also remove the link
if ( ltiService.deleteContent(key) )
{
state.setAttribute(STATE_SUCCESS,rb.getString("success.deleted"));
} else {
addAlert(state,rb.getString("error.delete.fail"));
}
switchPanel(state, "Refresh");
}
public String buildLinkAddPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.link"));
return "lti_error";
}
context.put("doAction", BUTTON + "doSiteLink");
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_deploy_system";
}
Long key = new Long(id);
Map<String,Object> content = ltiService.getContent(key);
if ( content == null ) {
addAlert(state,rb.getString("error.content.not.found"));
return "lti_deploy_system";
}
context.put("content",content);
state.removeAttribute(STATE_SUCCESS);
return "lti_link_add";
}
// Insert or edit
public void doSiteLink(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
String id = data.getParameters().getString(LTIService.LTI_ID);
String button_text = data.getParameters().getString("button_text");
Object retval = ltiService.insertToolSiteLink(id, button_text);
if ( retval instanceof String ) {
String prefix = ((String) retval).substring(0,2);
addAlert(state, ((String) retval).substring(2));
if ("0-".equals(prefix))
{
switchPanel(state, "Content");
}
else if ("1-".equals(prefix))
{
switchPanel(state, "Error");
}
return;
}
state.setAttribute(STATE_SUCCESS,rb.getString("success.link.add"));
switchPanel(state, "Refresh");
}
public String buildLinkRemovePanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
if ( ! ltiService.isMaintain() ) {
addAlert(state,rb.getString("error.maintain.link"));
return "lti_error";
}
context.put("doAction", BUTTON + "doLinkRemove");
String id = data.getParameters().getString(LTIService.LTI_ID);
if ( id == null ) {
addAlert(state,rb.getString("error.id.not.found"));
return "lti_main";
}
Long key = new Long(id);
Map<String,Object> content = ltiService.getContent(key);
if ( content == null ) {
addAlert(state,rb.getString("error.content.not.found"));
return "lti_main";
}
context.put("content",content);
state.removeAttribute(STATE_SUCCESS);
return "lti_link_remove";
}
public void doLinkRemove(RunData data, Context context)
{
String peid = ((JetspeedRunData) data).getJs_peid();
SessionState state = ((JetspeedRunData) data).getPortletSessionState(peid);
String id = data.getParameters().getString(LTIService.LTI_ID);
Long key = id == null ? null:new Long(id);
String rv = ltiService.deleteContentLink(key);
if (rv != null)
{
// there is error removing the external tool site link
addAlert(state, rv);
switchPanel(state, "Error");
return;
}
else
{
// external tool site link removed successfully
state.setAttribute(STATE_SUCCESS,rb.getString("success.link.remove"));
switchPanel(state, "Refresh");
}
}
public String buildRefreshPanelContext(VelocityPortlet portlet, Context context,
RunData data, SessionState state)
{
context.put("tlang", rb);
context.put("messageSuccess",state.getAttribute(STATE_SUCCESS));
state.removeAttribute(STATE_SUCCESS);
return "lti_top_refresh";
}
}