Java tutorial
/** * $URL$ * $Id$ * * Copyright (c) 2009 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.portlets; import org.imsglobal.basiclti.BasicLTIUtil; import java.lang.Integer; import java.io.PrintWriter; import java.io.IOException; import java.net.URL; import java.net.URI; import java.util.UUID; import java.util.Properties; import java.util.Map; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import java.util.Date; import java.text.SimpleDateFormat; import javax.portlet.GenericPortlet; import javax.portlet.RenderRequest; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.RenderResponse; import javax.portlet.PortletRequest; import javax.portlet.PortletException; import javax.portlet.PortletPreferences; import javax.portlet.PortletContext; import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletConfig; import javax.portlet.PortletMode; import javax.portlet.PortletSession; import javax.portlet.ReadOnlyException; import javax.servlet.ServletRequest; import org.sakaiproject.thread_local.cover.ThreadLocalManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.portlet.util.PortletHelper; // Sakai APIs import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.tool.cover.ToolManager; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.site.api.ToolConfiguration; import org.sakaiproject.tool.api.Placement; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SitePage; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.util.ResourceLoader; import org.sakaiproject.util.FormattedText; import org.sakaiproject.event.api.Event; import org.sakaiproject.event.api.NotificationService; //import org.sakaiproject.event.cover.EventTrackingService; import org.sakaiproject.basiclti.LocalEventTrackingService; import org.sakaiproject.basiclti.util.SakaiBLTIUtil; import org.sakaiproject.basiclti.util.SimpleEncryption; import org.sakaiproject.service.gradebook.shared.Assignment; import org.sakaiproject.service.gradebook.shared.AssignmentHasIllegalPointsException; import org.sakaiproject.service.gradebook.shared.CategoryDefinition; import org.sakaiproject.service.gradebook.shared.GradebookService; import org.sakaiproject.service.gradebook.shared.GradebookExternalAssessmentService; import org.sakaiproject.service.gradebook.shared.ConflictingAssignmentNameException; import org.sakaiproject.service.gradebook.shared.ConflictingExternalIdException; import org.sakaiproject.service.gradebook.shared.GradebookNotFoundException; /** * a simple IMSBLTIPortlet Portlet */ @SuppressWarnings("deprecation") public class IMSBLTIPortlet extends GenericPortlet { private static ResourceLoader rb = new ResourceLoader("basiclti"); private PortletContext pContext; private ArrayList<String> fieldList = new ArrayList<String>(); /** Our log (commons). */ private static Log M_log = LogFactory.getLog(IMSBLTIPortlet.class); public static final String EVENT_BASICLTI_CONFIG = "basiclti.config"; private static String LEAVE_SECRET_ALONE = "__dont_change_secret__"; /** To turn on really verbose debugging */ private static boolean verbosePrint = false; public static final String ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ssz"; public final static String CURRENT_HTTP_REQUEST = "org.sakaiproject.util.RequestFilter.http_request"; public static final String SITE_NAME = "ui.service"; public static final String SAKAI = "Sakai"; public void init(PortletConfig config) throws PortletException { super.init(config); pContext = config.getPortletContext(); // Populate the list of fields fieldList.add("launch"); fieldList.add("secret"); fieldList.add("key"); fieldList.add("xml"); fieldList.add("frameheight"); fieldList.add("debug"); fieldList.add("pagetitle"); fieldList.add("tooltitle"); fieldList.add("custom"); fieldList.add("releasename"); fieldList.add("releaseemail"); fieldList.add("assignment"); fieldList.add("newpage"); // fieldList.add("maximize"); fieldList.add("allowsettings"); fieldList.add("allowroster"); fieldList.add("contentlink"); fieldList.add("splash"); fieldList.add("fa_icon"); } // Simple Debug Print Mechanism public void dPrint(String str) { if (verbosePrint) System.out.println(str); M_log.trace(str); } // If the property is final, the property wins. If it is not final, // the portlet preferences take precedence. public String getTitleString(RenderRequest request) { return getCorrectProperty(request, "tooltitle", null); } // Render the portlet - this is not supposed to change the state of the portlet // Render may be called many times so if it changes the state - that is tacky // Render will be called when someone presses "refresh" or when another portlet // on the same page is handed an Action. public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { dPrint("==== doView called ===="); response.setContentType("text/html; charset=UTF-8"); // Grab that underlying request to get a GET parameter ServletRequest req = (ServletRequest) ThreadLocalManager.get(CURRENT_HTTP_REQUEST); String popupDone = req.getParameter("sakai.popup"); PrintWriter out = response.getWriter(); String title = getTitleString(request); if (title != null) response.setTitle(title); String context = getContext(); Placement placement = ToolManager.getCurrentPlacement(); // Get the properties Properties sakaiProperties = getSakaiProperties(); String placementSecret = getSakaiProperty(sakaiProperties, "imsti.placementsecret"); String allowOutcomes = getSakaiProperty(sakaiProperties, "imsti.allowoutcomes"); String allowSettings = getSakaiProperty(sakaiProperties, "imsti.allowsettings"); String allowRoster = getSakaiProperty(sakaiProperties, "imsti.allowroster"); String assignment = getSakaiProperty(sakaiProperties, "imsti.assignent"); String launch = getSakaiProperty(sakaiProperties, "imsti.launch"); if (placementSecret == null && ("on".equals(allowOutcomes) || "on".equals(allowSettings) || "on".equals(allowRoster))) { String uuid = UUID.randomUUID().toString(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_FORMAT); String date_secret = sdf.format(date); placement.getPlacementConfig().setProperty("imsti.placementsecret", uuid); placement.getPlacementConfig().setProperty("imsti.placementsecretdate", date_secret); placement.save(); } // Check to see if our launch will be successful String[] retval = SakaiBLTIUtil.postLaunchHTML(placement.getId(), rb); if (retval.length > 1) { String iframeUrl = "/access/basiclti/site/" + context + "/" + placement.getId(); String frameHeight = getCorrectProperty(request, "frameheight", null); dPrint("fh=" + frameHeight); String newPage = getCorrectProperty(request, "newpage", null); String serverUrl = ServerConfigurationService.getServerUrl(); boolean forcePopup = false; if (request.isSecure() || (serverUrl != null && serverUrl.startsWith("https://"))) { if (launch != null && launch.startsWith("http://")) { forcePopup = true; } } // Change "newpage" if forcePopup so the portal will do our pop up next time if (forcePopup && !"on".equals(newPage)) { placement.getPlacementConfig().setProperty("imsti.newpage", "on"); placement.save(); } String maximize = getCorrectProperty(request, "maximize", null); StringBuffer text = new StringBuffer(); Session session = SessionManager.getCurrentSession(); session.setAttribute("sakai:maximized-url", iframeUrl); dPrint("Setting sakai:maximized-url=" + iframeUrl); if ("on".equals(newPage) || forcePopup) { String windowOpen = "window.open('" + iframeUrl + "','BasicLTI');"; if (popupDone == null) { text.append("<p>\n"); text.append("<script type=\"text/javascript\">\n"); text.append(windowOpen + "\n"); text.append("</script>\n"); } String siteName = ServerConfigurationService.getString(SITE_NAME, SAKAI); title = title != null ? title : rb.getString("tool.name", "your tool"); String newPageLaunchText = rb.getFormattedMessage("new.page.launch", new Object[] { FormattedText.escapeHtml(title, false), FormattedText.escapeHtml(siteName, false) }); text.append(newPageLaunchText); text.append("</p>\n"); text.append("<input type=\"submit\" onclick=\"" + windowOpen + "\" target=\"BasicLTI\" value=\"Launch " + title + "\"/>"); } else { if ("on".equals(maximize)) { text.append("<script type=\"text/javascript\" language=\"JavaScript\">\n"); text.append("try { portalMaximizeTool(); } catch (err) { }\n"); text.append("</script>\n"); } text.append("<iframe "); if (frameHeight == null) frameHeight = "1200"; text.append("height=\"" + frameHeight + "\" \n"); text.append("width=\"100%\" frameborder=\"0\" marginwidth=\"0\"\n"); text.append("marginheight=\"0\" scrolling=\"auto\"\n"); text.append("src=\"" + iframeUrl + "\">\n"); text.append(rb.getString("noiframes")); text.append("<br>"); text.append("<a href=\"" + iframeUrl + "\">"); text.append(rb.getString("noiframe.press.here")); text.append("</a>\n"); text.append("</iframe>"); } out.println(text); dPrint("==== doView complete ===="); return; } else { out.println(rb.getString("not.configured")); } clearErrorMessage(request); dPrint("==== doView complete ===="); } // Prepare the edit screen with data public void prepareEdit(RenderRequest request) { // Hand up the tool properties Placement placement = ToolManager.getCurrentPlacement(); Properties config = placement.getConfig(); dPrint("placement=" + placement.getId()); dPrint("placement.toolId=" + placement.getToolId()); dPrint("properties=" + config); for (String element : fieldList) { String propertyName = placement.getToolId() + "." + element; String propValue = ServerConfigurationService.getString(propertyName, null); if ("splash".equals(element) && propValue == null) { propValue = ServerConfigurationService.getString(placement.getToolId() + ".overridesplash", null); } if (propValue != null && propValue.trim().length() > 0) { dPrint("Forcing Final = " + propertyName); config.setProperty("final." + element, "true"); } } request.setAttribute("imsti.properties", config); // Hand up the old values Properties oldValues = new Properties(); Map map = getErrorMap(request); String errorMsg = getErrorMessage(request); request.setAttribute("error.message", errorMsg); addProperty(oldValues, request, "launch", ""); for (String element : fieldList) { if ("launch".equals(element)) continue; String propKey = "imsti." + element; // addProperty(oldValues, request, element, null); String propValue = getCorrectProperty(request, element, null); if (map != null) { if (map.containsKey(propKey)) { Object obj = null; try { String[] arr = (String[]) map.get(propKey); obj = arr[0]; } catch (Exception e) { obj = null; } if (obj instanceof String) propValue = (String) obj; } } if (propValue != null) { if ("xml".equals(element)) { propValue = propValue.replace("&", "&amp;"); } if ("secret".equals(element)) { propValue = LEAVE_SECRET_ALONE; } oldValues.setProperty(propKey, FormattedText.escapeHtml(propValue, false)); } } request.setAttribute("imsti.oldvalues", oldValues); String allowSettings = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_SETTINGS_ENABLED, SakaiBLTIUtil.BASICLTI_SETTINGS_ENABLED_DEFAULT); request.setAttribute("allowSettings", new Boolean("true".equals(allowSettings))); String allowRoster = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_ROSTER_ENABLED, SakaiBLTIUtil.BASICLTI_ROSTER_ENABLED_DEFAULT); request.setAttribute("allowRoster", new Boolean("true".equals(allowRoster))); String allowContentLink = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_CONTENTLINK_ENABLED, SakaiBLTIUtil.BASICLTI_CONTENTLINK_ENABLED_DEFAULT); request.setAttribute("allowContentLink", new Boolean("true".equals(allowContentLink))); // For outcomes we check for tools in the site before offering the options String allowOutcomes = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_OUTCOMES_ENABLED, SakaiBLTIUtil.BASICLTI_OUTCOMES_ENABLED_DEFAULT); if ("true".equals(allowOutcomes)) { String outcomeProp = getCorrectProperty(request, "allowoutcomes", "on"); allowOutcomes = "on".equals(outcomeProp) ? "true" : "false"; } boolean foundLessons = false; boolean foundGradebook = false; ToolConfiguration toolConfig = SiteService.findTool(placement.getId()); try { Site site = SiteService.getSite(toolConfig.getSiteId()); for (SitePage page : (List<SitePage>) site.getPages()) { for (ToolConfiguration tool : (List<ToolConfiguration>) page.getTools()) { String tid = tool.getToolId(); if ("sakai.lessonbuildertool".equals(tid)) foundLessons = true; if ("sakai.gradebook.tool".equals(tid) || "sakai.gradebook.gwt.rpc".equals(tid)) foundGradebook = true; } } } catch (IdUnusedException ex) { M_log.warn("Could not load site."); } if (!foundGradebook) allowOutcomes = "false"; request.setAttribute("allowOutcomes", new Boolean("true".equals(allowOutcomes))); if ("true".equals(allowOutcomes)) { List<String> assignments = getGradeBookAssignments(); if (assignments != null && assignments.size() > 0) request.setAttribute("assignments", assignments); } clearErrorMessage(request); } public void addProperty(Properties values, RenderRequest request, String propName, String defaultValue) { String propValue = getCorrectProperty(request, propName, defaultValue); if (propValue != null) { values.setProperty("imsti." + propName, propValue); } } // Get Property - Precedence is frozen server configuration, sakai tool properties, // portlet preferences, sakai tool properties, and then default public String getCorrectProperty(PortletRequest request, String propName, String defaultValue) { Placement placement = ToolManager.getCurrentPlacement(); String propertyName = placement.getToolId() + "." + propName; String propValue = ServerConfigurationService.getString(propertyName, null); if (propValue != null && propValue.trim().length() > 0) { // System.out.println("Sakai.home "+propName+"="+propValue); return propValue; } Properties config = placement.getConfig(); propValue = getSakaiProperty(config, "imsti." + propName); if (propValue != null && "true".equals(config.getProperty("final." + propName))) { // System.out.println("Frozen "+propName+" ="+propValue); return propValue; } PortletPreferences prefs = request.getPreferences(); propValue = prefs.getValue("imsti." + propName, null); if (propValue != null) { // System.out.println("Portlet "+propName+" ="+propValue); return propValue; } propValue = getSakaiProperty(config, "imsti." + propName); if (propValue != null) { // System.out.println("Tool "+propName+" ="+propValue); return propValue; } if (defaultValue != null) { // System.out.println("Default "+propName+" ="+defaultValue); return defaultValue; } // System.out.println("Fell through "+propName); return null; } // isPropertyFinal() - if it comes from the Server configuration or // the final.propName is set to true public boolean isPropertyFinal(String propName) { Placement placement = ToolManager.getCurrentPlacement(); String propertyName = placement.getToolId() + "." + propName; String propValue = ServerConfigurationService.getString(propertyName, null); if (propValue != null && propValue.trim().length() > 0) { return true; } Properties config = placement.getConfig(); propValue = getSakaiProperty(config, "imsti." + propName); if (propValue != null && "true".equals(config.getProperty("final." + propName))) { return true; } return false; } public void doEdit(RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); dPrint("==== doEdit called ===="); PortletSession pSession = request.getPortletSession(true); String title = getTitleString(request); if (title != null) response.setTitle(title); // Debug String inputData = (String) pSession.getAttribute("sakai.descriptor"); if (inputData != null) dPrint("descriptor.length()=" + inputData.length()); String url = (String) pSession.getAttribute("sakai.url"); dPrint("sakai.url=" + url); String view = (String) pSession.getAttribute("sakai.view"); dPrint("sakai.view=" + view); if ("edit.reset".equals(view)) { sendToJSP(request, response, "/editreset.jsp"); } else { prepareEdit(request); sendToJSP(request, response, "/edit.jsp"); } clearErrorMessage(request); dPrint("==== doEdit called ===="); } public void doHelp(RenderRequest request, RenderResponse response) throws PortletException, IOException { dPrint("==== doHelp called ===="); String title = getTitleString(request); if (title != null) response.setTitle(title); sendToJSP(request, response, "/help.jsp"); clearErrorMessage(request); dPrint("==== doHelp done ===="); } public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException { dPrint("==== processAction called ===="); String action = request.getParameter("sakai.action"); dPrint("sakai.action = " + action); PortletSession pSession = request.getPortletSession(true); // Clear before Action clearErrorMessage(request); String view = (String) pSession.getAttribute("sakai.view"); dPrint("sakai.view=" + view); if (action == null) { // Do nothing } else if (action.equals("main")) { response.setPortletMode(PortletMode.VIEW); } else if (action.equals("edit")) { pSession.setAttribute("sakai.view", "edit"); } else if (action.equals("edit.reset")) { pSession.setAttribute("sakai.view", "edit.reset"); } else if (action.equals("edit.setup")) { pSession.setAttribute("sakai.view", "edit.setup"); } else if (action.equals("edit.clear")) { clearSession(request); response.setPortletMode(PortletMode.VIEW); pSession.setAttribute("sakai.view", "main"); } else if (action.equals("edit.do.reset")) { processActionReset(action, request, response); } else if (action.equals("edit.save")) { processActionSave(action, request, response); } dPrint("==== End of ProcessAction ===="); } private void clearSession(PortletRequest request) { PortletSession pSession = request.getPortletSession(true); pSession.removeAttribute("sakai.url"); pSession.removeAttribute("sakai.widget"); pSession.removeAttribute("sakai.descriptor"); pSession.removeAttribute("sakai.attemptdescriptor"); for (String element : fieldList) { pSession.removeAttribute("sakai." + element); } } public void processActionReset(String action, ActionRequest request, ActionResponse response) throws PortletException, IOException { // TODO: Check Role dPrint("Removing preferences...."); clearSession(request); PortletSession pSession = request.getPortletSession(true); PortletPreferences prefs = request.getPreferences(); try { prefs.reset("sakai.descriptor"); for (String element : fieldList) { prefs.reset("imsti." + element); prefs.reset("sakai:imsti." + element); } dPrint("Preference removed"); } catch (ReadOnlyException e) { setErrorMessage(request, rb.getString("error.modify.prefs")); return; } prefs.store(); // Go back to the main edit page pSession.setAttribute("sakai.view", "edit"); } public void processActionEdit(String action, ActionRequest request, ActionResponse response) throws PortletException, IOException { } public Properties getSakaiProperties() { Placement placement = ToolManager.getCurrentPlacement(); return placement.getConfig(); } // Empty or all whitespace properties are null public String getSakaiProperty(Properties config, String key) { String propValue = config.getProperty(key); if (propValue != null && propValue.trim().length() < 1) propValue = null; return propValue; } // Insure that if we have frozen properties - we never accept form data public String getFormParameter(ActionRequest request, Properties sakaiProperties, String propName) { String propValue = getCorrectProperty(request, propName, null); if (propValue == null || !isPropertyFinal(propName)) { propValue = request.getParameter("imsti." + propName); } dPrint("Form/Final imsti." + propName + "=" + propValue); if (propValue != null) propValue = propValue.trim(); return propValue; } public void processActionSave(String action, ActionRequest request, ActionResponse response) throws PortletException, IOException { PortletSession pSession = request.getPortletSession(true); Properties sakaiProperties = getSakaiProperties(); String imsType = getFormParameter(request, sakaiProperties, "type"); String imsTIUrl = getFormParameter(request, sakaiProperties, "launch"); if (imsTIUrl != null && imsTIUrl.trim().length() < 1) imsTIUrl = null; String imsTIXml = getFormParameter(request, sakaiProperties, "xml"); if (imsTIXml != null && imsTIXml.trim().length() < 1) imsTIXml = null; // imsType will be null if launch or xml is coming from final properties if (imsType != null) { if (imsType.equalsIgnoreCase("XML")) { if (imsTIXml != null) imsTIUrl = null; } else { if (imsTIUrl != null) imsTIXml = null; } } String launch_url = imsTIUrl; if (imsTIXml != null) { launch_url = BasicLTIUtil.validateDescriptor(imsTIXml); if (launch_url == null) { setErrorMessage(request, rb.getString("error.xml.input")); return; } } else if (imsTIUrl == null) { setErrorMessage(request, rb.getString("error.no.input")); return; } else if (imsTIUrl.startsWith("http://") || imsTIUrl.startsWith("https://")) { try { URL testUrl = new URL(imsTIUrl); URI testUri = new URI(imsTIUrl); } catch (Exception e) { setErrorMessage(request, rb.getString("error.bad.url")); return; } } else { setErrorMessage(request, rb.getString("error.bad.url")); return; } // Prepare to store preferences PortletPreferences prefs = request.getPreferences(); boolean changed = false; // Make Sure the Assignment is a legal one String assignment = getFormParameter(request, sakaiProperties, "assignment"); String newAssignment = getFormParameter(request, sakaiProperties, "newassignment"); String oldPlacementSecret = getSakaiProperty(sakaiProperties, "imsti.placementsecret"); String allowOutcomes = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_OUTCOMES_ENABLED, SakaiBLTIUtil.BASICLTI_OUTCOMES_ENABLED_DEFAULT); String allowSettings = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_SETTINGS_ENABLED, SakaiBLTIUtil.BASICLTI_SETTINGS_ENABLED_DEFAULT); String allowRoster = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_ROSTER_ENABLED, SakaiBLTIUtil.BASICLTI_ROSTER_ENABLED_DEFAULT); if ("true".equals(allowOutcomes) && newAssignment != null && newAssignment.trim().length() > 1) { if (addGradeBookItem(request, newAssignment)) { // System.out.println("Success!"); assignment = newAssignment; } } // System.out.println("old placementsecret="+oldPlacementSecret); if (oldPlacementSecret == null && ("true".equals(allowOutcomes) || "true".equals(allowSettings) || "true".equals(allowRoster))) { try { String uuid = UUID.randomUUID().toString(); Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_FORMAT); String date_secret = sdf.format(date); prefs.setValue("sakai:imsti.placementsecret", uuid); prefs.setValue("sakai:imsti.placementsecretdate", date_secret); // System.out.println("placementsecret set to="+uuid+" data="+date_secret); changed = true; } catch (ReadOnlyException e) { setErrorMessage(request, rb.getString("error.modify.prefs")); return; } } if ("true".equals(allowOutcomes) && assignment != null && assignment.trim().length() > 1) { List<String> assignments = getGradeBookAssignments(); boolean found = false; if (assignments != null) for (String assn : assignments) { if (assn.equals(assignment)) { found = true; break; } } if (!found) { setErrorMessage(request, rb.getString("error.gradable.badassign") + " " + FormattedText.escapeHtml(assignment, false)); return; } } String imsTIHeight = getFormParameter(request, sakaiProperties, "frameheight"); if (imsTIHeight != null && imsTIHeight.trim().length() < 1) imsTIHeight = null; if (imsTIHeight != null) { try { int x = Integer.parseInt(imsTIHeight); if (x < 0) { setErrorMessage(request, rb.getString("error.bad.height")); return; } } catch (Exception e) { setErrorMessage(request, rb.getString("error.bad.height")); return; } } // Passed the sanity checks - time to save it all! String context = getContext(); Placement placement = ToolManager.getCurrentPlacement(); // Update the Page Title (button text) String imsTIPageTitle = getFormParameter(request, sakaiProperties, "pagetitle"); String prefsPageTitle = prefs.getValue("sakai:imsti.pagetitle", null); imsTIPageTitle = imsTIPageTitle == null ? "" : imsTIPageTitle.trim(); prefsPageTitle = prefsPageTitle == null ? "" : prefsPageTitle.trim(); if (!imsTIPageTitle.equals(prefsPageTitle)) { try { if (imsTIPageTitle.length() > 99) imsTIPageTitle = imsTIPageTitle.substring(0, 99); ToolConfiguration toolConfig = SiteService.findTool(placement.getId()); Site site = SiteService.getSite(toolConfig.getSiteId()); SitePage page = site.getPage(toolConfig.getPageId()); if (imsTIPageTitle.length() > 1) { page.setTitle(imsTIPageTitle.trim()); page.setTitleCustom(true); } else { page.setTitle(""); page.setTitleCustom(false); } SiteService.save(site); } catch (Exception e) { setErrorMessage(request, rb.getString("error.page.title")); return; } } // Store preferences for (String element : fieldList) { String formParm = getFormParameter(request, sakaiProperties, element); if ("assignment".equals(element)) formParm = assignment; if ("secret".equals(element)) { if (LEAVE_SECRET_ALONE.equals(formParm)) continue; String key = ServerConfigurationService.getString(SakaiBLTIUtil.BASICLTI_ENCRYPTION_KEY, null); if (key != null) { try { if (formParm != null && formParm.trim().length() > 0) { formParm = SimpleEncryption.encrypt(key, formParm); // BLTI-195 convert old-style encrypted secrets prefs.reset("sakai:imsti.encryptedsecret"); } } catch (RuntimeException re) { M_log.warn("Failed to encrypt secret, falling back to plaintext: " + re.getMessage()); } } } try { prefs.setValue("sakai:imsti." + element, formParm); changed = true; } catch (ReadOnlyException e) { setErrorMessage(request, rb.getString("error.modify.prefs")); return; } } // Clear out the other setting if (imsType != null) { if (imsType.equalsIgnoreCase("XML")) { if (imsTIXml != null) { prefs.reset("sakai:imsti.launch"); changed = true; } } else { if (imsTIUrl != null) { prefs.reset("sakai:imsti.xml"); changed = true; } } } // track event and store if (changed) { // 2.6 Event Tracking Event event = LocalEventTrackingService.newEvent(EVENT_BASICLTI_CONFIG, launch_url, context, true, NotificationService.NOTI_OPTIONAL); // 2.5 Event Tracking // Event event = EventTrackingService.newEvent(EVENT_BASICLTI_CONFIG, launch_url, true); LocalEventTrackingService.post(event); prefs.store(); } pSession.setAttribute("sakai.view", "main"); response.setPortletMode(PortletMode.VIEW); } /** * Get the current site page our current tool is placed on. * * @return The site page id on which our tool is placed. */ protected String getCurrentSitePageId() { Placement placement = ToolManager.getCurrentPlacement(); ToolConfiguration tool = SiteService.findTool(placement.getId()); if (tool != null) { return tool.getPageId(); } return null; } // TODO: Local cleverness ??? private void sendToJSP(RenderRequest request, RenderResponse response, String jspPage) throws PortletException { response.setContentType(request.getResponseContentType()); if (jspPage != null && jspPage.length() != 0) { try { PortletRequestDispatcher dispatcher = pContext.getRequestDispatcher(jspPage); dispatcher.include(request, response); } catch (IOException e) { throw new PortletException("Sakai Dispatch unabble to use " + jspPage, e); } } } // Error Message public void clearErrorMessage(PortletRequest request) { PortletHelper.clearErrorMessage(request); } public Map getErrorMap(PortletRequest request) { return PortletHelper.getErrorMap(request); } public String getErrorOutput(PortletRequest request) { return PortletHelper.getErrorOutput(request); } public void setErrorMessage(PortletRequest request, String errorMsg) { PortletHelper.setErrorMessage(request, errorMsg); } public String getErrorMessage(PortletRequest request) { return PortletHelper.getErrorMessage(request); } public void setErrorMessage(PortletRequest request, String errorMsg, Throwable t) { PortletHelper.setErrorMessage(request, errorMsg, t); } private String getContext() { String retval = ToolManager.getCurrentPlacement().getContext(); return retval; } // Create an item in the Gradebook protected boolean addGradeBookItem(ActionRequest request, String assignmentName) { try { GradebookService g = (GradebookService) ComponentManager .get("org.sakaiproject.service.gradebook.GradebookService"); String gradebookUid = getContext(); if (!(g.isGradebookDefined(gradebookUid) && (g.currentUserHasEditPerm(gradebookUid) || g.currentUserHasGradingPerm(gradebookUid)) && g.currentUserHasGradeAllPerm(gradebookUid))) return false; // add assignment to gradebook Assignment asn = new Assignment(); asn.setPoints(Double.valueOf(100)); asn.setExternallyMaintained(false); asn.setName(assignmentName); asn.setReleased(true); asn.setUngraded(false); g.addAssignment(gradebookUid, asn); return true; } catch (ConflictingAssignmentNameException e) { return true; } catch (Exception e) { dPrint("GradebookNotFoundException (may be because GradeBook has not yet been added to the Site) " + e.getMessage()); setErrorMessage(request, rb.getString("error.gradable.badcreate") + ":" + e.getMessage()); M_log.warn(this + ":addGradeItem " + e.getMessage()); } return false; } // get all assignments from the Gradebook protected List<String> getGradeBookAssignments() { List<String> retval = new ArrayList<String>(); try { GradebookService g = (GradebookService) ComponentManager .get("org.sakaiproject.service.gradebook.GradebookService"); String gradebookUid = getContext(); if (!(g.isGradebookDefined(gradebookUid) && (g.currentUserHasEditPerm(gradebookUid) || g.currentUserHasGradingPerm(gradebookUid)) && g.currentUserHasGradeAllPerm(gradebookUid))) return null; List gradebookAssignments = g.getAssignments(gradebookUid); // filtering out anything externally provided for (Iterator i = gradebookAssignments.iterator(); i.hasNext();) { org.sakaiproject.service.gradebook.shared.Assignment gAssignment = (org.sakaiproject.service.gradebook.shared.Assignment) i .next(); if (gAssignment.isExternallyMaintained()) continue; retval.add(gAssignment.getName()); } return retval; } catch (GradebookNotFoundException e) { dPrint("GradebookNotFoundException (may be because GradeBook has not yet been added to the Site) " + e.getMessage()); return null; } } }