Index: lams_bb_integration/.classpath =================================================================== diff -u --- lams_bb_integration/.classpath (revision 0) +++ lams_bb_integration/.classpath (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + Index: lams_bb_integration/.project =================================================================== diff -u --- lams_bb_integration/.project (revision 0) +++ lams_bb_integration/.project (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,17 @@ + + + BB_integration + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + Index: lams_bb_integration/WEB-INF/bb-manifest.xml =================================================================== diff -u --- lams_bb_integration/WEB-INF/bb-manifest.xml (revision 0) +++ lams_bb_integration/WEB-INF/bb-manifest.xml (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + application-def description goes here + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_bb_integration/WEB-INF/config/log4j.properties =================================================================== diff -u --- lams_bb_integration/WEB-INF/config/log4j.properties (revision 0) +++ lams_bb_integration/WEB-INF/config/log4j.properties (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,20 @@ +# Set root category priority to INFO and its only appender to CONSOLE. +log4j.rootCategory=INFO, CONSOLE +#log4j.rootCategory=INFO, CONSOLE, LOGFILE + +# Set the enterprise logger category to FATAL and its only appender to CONSOLE. +log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Threshold=INFO +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n + +# LOGFILE is set to be a File appender using a PatternLayout. +log4j.appender.LOGFILE=org.apache.log4j.FileAppender +log4j.appender.LOGFILE.File=axis.log +log4j.appender.LOGFILE.Append=true +log4j.appender.LOGFILE.Threshold=INFO +log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file Index: lams_bb_integration/WEB-INF/config/taglibs/bbData.tld =================================================================== diff -u --- lams_bb_integration/WEB-INF/config/taglibs/bbData.tld (revision 0) +++ lams_bb_integration/WEB-INF/config/taglibs/bbData.tld (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,91 @@ + + + + + 1.0 + + 1.1 + + Blackboard Data Tag Library + + /bbData + + The Blackboard Data tag library encapsulates interaction + with the Blackboard data and logic layer to allow separation of + the UI elements (bbUI) and other page logic. + + + context + + blackboard.servlet.tags.data.ContextTag + + blackboard.servlet.tags.data.ContextTei + JSP + + In order to support forward compatibility for 5.5 + extension into 6, we need to build a hook that will allow us to + capture virtual installation info in 6. Programmatically, this + was going to be through the Context object. We need to + formalize the interface in 5.5 so that developers can use the + API to ensure 6.0 conformance. As a high-level wrapper, we also + need a taglib for simple inclusion. The taglib would be a + no-arg tag required before any service APIs were called, with a + required closing tag at the bottom of the page (ensuring + context is released). API calls would be Context.setInstance( + HttpServletRequest req ) and Context.releaseInstance(). We need + to include some kind of integrity checking/reference counting + to ensure proper behavior of nested calls. + + id - may be used to explicitly reference the context object elsewhere + in the page (also can access the context from the Java APIs, as + usual) + + license - license key, used to ensure that page will not display if + the license is not valid + + navItem - initializes a NavigationItemControl that will automatically + handle entitlements, and also sets default values for the page title + and breadcrumbs on a given page. + entitlements - a String[] containing entitlements to check before displaying the page + entitlements as per + blackboard.platform.security.AccessManagerService.userHasAnyEntitlements() + entitlement - a String containing a single entitlement to check before displaying the page + entitlement as per + blackboard.platform.security.AccessManagerService.userEntitlement() + + + + + id + false + true + + + license + false + true + + + navItem + false + true + + + + entitlements + false + true + + + + entitlement + false + true + + + + + + Index: lams_bb_integration/WEB-INF/config/taglibs/bbUI.tld =================================================================== diff -u --- lams_bb_integration/WEB-INF/config/taglibs/bbUI.tld (revision 0) +++ lams_bb_integration/WEB-INF/config/taglibs/bbUI.tld (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,1823 @@ + + + + + + + + + 1.0 + 1.1 + Blackboard UI Tag Library + /bbUI + + The Blackboard User Interface tag library encapsulates Blackboard user + interface elements to allow developers easy access to the Blackboard look and feel. + + + + loginWelcome + blackboard.servlet.tags.LoginWelcomeTag + empty + + Creates the standard login welcome panel. + + + errorMessage + false + true + + + + + + loginForm + blackboard.servlet.tags.LoginFormTag + empty + + Creates the standard login form ( same look and feel as rendered by login.pl ). + + validateFormScript - name of the inline script which will validate the login form. + errorMessage - error message from previous login attempt + + + validateFormScript + false + true + + + errorMessage + false + true + + + target + false + true + + + + + createAccountForm + blackboard.servlet.tags.CreateAccountFormTag + empty + + Creates the create-account form. + + createAccountLink - name of the page that will create a new user account. + + + createAccountLink + false + true + + + + + copyright + blackboard.servlet.tags.CopyrightTag + empty + + Standard HTML snippet for Blackboard copyright notice. + + + + + validateLoginFormScript + blackboard.servlet.tags.ValidateLoginFormScriptTag + empty + + Validates login form. + + + + + inlineScript + blackboard.servlet.tags.InlineScriptTag + JSP + + Inserts inline script into HTML. + + scriptLanguage - assumed to be JavaScript, if no input is provided. + scriptRef1 - reference to existing script. + scriptRef2 - reference to another existing script. + scriptRef3 - reference to another existing script. + scriptRef4 - reference to another existing script. + + + scriptLanguage + false + true + + + scriptRef1 + false + true + + + scriptRef2 + false + true + + + scriptRef3 + false + true + + + scriptRef4 + false + true + + + + + spacer + blackboard.servlet.tags.SpacerTag + empty + + Creates an invisible area on the page with the specified height + and width. + + height - Vertical size of the spacer in pixels [1]; + width - Horizontal size of the spacer in pixels [1]; + + + height + false + true + + + width + false + true + + + align + false + true + + + + + devDocTemplate + blackboard.servlet.tags.DocumentTemplateTag + JSP + + combines the docTemplateHead and docTemplateBody tag (for use + when you don't need to add items to the HEAD of the HTML doc. + + + title + true + true + + + + + docTemplate + blackboard.servlet.tags.ProductionDocTemplateTag + JSP + combines the docTemplateHead and docTemplateBody tag (for use + when you don't need to add items to the HEAD of the HTML doc. + + + + title + false + true + + + onLoad + false + true + + + onUnload + false + true + + + onSubmit + false + true + + + + + docTemplateHead + blackboard.servlet.tags.ProductionDocTemplateHeadTag + JSP + + sets head defaults, such as including the base css sheet and validateForm.js + links. Use this tag if you wish to add more style sheets or javascript to + the head of your HTML doc. + + + title + false + true + + + + + docTemplateBody + blackboard.servlet.tags.ProductionDocTemplateBodyTag + JSP + + Sets the default body tag settings for the HTML page (such as attaching the + default style class to the body tag) + + + onLoad + false + true + + + onUnload + false + true + + + + + coursePage + blackboard.servlet.tags.CoursePageTag + JSP + + Creates a course page element. It may be used to re-arrange elements on a page + from interface to interface. It makes the course available to sub-tags. + + course - Course data object [used in sub-tags to render course-specific elements]; + + + courseId + false + true + + + course + false + true + + + + + courseTitleBar + blackboard.servlet.tags.CourseTitlebarTag + JSP + + Creates a course title bar + + + + + titleBar + blackboard.servlet.tags.TitlebarTag + JSP + + Creates a general use title bar. + iconUrl - the URL for the Icon image used in the titlebar; + pluginId - the Id for the plugin (known by the plugin developer; + and used as the directory root of the plugin, e.g. + "/Blackboard/plugins/*pluginId*/images/pluginimg.gif") + + + iconUrl + false + true + + + pluginId + false + true + + + + + step + blackboard.servlet.tags.StepTag + JSP + + Creates html for a wizard Step element. + number - the number for the step (1, 2, 3 for 1st, 2nd, 3rd in wizard); + title - the title of the step; + + + number + false + true + + + title + true + true + + + width + false + true + + + + + stepSubmit + blackboard.servlet.tags.StepSubmitTag + empty + + Creates html for ane entire submit/cancel step element. + number - the number for the step (1, 2, 3 for 1st, 2nd, 3rd in wizard); + title - the title of the step; + cancelUrl - the url to recall the page to if the user cancels; + instructions - the message string displayed in this step; + + + number + false + true + + + title + false + true + + + cancelUrl + false + true + + + instructions + false + true + + + + + + breadcrumbBar + blackboard.servlet.tags.BreadcrumbBarTag + JSP + + Creates the framework for the breadcrumb navigation. + environment - whether we are viewing this navigation in the + course, control panel, portal, etc. + Acceptable values are: + PORTAL, + COURSE, + CTRL_PANEL, + SYS_ADMIN; + handle - the database field used to uniquely identify the + root nav item for the breadcrumb bar. (bar gets the appropriate + nav item from the handler, then traverses the navigation tree to + iteratively get the item's parents; + target - the default target for bc items in this bar, defaults to none + + + environment + false + true + + + handle + false + true + + + + isContent + false + true + + + target + false + true + + + + + + + breadcrumb + blackboard.servlet.tags.BreadcrumbTag + JSP + + Navigation item for the breadcrumb bar. + href - the optional attribute setting the link for the element; + target - the target attribute for the links in this breadcrumb, defaults + to none + + + href + false + true + + + target + false + true + + + + + + dataElement + blackboard.servlet.tags.DataElementTag + JSP + + This tag will be superceded by type-safe form input tags. + label - the text label for the data (form) element; + should contain: form input tags. + required - indicates that the element is required before submitting + form. (Doesn't validate, simply adds *); + + + label + false + true + + + required + false + true + + + + + instructions + blackboard.servlet.tags.InstructionsTag + JSP + + Instructions should only be called inside a step. + + + + + + stepContent + blackboard.servlet.tags.StepContentTag + JSP + + StepContent should only be called inside a step. It wraps the enclosed + HTML in the appropriate table row and table data code to fit inside the + step tag. It is comparable to the specialized tags Instructions and + DataElement, but is more generalized since it ONLY contains table code. + + + + + + button + blackboard.servlet.tags.ButtonTag + empty + + This tag will be superceded by type-safe button tags. + It hides the details of a button object (eventually will be functional + in javascript and non-javascript modes). + + type - whether the buton is FORM_ACTION, INLINE, LONG_INLINE, or TOOLBAR; + + FORM_ACTION corresponds to the "submit"|"cancel" button type + ACTION_INLINE corresponds to the "modify"|"remove" button type + LONG_INLINE corresponds to inline buttons that don't have the standard button size (e.g., "properties") + TOOLBAR corresponds to the toolbar buttons (e.g. "add item") BUT NOT buttons used in actionbars (only old style toolbar buttons) + + + name - the name of the button, which should correspond to the name of the + image for the button, minus the "_off.gif"; + alt - used for the alt tag for the code; + action - whether the button submits a form or links to another page; + targetUrl - the target for the page to link to, if it's a link-type button; + tabindex - corresponds to the html tabindex property, used to set the tab order + of a given link or button + + + type + true + true + + + name + true + true + + + alt + true + true + + + action + true + true + + + targetUrl + false + true + + + tabindex + false + true + + + + + + receipt + blackboard.servlet.tags.ReceiptTag + JSP + + Creates a receipt page using titleBar and button components. + iconUrl - the URL for the Icon image used in the titlebar; + pluginId - the Id for the plugin (known by the plugin developer + and used as the directory root of the plugin, e.g. + "/Blackboard/plugins/*pluginId*/images/pluginimg.gif"); + recallUrl - OK button, if null will attempt to locate recallUrl from nav item + or use javascript back ONLY SHOWN IF submitUrl and cancelUrl are both null + submitUrl, cancelUrl - optional attributes to allow the receipt to have + two buttons (although either may be used alone).LINK rather than FORM_SUBMIT action + + + + type + false + true + + + iconUrl + false + true + + + pluginId + false + true + + + title + false + true + + + recallUrl + false + true + + + cancelUrl + false + true + + + + buttonName + false + true + + + + buttonAlt + false + true + + + + + + list + blackboard.servlet.tags.ListTag + blackboard.servlet.tags.ListTei + JSP + + Creates a list (UI determined by the TYPE attribute). + collection - the collection passed to the list + (usually a Blackboard filteredList resulting from a Load attempt + within the persistence layer. example: a list of users in a course) + collectionLabel - a label for the objects inthe list, default is "Objects" + object - the BbObject that will be iterated over in the list (example: user) + type - the type of list (determines the UI) + description - description of the list (required for accessibility compliance) + sortUrl - the URL to sort or paginate this list, probably of the form + "myPage.jsp?id=_1_2&name=test" or to control the list display, also specify + "myPage.jsp?id=_1_2&name=test&sortBy=" + listElement_index + + "&startIndex=" + ind + resultsPerPage - the number of items to display on a given page. Default is 20, and + -1 is "show all" + + + collection + true + true + + + objectId + true + true + + + className + true + true + + + type + false + true + + + description + false + true + + + sortUrl + false + true + + + resultsPerPage + false + true + + + collectionLabel + false + true + + + + + listElement + blackboard.servlet.tags.ListElementTag + JSP + + Creates a list item (one "cell" in a list)-- these items will be built up + into rows and rendered as a list (examples: First Name, Last Name, Email) + width - the optional width setting (used for the width of the column of the list) + label - the optional label for the column + href - the optional url to use to sort the list by + abbr - the abbreviation for screen readers (required for accessibility if a LABEL is supplied) + comparator - an optional attribute to specify a comparator used to sort the list. + + + width + false + true + + + label + false + true + + + href + false + true + + + abbr + false + true + + + comparator + false + true + + + name + false + true + + + nowrap + false + true + + + align + false + true + + + valign + false + true + + + + + + simpleList + blackboard.servlet.tags.SimpleListTag + empty + + Creates a list (UI determined by the TYPE attribute). + collection - the collection passed to the list + (usually a Blackboard filteredList resulting from a Load attempt + within the persistence layer. example: a list of users in a course) + type - the type of list (determines the UI) + description - description of the list (required for accessibility compliance) + + + collection + true + true + + + type + false + true + + + description + true + true + + + + + + dateAvailability + + + blackboard.servlet.tags.DateAvailabilityTag + + empty + + creates the HTML and JavaScript for the date dropdown and + validation + + + TO CONNECT WITH FORM HANDLING: + + Read from hidden elements: + data__course_contents___pk1_pk2__restrict_start_date + data__course_contents___pk1_pk2__restrict_end_date + On edit, write to tag Date startDate and Date endDate + + NEW: can now rename these hidden fields with + startDateField + and + endDateField + + For use with the blackboard.struts.DateAvailabilityForm, set + startDateField = "blackboard.struts.DateAvailabilityForm.startDateField"; + endDateField = "blackboard.struts.DateAvailabilityForm.endDateField"; + + pickdate //unknown + pickname //unknown + + make sure that you include a link to the javascript file "/javascript/validateForm.js" + in the jsp page when this widget is used, if you are not using the docTemplate or docTemplateHead + widgets. (this link has been removed + from the widget due to possible javascript conflicts) + + + + + formName + + true + + true + + + + startCaption + + false + + true + + + + endCaption + + false + + true + + + + startDateField + + false + + true + + + + endDateField + + false + + true + + + + startDate + + false + + true + + + + endDate + + false + + true + + + + + + dateSelection + blackboard.servlet.tags.DateSelectionTag + empty + + Creates the HTML for a date dropdown and related JavaScript validation + + TO CONNECT WITH FORM HANDLING: + Read from hidden elements: + data__course_contents___pk1_pk2__restrict_start_date + On edit, write to tag Date startDate and Date endDate + + + + formName + true + true + + + + elementName + false + true + + + + date + false + true + + + + + caretList + blackboard.servlet.tags.CaretListTag + JSP + + Widget encapsulating a Caret List. + It works like the BreadcrumbBarTag, in that it can accept either + child tags (caret) or a collection of CaretBeans (blackboard.servlet.data.CaretBean). + + description: the table summary (for accessibility/screenreader functionality), describes + the function of the caret list. + + + + description + false + true + + + collection + false + true + + + + + caret + blackboard.servlet.tags.CaretTag + JSP + + Entry in a Caret List. Contains a title, description, and href + (which is a link for the title attribute). Only the title is + required. + The description is set in the body of the tag + + + title + true + true + + + href + false + true + + + + + module + blackboard.servlet.tags.ModuleTag + JSP + + Creates html for a module. + + + title + true + true + + + bgColor + false + true + + + borderColor + false + true + + + borderSize + false + true + + + titleBgColor + false + true + + + titleColor + false + true + + + layoutUIStyle + false + true + + + + + + actionItem + blackboard.servlet.tags.ActionItemTag + Empty + + Action items (such as Add Content), which appear in the + ActionBar + + + title + true + true + + + href + true + true + + + imgUrl + true + true + + + + + actionBar + blackboard.servlet.tags.ActionBarTag + JSP + + Action items (such as Add Content) appear in the + ActionBar + + + action + false + true + + + icon + false + true + + + maxItems + false + true + + + collection + false + true + + + + + colorPicker + blackboard.servlet.tags.ColorPickerTag + empty + + Creates an form element for choosing a color. + + name - Name of the form element; + color - Current color; + + + name + true + true + + + color + false + true + + + formName + false + true + + + + + modulePersonalizationPage + blackboard.servlet.tags.ModulePersonalizationPageTag + JSP + + Creates the header and footer for a module personalization page. + + + title + false + true + + + iconUrl + false + true + + + + + modulePersonalizationReceipt + blackboard.servlet.tags.ModulePersonalizationReceiptTag + JSP + + Creates a module personalization receipt. + + + title + false + true + + + iconUrl + false + true + + + recallUrl + false + true + + + + + moduleAdminPage + blackboard.servlet.tags.ModuleAdminPageTag + JSP + + Creates the header and footer for a module personalization page. + + + title + false + true + + + iconUrl + false + true + + + + + moduleAdminReceipt + blackboard.servlet.tags.ModuleAdminReceiptTag + JSP + + Creates a module personalization receipt. + + + title + false + true + + + iconUrl + false + true + + + recallUrl + false + true + + + + + + + textbox + blackboard.servlet.tags.TextboxTag + empty + + Creates a textbox tag with formatting and MathML controls. + + isMathML - should the widget include the MathML links? + isFormattedText - should the widget include radio buttons for smart/plain/html? + mode - modify|insert + name - the name of the text area control, used in JS as well + label - label for textarea + rows - number of rows for textarea + cols - number of columns for textarea + minLength - validation-- must have a min length of this + maxLength - text content can be no longer than maxLength (validation + text - the text value of the area + xContent - the structured text, in xml + format - smarttext|plaintext|html + includeJs - should only be true ONCE on a page-- set for the first MathML element on page + popupType - defaults to html-- but can configure in future to popup.jsp instead + + + + + isMathML + false + true + + + + + isFormattedText + false + true + + + + mode + false + true + + + + name + true + true + + + + + label + false + true + + + + rows + false + true + + + + + cols + false + true + + + + + minLength + false + true + + + + maxLength + false + true + + + + + text + false + true + + + + + xContent + false + true + + + + + format + false + true + + + + + includeJs + false + true + + + + + popupType + false + true + + + + + + + toolbar + blackboard.servlet.tags.ToolbarTag + JSP + A generic toolbar + + borderColor + false + true + + + toolbarColor + false + true + + + height + false + true + + + width + false + true + + + styleClass + false + true + + + + + toolbarButton + blackboard.servlet.tags.ToolbarButtonTag + JSP + Very similar to an ActionItem containing a link, label and icon + + label + false + true + + + link + true + true + + + icon + false + true + + + iconAlternative + false + true + + + iconHeight + false + true + + + iconWidth + false + true + + + + + toolbarDivider + blackboard.servlet.tags.ToolbarDividerTag + JSP + A vertical divider element + + height + false + true + + + + + toolbarEmpty + blackboard.servlet.tags.ToolbarEmptyTag + JSP + A completely empty element ... do with it what you will, but check the documentation for toolbar eccentricities + + + + toolbarForm + blackboard.servlet.tags.ToolbarFormTag + JSP + Wrapper for toolbar form elements + + name + false + true + + + action + true + true + + + method + false + true + + + encType + false + true + + + + + toolbarText + blackboard.servlet.tags.ToolbarTextTag + JSP + A text input form element + + inputId + true + true + + + label + false + true + + + size + false + true + + + value + false + true + + + icon + false + true + + + iconAlternative + false + true + + + iconHeight + false + true + + + iconWidth + false + true + + + + + toolbarSelect + blackboard.servlet.tags.ToolbarSelectTag + JSP + Info. + + inputId + true + true + + + label + false + true + + + icon + false + true + + + iconAlternative + false + true + + + iconHeight + false + true + + + iconWidth + false + true + + + + + + + navigationItemMenu + blackboard.servlet.tags.NavigationItemMenuTag + JSP + + A box defined by a cascading style sheet, containing all the navigation items belonging to a + certain navigation family. Similar to a caret list, but designed for inline navigation links. + + + family + true + true + + + id + false + true + + + substitutionMap + false + true + + + + + + box + blackboard.servlet.tags.BoxTag + JSP + + A basic box. The body of the tag is included inside the box. Border color + and background color can be specified for visual interfaces. + + + borderColor + false + true + + + backgroundColor + false + true + + + + + search + blackboard.servlet.tags.SearchTag + JSP + + A tabbed search interface. Wraps the UI html around whatever content is in the body of + the tag + + Attributes: + isShowAdvanced - defaults to false. if true, displays a second tab, for Advanced search, + and adds hyperlink wrappers for the inactive tab (note: tabbing between the two + views, normal and advanced, is handled by the tab. If a searchUrl (below) is given, + the hyperlink for the tabs is created by appending "&mode=advanced|normal". Otherwise, + a URL is determined from the request. + searchUrl: an optional attribute used to construct the hyperlink for the Advanced|Normal + tabs. Default- constructed from the request. + + + isShowAdvanced + false + true + + + searchUrl + false + true + + + + + + error + blackboard.servlet.tags.ErrorTag + empty + + Handles exception UI + + exception - the exception that was thrown + + + exception + true + true + + + + + + + + + + + + + + dateRangePicker + + + blackboard.servlet.tags.DatePickerTag + + empty + + creates the HTML and JavaScript for the date dropdown and + validation + + Calendar startDate - if null, defaults to the current time + Calendar endDate - if null, end date dropdown is omitted + + int datePickerIndex - defaults to 0, should be incremented for additional pickers on a page + (NOTE: datePicker and dateRangePicker use the same field naming convention, and should not have the same index if on a page together) + + String formName - defaults to "forms[0]", should be replaced by the form name attribute if more than one form is used on the page + String startCaption - label to use for start date picker, defaults to "Start" + String endCaption - label to use for the end date picker, defaults to "End" + String endDateField - see below + String startDateField - see below + + + boolean checkPastDue - defaults to false, set to true if js validation for past due events is needed + boolean isEndChecked - defaults to false, set to true if the end date is set in the data object (as opposed to an as-yet-unset end date) + + + TO CONNECT WITH FORM HANDLING: + Hidden field names are set with + startDateField + and + endDateField + By default, read from hidden inputs: + start_date_0 + end_date_0 + (if manually setting these names, form name is rendered to page as: + startDateField+"_" + datePickerIndex, to allow multiple pickers per page) + + make sure that you include a link to the javascript file "/javascript/validateForm.js" + in the jsp page when this widget is used, if you are not using the docTemplate or docTemplateHead + widgets. (this link has been removed + from the widget due to possible javascript conflicts) + + + + + formName + + false + + true + + + + + startCaption + + false + + true + + + + endCaption + + false + + true + + + + startDateField + + false + + true + + + + endDateField + + false + + true + + + + startDate + + false + + true + + + + endDate + + false + + true + + + + datePickerIndex + + false + + true + + + + + checkPastDue + + false + + true + + + + + isEndChecked + + false + + true + + + + + + + + + + + + + + datePicker + + + blackboard.servlet.tags.DatePickerTag + + empty + + creates the HTML and JavaScript for the date dropdown and + validation for a single date picker element + + Calendar startDate - if null, defaults to the current time + + int datePickerIndex - defaults to 0, should be incremented for additional pickers on a page + (NOTE: datePicker and dateRangePicker use the same field naming convention, and should not have the same index if on a page together) + + String formName - defaults to "forms[0]", should be replaced by the form name attribute if more than one form is used on the page + String startCaption - label to use for start date picker, defaults to "Start" + String startDateField - see below + + + boolean checkPastDue - defaults to false, set to true if js validation for past due events is needed + + + TO CONNECT WITH FORM HANDLING: + Hidden field name is set with + startDateField + By default, read from hidden inputs: + start_date_0 + (if manually setting these names, form name is rendered to page as: + startDateField+"_" + datePickerIndex, to allow multiple pickers per page) + + make sure that you include a link to the javascript file "/javascript/validateForm.js" + in the jsp page when this widget is used, if you are not using the docTemplate or docTemplateHead + widgets. (this link has been removed + from the widget due to possible javascript conflicts) + + + + + formName + + false + + true + + + + + startCaption + + false + + true + + + + startDateField + + false + + true + + + + startDate + + false + + true + + + + datePickerIndex + + false + + true + + + + + checkPastDue + + false + + true + + + + + + + errors + blackboard.servlet.tags.ErrorsTag + empty + + This is a replacement for the Struts html:error tag, which does not + include the internationalization features. It is assumed that the object + specified by "name" is an ActionErrors object, and that for each + ActionError it contains, the "key" property is actually the literal + message that should be displayed, and not a key into some ResourceBundle. + + Note that, due to a dependency on Struts, and the fact that Struts 1.0 + cannot be loaded from the systemlib classloader, this class is NOT built + into the bb-taglib-api.jar. Instead, if you need to use this tag, you + must share the class into your webapp src directory. See tmoore for info. + + + name + false + true + + + property + false + true + + + + + ppgBase + blackboard.servlet.tags.PpgBaseTag + empty + + + + Index: lams_bb_integration/WEB-INF/config/taglibs/bbUI.xsl =================================================================== diff -u --- lams_bb_integration/WEB-INF/config/taglibs/bbUI.xsl (revision 0) +++ lams_bb_integration/WEB-INF/config/taglibs/bbUI.xsl (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,32 @@ + + + + + +
    + +

  1. + +
      + + +
    • Body:
    • + +
    • Info:


    • + + Attributes: + +
        +

      • + Required:
        + Real-time evaluated:
        +
      +
      +


    + +
    +
+ + +
+
Index: lams_bb_integration/WEB-INF/lib/axis-ant.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/axis.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/commons-codec-1.3.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/commons-discovery-0.2.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/commons-logging-1.0.4.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/jaxrpc.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/log4j-1.2.8.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/saaj.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/lib/wsdl4j-1.5.1.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/WEB-INF/web.xml =================================================================== diff -u --- lams_bb_integration/WEB-INF/web.xml (revision 0) +++ lams_bb_integration/WEB-INF/web.xml (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,36 @@ + + + + + + + UserDataServlet + org.lamsfoundation.ld.integration.blackboard.UserDataServlet + + + LamsActionRequestServlet + org.lamsfoundation.ld.integration.blackboard.LamsActionRequestServlet + + + + LamsActionRequestServlet + /LamsActionRequest + + + UserDataServlet + /UserData + + + + + /bbUI + /WEB-INF/config/taglibs/bbUI.tld + + + /bbData + /WEB-INF/config/taglibs/bbData.tld + + + Index: lams_bb_integration/build.xml =================================================================== diff -u --- lams_bb_integration/build.xml (revision 0) +++ lams_bb_integration/build.xml (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: lams_bb_integration/lib/bb-cms-admin.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/lib/bb-platform.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/lib/bb-taglibs.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/lib/servlet-api.jar =================================================================== diff -u Binary files differ Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/Constants.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/Constants.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/Constants.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + */ +package org.lamsfoundation.ld.integration; + +/** + * @author Anthony Xiao + */ +public class Constants { + + public static final String PARAM_USER_ID = "uid"; + public static final String PARAM_SERVER_ID = "sid"; + public static final String PARAM_TIMESTAMP = "ts"; + public static final String PARAM_HASH = "hash"; + //public static final String PARAM_URL = "url"; + public static final String PARAM_METHOD = "method"; + public static final String PARAM_LEARNING_SESSION_ID = "lsid"; + public static final String PARAM_LEARNING_DESIGN_ID = "ldid"; + public static final String PARAM_COURSE_ID = "course_id"; + + + public static final String SERVLET_LOGIN_REQUEST = "/lams/LoginRequest"; + public static final String SERVLET_ACTION_REQUEST = "/LamsActionRequest"; + + public static final String URLDECODER_CODING = "US-ASCII"; + + public static final String METHOD_AUTHOR = "author"; + public static final String METHOD_MONITOR = "monitor"; + public static final String METHOD_LEARNER = "learner"; + + // Conf file constants + //public static final String CONF_SERVER_ADDRRESS = "lamstwo.serverAddr"; + //public static final String CONF_SERVER_ID = "lamstwo.serverId"; + //public static final String CONF_SERVER_KEY = "lamstwo.serverKey"; + //public static final String CONF_REQUEST_SOURCE = "lamstwo.requestSrc"; + + // XML format constnats + public static final String ELEM_FOLDER = "Folder"; + public static final String ELEM_LEARNING_DESIGN = "LearningDesign"; + public static final String ATTR_NAME = "name"; + public static final String ATTR_RESOURCE_ID = "resourceId"; + +} Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsActionRequestServlet.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsActionRequestServlet.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsActionRequestServlet.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,140 @@ +/**************************************************************** + * Copyright (C) 2007 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ + +package org.lamsfoundation.ld.integration.blackboard; + +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.lamsfoundation.ld.integration.Constants; +import blackboard.persist.BbPersistenceManager; +import blackboard.persist.Id; +import blackboard.platform.BbServiceManager; +import blackboard.data.course.Course; +import blackboard.platform.context.ContextManager; +import blackboard.platform.context.Context; +import blackboard.platform.plugin.PlugInException; +import blackboard.platform.plugin.PlugInUtil; +import blackboard.platform.session.BbSession; +import blackboard.platform.session.BbSessionManagerService; + + +/** + * @author Luke Foxton + */ +public class LamsActionRequestServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * The doGet method of the servlet.
+ * + * This method is called by a when a GET request is performed + * There are three types of requests for LAMS AUTHOR, MONITOR and LEARNER + * Basically it creates the redirect URL strings and sends the redirect + * + * @param request the request sent by the client to the server + * @param response the response sent by the server to the client + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException{ + + //get request parameters + String p_method = request.getParameter(Constants.PARAM_METHOD); + + //String p_learningSessionId = request.getParameter(Constants.PARAM_LEARNING_SESSION_ID); + //String p_learningDesignId = request.getParameter(Constants.PARAM_LEARNING_DESIGN_ID); + String p_courseId = request.getParameter(Constants.PARAM_COURSE_ID); + + //validate method parameter and associated parameters + if(p_method == null) + { + throw new ServletException("requred parameters missing"); + } + + + ContextManager ctxMgr = null; + Context ctx = null; + + try{ + // get Blackboard context + ctxMgr = (ContextManager) BbServiceManager.lookupService(ContextManager.class); + ctx = ctxMgr.setContext(request); + + + // get the session object to obtain the current user and course object + BbSessionManagerService sessionService = BbServiceManager.getSessionManagerService(); + BbSession bbSession = sessionService.getSession( request ); + String username = bbSession.getUserName(); + + //attach the learningSessionId, learningDesignId or courseId to the redirect url + //String redirect = LamsSecurityUtil.generateRequestURL(username, p_method); + String redirect = LamsSecurityUtil.generateRequestURL(ctx, p_method); + + //redirect = LamsSecurityUtil.generateRequestURL(username, p_method); + /*if(p_learningSessionId!=null) + { + redirect += '&' + Constants.PARAM_LEARNING_SESSION_ID + '=' + p_learningSessionId; + //redirect1 += '&' + Constants.PARAM_LEARNING_SESSION_ID + '=' + p_learningSessionId; + } + if(p_learningDesignId!=null) + { + redirect += '&' + Constants.PARAM_LEARNING_DESIGN_ID + '=' + p_learningDesignId; + //redirect1 += '&' + Constants.PARAM_LEARNING_SESSION_ID + '=' + p_learningSessionId; + } + if(p_courseId!=null) + { + redirect += '&' + Constants.PARAM_COURSE_ID + '=' + p_courseId; + //redirect1 += '&' + Constants.PARAM_LEARNING_SESSION_ID + '=' + p_learningSessionId; + } + */ + + + if(p_courseId!=null) + { + redirect += '&' + Constants.PARAM_COURSE_ID + '=' + p_courseId; + //redirect1 += '&' + Constants.PARAM_LEARNING_SESSION_ID + '=' + p_learningSessionId; + } + + //response.sendRedirect(redirect1); + + response.sendRedirect(response.encodeRedirectURL(redirect)); + + + } catch (Exception e){ + + throw new ServletException(e.getMessage(), e); + } + finally{ + //make sure context is released + if (ctxMgr != null) + ctxMgr.releaseContext(); + } + } +} Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsPluginUtil.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsPluginUtil.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsPluginUtil.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,141 @@ +/**************************************************************** + * Copyright (C) 2007 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.ld.integration.blackboard; + + +import java.util.Properties; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +import blackboard.platform.plugin.PlugInException; +import blackboard.platform.plugin.PlugInUtil; + + + +/** + * + * This class basically manages the lams.properties file on the BB server + * This file contains the LAMS server URL, server ID and secret key + * These values allow the communication between the two servers + * + * @author Luke Foxton + */ +public class LamsPluginUtil { + + public static final String VENDOR_ID = "lams"; + public static final String PLUGIN_HANDLE = "plglamscontent"; + public static final String CONTENT_HANDLE = "resource/x-lams-lamscontent"; + public static final String FILE_PROPERTIES = "lams.properties"; + + public static final String PROP_LAMS_SECRET_KEY = "LAMS_SERVER_SKEY"; + public static final String PROP_LAMS_SERVER_ID = "LAMS_SERVER_ID"; + public static final String PROP_LAMS_URL = "LAMS_SERVER_URL"; + public static final String PROP_REQ_SRC = "BB_REQ_SRC"; + + private static Properties lamsProperties = null; + + + /** + * Returns the properties file that contains the server name, key and connection URL + * + * @return The LAMS Properties file + * @throws PlugInException + * @throws FileNotFoundException + * @throws IOException + */ + public static Properties getProperties() { + if(lamsProperties != null) + return lamsProperties; + + //load LAMS Configuration File + try{ + File configFile = new File(PlugInUtil.getConfigDirectory(VENDOR_ID, PLUGIN_HANDLE).getPath() + File.separator + FILE_PROPERTIES); + Properties p = new Properties(); + + if(configFile.exists()) + p.load(new FileInputStream(configFile)); + else{ + p.setProperty(PROP_LAMS_URL, ""); + p.setProperty(PROP_LAMS_SECRET_KEY, ""); + p.setProperty(PROP_LAMS_SERVER_ID, ""); + p.setProperty(PROP_REQ_SRC, ""); + } + + lamsProperties = p; + return p; + } catch(PlugInException e){ + throw new RuntimeException(e); + } catch(FileNotFoundException e){ + throw new RuntimeException(e); + } catch(IOException e){ + throw new RuntimeException(e); + } + } + + /** + * Save a Properties file as the LAMS properties file + * + * @param p + * @throws PlugInException + * @throws FileNotFoundException + * @throws IOException + */ + public static void setProperties(Properties p) { + try{ + lamsProperties = p; + + FileOutputStream configFile = + new FileOutputStream(PlugInUtil.getConfigDirectory(VENDOR_ID, PLUGIN_HANDLE).getPath() + + File.separator + FILE_PROPERTIES); + p.store(configFile, "LAMS configuration"); + configFile.close(); + } catch(PlugInException e){ + throw new RuntimeException(e); + } catch(FileNotFoundException e){ + throw new RuntimeException(e); + } catch(IOException e){ + throw new RuntimeException(e); + } + } + + public static String getSecretKey(){ + return getProperties().getProperty(PROP_LAMS_SECRET_KEY); + } + + public static String getServerUrl(){ + return getProperties().getProperty(PROP_LAMS_URL); + } + + public static String getServerId(){ + return getProperties().getProperty(PROP_LAMS_SERVER_ID); + } + + public static String getReqSrc(){ + return getProperties().getProperty(PROP_REQ_SRC); + } + + +} Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsSecurityUtil.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsSecurityUtil.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsSecurityUtil.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,437 @@ +/**************************************************************** + * Copyright (C) 2007 LAMS Foundation (http://lamsfoundation.org) + * ============================================================= + * License Information: http://lamsfoundation.org/licensing/lams/2.0/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2.0 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + * **************************************************************** + */ +package org.lamsfoundation.ld.integration.blackboard; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.rmi.RemoteException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.Locale; +import javax.xml.rpc.ServiceException; +import blackboard.platform.context.ContextManager; +import blackboard.platform.context.Context; +import org.apache.commons.codec.binary.Hex; +import org.lamsfoundation.lams.integrations.sakai.logic.impl.LamstwoUtils; +import org.lamsfoundation.lams.webservice.LessonManager; +import org.lamsfoundation.lams.webservice.LessonManagerService; +import org.lamsfoundation.lams.webservice.LessonManagerServiceLocator; +import org.lamsfoundation.ld.integration.Constants; +import org.lamsfoundation.ld.webservice.*; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; +import org.apache.log4j.Logger; +import java.io.*; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * @author Luke Foxton + */ +public class LamsSecurityUtil { + + //private static Connection _conn = null; + static Logger logger = Logger.getLogger(LamsSecurityUtil.class); + + public static String generateRequestURL(Context ctx, String method) throws Exception + { + String serverAddr = getServerAddress(); + String serverId = getServerID(); + String reqSrc = getReqSrc(); + + // If lams.properties could not be read, throw exception + if(serverAddr == null || serverId == null || reqSrc==null){ + throw new Exception("Configuration Exception " + serverAddr + ", " + serverId); + } + + String timestamp = new Long(System.currentTimeMillis()).toString(); + String username = ctx.getUser().getUserName(); + String hash = generateAuthenticationHash(timestamp, username, method, serverId); + String courseId = ctx.getCourse().getCourseId(); + String country = "US"; + String lang = "en"; + + + //ResourceLoader rl = new ResourceLoader(); + //String[] locale = ctx.getGuestSessionLocale().split("-"); + + //String siteID = getCurrentContext(); + + // TODO: Make locale settings work + + String url; + try { + url = serverAddr + "/LoginRequest?" + + "&uid=" + URLEncoder.encode(username, "UTF8") + + "&method=" + method + + "&ts=" + timestamp + + "&sid=" + serverId + + "&hash=" + hash + + "&courseid=" + URLEncoder.encode(courseId, "UTF8") + + "&country=" + country + + "&lang=" + lang + + "&requestSrc=" + URLEncoder.encode(reqSrc, "UTF8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(); + } + + System.out.println(url); + + return url; + } + + public static String getLearningDesigns(Context ctx, Integer mode) throws Exception + { + String serverAddr = getServerAddress(); + String serverId = getServerID(); + String serverKey = getServerKey(); + + // If lams.properties could not be read, throw exception + if(serverAddr == null || serverId == null || serverKey==null){ + throw new Exception("Configuration Exception " + serverAddr + ", " + serverId); + } + + String timestamp = new Long(System.currentTimeMillis()).toString(); + String username = ctx.getUser().getUserName(); + String hash = generateAuthenticationHash(timestamp, username, serverId); + String courseId = ctx.getCourse().getCourseId(); + String country = "US"; + String lang = "en"; + + // TODO: Make locale settings work + String learningDesigns = "[]"; // empty javascript array + try { + String serviceURL = serverAddr + "/services/xml/LearningDesignRepository?" + + "datetime=" + timestamp + + "&username=" + URLEncoder.encode(username, "utf8") + + "&serverId=" + URLEncoder.encode(serverId, "utf8") + + "&serverKey=" + URLEncoder.encode(serverKey, "utf8") + + "&hashValue=" + hash + + "&courseId=" + URLEncoder.encode(courseId, "UTF8") + + "&country=" + country + + "&lang=" + lang + + "&mode=" + mode; + + URL url = new URL(serviceURL); + URLConnection conn = url.openConnection(); + if (!(conn instanceof HttpURLConnection)) { + logger.error("Unable to open connection to: " + serviceURL); + } + + HttpURLConnection httpConn = (HttpURLConnection)conn; + + if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { + logger.error("HTTP Response Code: " + httpConn.getResponseCode() + + ", HTTP Response Message: " + httpConn.getResponseMessage()); + } + + InputStream is = url.openConnection().getInputStream(); + + // parse xml response + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(is); + + learningDesigns = "[" + convertToTigraFormat(document.getDocumentElement()) + "]"; + + // replace sequence id with javascript method + String pattern = "'(\\d+)'"; + String replacement = "'javascript:selectSequence($1)'"; + learningDesigns = learningDesigns.replaceAll(pattern, replacement); + + // TODO better error handling + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } + + return learningDesigns; + } + + + + /* + * TODO: + */ + public static Long scheduleLesson(Context ctx, long ldId, String title, String desc, String startDate) { + + + String serverID = getServerID(); + String serverAddress = getServerAddress(); + String serverKey = getServerKey(); + + String username = ctx.getUser().getUserName(); + String siteId = getReqSrc(); + + if (serverID == null || serverAddress == null || serverKey == null ) { + logger.error("Unable to retrieve learning designs from LAMS, one or more lams configuration properties is null"); + return null; + } + + try { + + String datetime = new Date().toString(); + String hashValue = LamstwoUtils.generateAuthenticationHash(serverID, serverKey, username, datetime); + + LessonManagerService service = new LessonManagerServiceLocator(); + LessonManager lessonManager = service.getLessonManagerService(new URL(serverAddress + "/services/LessonManagerService")); + Long lessonId = lessonManager.scheduleLesson(serverID, datetime, hashValue, username, ldId, siteId, title, desc, startDate, "US", "en"); + + return lessonId; + + } catch (MalformedURLException e) { + logger.error("Unable to schedule LAMS lesson, bad URL: '" + + serverAddress + + "', please check sakai.properties"); + } catch (ServiceException e) { + logger.error("Unable to schedule LAMS lesson, RPC Service Exception"); + e.printStackTrace(); + } catch (RemoteException e) { + logger.error("Unable to schedule LAMS lesson, RMI Remote Exception"); + e.printStackTrace(); + } + return null; + } + + public static Long startLesson(Context ctx, long ldId, String title, String desc) { + + String serverID = getServerID(); + String serverAddress = getServerAddress(); + String serverKey = getServerKey(); + + String username = ctx.getUser().getUserName(); + String siteId = getReqSrc(); + + if (serverID == null || serverAddress == null || serverKey == null ) { + logger.error("Unable to retrieve learning designs from LAMS, one or more lams configuration properties is null"); + return null; + } + + try { + + String datetime = new Date().toString(); + String hashValue = LamstwoUtils.generateAuthenticationHash(serverID, serverKey, username, datetime); + + LessonManagerService service = new LessonManagerServiceLocator(); + LessonManager lessonManager = service.getLessonManagerService(new URL(serverAddress + "/services/LessonManagerService")); + Long lessonId = lessonManager.startLesson(serverID, datetime, hashValue, username, ldId, siteId, title, desc, "en", "US"); + + return lessonId; + + } catch (MalformedURLException e) { + logger.error("Unable to start LAMS lesson, bad URL: '" + + serverAddress + + "', please check sakai.properties"); + } catch (ServiceException e) { + logger.error("Unable to start LAMS lesson, RPC Service Exception"); + e.printStackTrace(); + } catch (RemoteException e) { + logger.error("Unable to start LAMS lesson, RMI Remote Exception"); + e.printStackTrace(); + } + return null; + } + + /* + * TODO: + */ + public static boolean deleteLesson(Context ctx, long lsId) { + String serverID = getServerID(); + String serverAddress = getServerAddress(); + String serverKey = getServerKey(); + + String username = ctx.getUser().getUserName(); + + + if (serverID == null || serverAddress == null || serverKey == null ) { + logger.error("Unable to delete LAMS lesson: lsid = " + lsId + ", one or more lams configuration properties is null"); + return false; + } + + try { + String datetime = new Date().toString(); + String hashValue = LamstwoUtils.generateAuthenticationHash(serverID, serverKey, username, datetime); + LessonManagerService service = new LessonManagerServiceLocator(); + LessonManager lessonManager = service.getLessonManagerService(new URL(serverAddress + "/services/LessonManagerService")); + lessonManager.deleteLesson(serverID, datetime, hashValue, username, lsId); + + return true; + + } catch (MalformedURLException e) { + logger.error("Unable to delete LAMS lesson, lsid = " + lsId + ": ', bad URL: '" + + serverAddress + + "', please check sakai.properties"); + } catch (ServiceException e) { + logger.error("Unable to start LAMS lesson, RPC Service Exception"); + e.printStackTrace(); + } catch (RemoteException e) { + logger.error("Unable to start LAMS lesson, RMI Remote Exception"); + e.printStackTrace(); + } + return false; + } + + + public static String getServerAddress() + { + return LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_LAMS_URL); + } + + public static String getServerID() + { + return LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_LAMS_SERVER_ID); + } + + public static String getServerKey() + { + return LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_LAMS_SECRET_KEY); + } + + public static String getReqSrc() + { + return LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_REQ_SRC); + } + + + + + public static String convertToTigraFormat(Node node) { + + StringBuilder sb = new StringBuilder(); + + if (node.getNodeName().equals(Constants.ELEM_FOLDER)) { + sb.append("['"); + sb.append( + node.getAttributes().getNamedItem( + Constants.ATTR_NAME).getNodeValue()).append( + "',").append("null").append(','); + + NodeList children = node.getChildNodes(); + if (children.getLength() == 0) { + sb.append("['',null]"); + } else { + sb.append(convertToTigraFormat(children.item(0))); + for (int i = 1; i < children.getLength(); i++) { + sb.append(',').append( + convertToTigraFormat(children.item(i))); + } + } + sb.append(']'); + } else if (node.getNodeName().equals( + Constants.ELEM_LEARNING_DESIGN)) { + sb.append('['); + sb.append('\'').append( + node.getAttributes().getNamedItem( + Constants.ATTR_NAME).getNodeValue()).append( + '\'').append(',').append('\'').append( + node.getAttributes().getNamedItem( + Constants.ATTR_RESOURCE_ID).getNodeValue()) + .append('\''); + sb.append(']'); + } + return sb.toString(); + } + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String login, String method, String serverId) { + String secretkey = LamsPluginUtil.getSecretKey(); + + String plaintext = datetime.toLowerCase().trim() + + login.toLowerCase().trim() + + method.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey.toLowerCase().trim(); + + System.out.println(plaintext); + String hash = sha1(plaintext); + + return hash; + } + + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String login, String serverId) { + String secretkey = getServerKey(); + + String plaintext = datetime.toLowerCase().trim() + + login.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey; + + System.out.println(plaintext); + String hash = sha1(plaintext); + + return hash; + } + + //generate authentication hash code to validate parameters + public static String generateAuthenticationHash(String datetime, String serverId) + throws NoSuchAlgorithmException { + String secretkey = LamsPluginUtil.getSecretKey(); + + String plaintext = datetime.toLowerCase().trim() + + serverId.toLowerCase().trim() + + secretkey.toLowerCase().trim() ; + + return sha1(plaintext); + } + + + /** + * The parameters are: + * uid - the username on the external system + * method - either author, monitor or learner + * ts - timestamp + * sid - serverID + * str is [ts + uid + method + serverID + serverKey] (Note: all lower case) + * + * @param str The string to be hashed + * @return The hased string + */ + private static String sha1(String str){ + try{ + MessageDigest md = MessageDigest.getInstance("SHA1"); + return new String(Hex.encodeHex(md.digest(str.getBytes()))); + } catch(NoSuchAlgorithmException e){ + throw new RuntimeException(e); + } + } +} Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsServiceUtil.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsServiceUtil.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/LamsServiceUtil.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + */ +package org.lamsfoundation.ld.integration.blackboard; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.rmi.RemoteException; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import javax.xml.rpc.ServiceException; +import lamsws.LDRepository; +import lamsws.LDRepositoryServiceLocator; +import lamsws.LearningSessionManager; +import lamsws.LearningSessionManagerServiceLocator; +import lamsws.SimpleLearningDesignVO; +import lamsws.UserManager; +import lamsws.UserManagerServiceLocator; +import org.lamsfoundation.ld.integration.Constants; +import blackboard.platform.plugin.PlugInException; + +/** + * @author Luke Foxton + */ +public class LamsServiceUtil { + public static final String FILE_WS_PATH = "/lams/services/"; + private static final String WS_LEARNING_DESIGN = "LearningDesignService"; + private static final String WS_LEARNING_SESSION = "LearningSessionService"; + + + public static SimpleLearningDesignVO[] getAllLearningDesign(String login) + throws RemoteException, ServiceException + { + + LDRepository ldr = getLearningDesignRepository(); + + String timestamp = Long.toString(new Date().getTime()); + + String serverId = LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_LAMS_SERVER_ID); + String hash = LamsSecurityUtil.generateAuthenticationHash(timestamp, login, serverId); + + SimpleLearningDesignVO[] res = null; + + res = ldr.getAllLearningDesigns(serverId, timestamp, hash, login); + + return res; + } + + public static long createLearningSession(String login, long ldId, String courseId, String title, String desc) throws RemoteException, ServiceException + { + LearningSessionManager lsmanager = getLearningSessionManager(); + + String timestamp = Long.toString(new Date().getTime()); + String serverId = LamsPluginUtil.getProperties().getProperty(LamsPluginUtil.PROP_LAMS_SERVER_ID); + String hash = LamsSecurityUtil.generateAuthenticationHash(timestamp, login, serverId); + + long learningSessionId = lsmanager.createLearningSession(serverId, timestamp, hash, login, ldId, courseId, title, desc, LearningSessionManager.NORMAL); + return learningSessionId; + } + + + + + private static LearningSessionManager getLearningSessionManager() throws RemoteException, ServiceException{ + //get lamsServerUrl + String lamsServerUrl = LamsPluginUtil.getServerUrl(); + + //call the wsdl generated stubs + LearningSessionManagerServiceLocator lssService = new LearningSessionManagerServiceLocator(); + LearningSessionManager lsm = null; + + String serviceUrl = lamsServerUrl + FILE_WS_PATH + WS_LEARNING_SESSION; + + lssService.setEndpointAddress(WS_LEARNING_SESSION, serviceUrl); + lsm = lssService.getLearningSessionService(); + + return lsm; + } + + + private static LDRepository getLearningDesignRepository() throws RemoteException, ServiceException{ + //get lamsServerUrl + String lamsServerUrl = LamsPluginUtil.getServerUrl(); + + //call the wsdl generated stubs + LDRepositoryServiceLocator ldrService = new LDRepositoryServiceLocator(); + LDRepository ldr = null; + + String serviceUrl = lamsServerUrl + FILE_WS_PATH + WS_LEARNING_DESIGN; + System.out.println("trace: " + serviceUrl); + + ldrService.setEndpointAddress(WS_LEARNING_DESIGN, serviceUrl); + ldr = ldrService.getLearningDesignService(); + + return ldr; + } +} Index: lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/UserDataServlet.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/UserDataServlet.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/integration/blackboard/UserDataServlet.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,203 @@ +/** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + */ +package org.lamsfoundation.ld.integration.blackboard; + +import java.io.IOException; +import java.io.PrintWriter; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +//import javax.servlet.ServletException; + +import org.apache.commons.codec.binary.Hex; +//import org.lamsfoundation.lams.integration.security.RandomPasswordGenerator; +//import org.lamsfoundation.lams.usermanagement.AuthenticationMethod; +//import org.lamsfoundation.lams.util.HashUtil; +import org.lamsfoundation.ld.util.CSVUtil; +import org.lamsfoundation.ld.integration.Constants; + +import blackboard.persist.BbPersistenceManager; +import blackboard.persist.user.UserDbLoader; +import blackboard.platform.BbServiceManager; +import blackboard.data.user.User; +import blackboard.platform.context.ContextManager; +import blackboard.platform.context.Context; +import org.apache.log4j.Logger; + + +/** + * @author Anthony Xiao + */ +public class UserDataServlet extends HttpServlet { + + static Logger logger = Logger.getLogger(UserDataServlet.class); + + /** + * The doGet method of the servlet.
+ * + * This method is called when a form has its tag value method equals to get. + * + * @param request the request send by the client to the server + * @param response the response send by the server to the client + * @throws ServletException if an error occurred + * @throws IOException if an error occurred + */ + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException{ + + ContextManager ctxMgr = null; + Context ctx = null; + //get Blackboard context + try{ + ctxMgr = (ContextManager) BbServiceManager.lookupService(ContextManager.class); + ctx = ctxMgr.setContext(request); + + + //get Parameter values + String usernameParam = request.getParameter(Constants.PARAM_USER_ID); + String tsParam = request.getParameter(Constants.PARAM_TIMESTAMP); + String hashParam = request.getParameter(Constants.PARAM_HASH); + + //check paramaeters + if(usernameParam == null || tsParam == null || hashParam == null){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "missing expected parameters"); + return; + } + + String secretKey = LamsPluginUtil.getSecretKey(); + String serverId = LamsPluginUtil.getServerId(); + + if(!sha1(tsParam+ usernameParam + serverId + secretKey).equals(hashParam)){ + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "authentication failed"); + } + + //get the persistence manager + BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager(); + + + + //get user list, but no role info since there are no course info + UserDbLoader userLoader = (UserDbLoader) bbPm.getLoader(UserDbLoader.TYPE); + User u = userLoader.loadByUserName(usernameParam); + + if(u==null){ + throw new ServletException("user not found"); + } + + + + //construct the address + String address = u.getStreet1() + (u.getStreet1().length()==0?"":" "); + address+= u.getStreet2() + (address.length()==0?"":" "); + address+= u.getState() + (address.length()==0?"":" "); + address+= u.getCountry() + (address.length()==0?"":" "); + address+= u.getZipCode(); + //String username = u.getUserName().replaceAll(); + + + PrintWriter out = response.getWriter(); + + String loc_lang="en"; + String loc_cntry="US"; + + /* + String locale = u.getLocale(); + String loc_lang; + String loc_cntry; + if (u.getLocale()==null) + { + loc_lang="en"; + loc_cntry="US"; + } + else + { + String [] loc = locale.split("_"); + loc_lang=loc[0]; + loc_cntry=loc[1]; + } + */ + + // The CSV list should be the format below + // ,<First name>,<Last name>,<Address>,<City>,<State>, + // <Postcode>,<Country>,<Day time number>,<Mobile number>, + // <Fax number>,<Email>,<Locale language>,<Locale country> + String[] valList = { + u.getTitle(), + u.getGivenName(), + u.getFamilyName(), + u.getStreet1()+u.getStreet2(), + u.getCity(), + u.getState(), + u.getZipCode(), + u.getCountry(), + u.getHomePhone1(), + u.getMobilePhone(), + u.getBusinessFax(), + u.getEmailAddress(), + loc_lang, + loc_cntry + }; + // DEBUGGING + System.out.println(valList[0]); + System.out.println(valList[1]); + System.out.println(valList[2]); + System.out.println(valList[3]); + System.out.println(valList[4]); + System.out.println(valList[5]); + System.out.println(valList[6]); + System.out.println(valList[7]); + System.out.println(valList[8]); + System.out.println(valList[9]); + System.out.println(valList[10]); + System.out.println(valList[11]); + System.out.println(valList[12]); + System.out.println(valList[13]); + System.out.println("LUKE IS AWESOME: " + CSVUtil.write(valList)); + + + out.println(CSVUtil.write(valList)); + + } catch (Exception e){ + e.printStackTrace(); + logger.error("Problem with user data servlet: " + e.getMessage(), e); + logger.error(e.getStackTrace().toString()); + throw new ServletException("Failed to fetch user", e); + } finally{ + //make sure context is released + if (ctxMgr != null) + ctxMgr.releaseContext(); + } + } + + private String sha1(String str){ + try{ + MessageDigest md = MessageDigest.getInstance("SHA1"); + return new String(Hex.encodeHex(md.digest(str.getBytes()))); + } catch(NoSuchAlgorithmException e){ + throw new RuntimeException(e); + } + } +} Index: lams_bb_integration/src/org/lamsfoundation/ld/util/CSVUtil.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/util/CSVUtil.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/util/CSVUtil.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,170 @@ +/** + * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * http://www.gnu.org/licenses/gpl.txt + */ + +package org.lamsfoundation.ld.util; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.regex.*; + +/** + * CSVUtil Provides "Comma Seperated Value" writing and parsing. + * The two methods write() and parse() will perform writing to and parse from + * the CSV format + * + * @author <a href="mailto:anthony.xiao@lamsinternational.com">Anthony Xiao</a> + */ +public class CSVUtil { + + private static final char QUOTE = '"'; + private static final char COMMA = ','; + + /* precompile the patterns to speed up the search */ + + // should we put quotes around a value? + private static final Pattern CONTAINS_NEWLINE = Pattern.compile(".*(\\n|\\r)+.*"); + + // should we put quotes around a value? + private static final Pattern CONTAINS_COMMA = Pattern.compile(".*(,)+.*"); + + // should we escape the quotes? + private static final Pattern CONTAINS_QUOTE = Pattern.compile("\""); + + // how should we wrap qoutes around comma or newline? + private static final String WRAP_QOUTE = "\"$0\""; + + // how should we escape the value if it has qoutes? + private static final String ESCAPE_QUOTE = "\"\""; + + // has this value been wrapped with quotes + private static final Pattern WRAPPED_QUOTE = Pattern.compile("^\"(.*((,|\\n|\\r)+).*)\"$"); + + // has this value been escaped by ESCAPE_QUOTE + private static final Pattern ESCAPED_QUOTE = Pattern.compile("\"\""); + + // how should we unescape the the ESCAPED_QUOTE? + private static final String UNWRAP_QOUTE = "$1"; + + // how should we unescape the the ESCAPED_COMMA? + private static final String UNESCAPE_QUOTE = "\""; + + /* + * NOTE: why are we using \\n|\\r in CONTAINS_NEWLINE and WRAPPED_QUOTE? + * javadoc says "." represents "Any character (may or may not match line terminators)" + * and we want to make sure terminiators such as newline (\n) gets matched as well + * if we dont match it then ,\n, will get written as ","\n"," + */ + + /** + * Writes a array of String into CSV format + * @param vals - The array of string to be written into CSV format + * @return + */ + public static String write(String[] vals){ + String str = ""; + int lastIndex = vals.length - 1; + for(int i=0; i<vals.length; i++){ + // str += vals[i].replaceAll("\"", "\"\"").replaceAll(".*,.*", "\"$0\"") + + // (i==lastIndex?"":","); //same as below but used compiled patterns + + //check for quotes then escape it + String tmp = CONTAINS_QUOTE.matcher(vals[i]).replaceAll(ESCAPE_QUOTE); + //System.out.println("trace: " + vals[i] + ", " + tmp); + + //check for comma then escape it + /** + * NOTE: the replaceAll method will not replace accross multiple line + * hence \n,\n will be replaced as \n","\n but "\n,\n" is expected + * therefore we put quotes around tmp without using replace + */ + // String wrapped = CONTAINS_COMMA.matcher(tmp).replaceAll("\"$0\""); + // String wrapped = CONTAINS_COMMA.matcher(tmp).replaceAll('"' + tmp + '"'); + String wrapped = CONTAINS_COMMA.matcher(tmp).find()?'"'+tmp+'"':tmp; + + //check if tmp has been wrapped because of commas found, + //if not wrapped then look look for newline and then wrap it + if(wrapped.equals(tmp)){ + wrapped = CONTAINS_COMMA.matcher(tmp).find()?'"'+tmp+'"':tmp; + } + + + str += wrapped + (i==lastIndex?"":","); //dont append comma to the last value + } + return str; + } + + /** + * Parse the CSV formatted string and return each value seperatly stored in an array + * + * The parse() method is design to parse 1 record only, each value in the record + * can contain , newline(\n) or carriage-return(\r). + * but parse() is not design to handle newline or carriage-return outside the quoted + * values. newline or carriage-return outside the quoted values signals a new record. + * + * If someone decide parse() need to handle multiple rows of record then we can extend + * the functionaliy of this method. + * + * @param str + * @return + */ + public static String[] parse(String str) throws ParseException{ + ArrayList res = new ArrayList(); + int startIndex = 0; + boolean openQuote = false; + + str += ","; //end the last value with comma, so last value can be found correctly + + for(int i=0; i<str.length(); i++){ + char ch = str.charAt(i); + + //match pairs of quote + if(ch==QUOTE){ + openQuote = !openQuote; + } + + //if comma is detected and is not inside quotes, then we have found a value + else if((ch==COMMA) && !openQuote){ + String val = str.substring(startIndex, i); + //System.out.println("trace: found - " + val); + + // check for escaped quote then unescape it + String tmp = ESCAPED_QUOTE.matcher(val).replaceAll(UNESCAPE_QUOTE); + + // check for wrapped quotes then unwrap it + res.add(WRAPPED_QUOTE.matcher(tmp).replaceAll(UNWRAP_QOUTE)); + //System.out.println("trace: " + val + " - " + tmp); + + //res.add(val.replaceAll("^\"((.|\\p{Space})+)\"$", "$1").replaceAll("\"\"", "\"")); + + startIndex = i + 1; + } + } + if(openQuote){ + throw new ParseException("Fail to find matching \" while parsing [" + str + "] ", startIndex); + } + + String [] resStr = new String[res.size()]; + res.toArray(resStr); + + + return resStr; + } +} Index: lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManager.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManager.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManager.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,25 @@ +/****************************************************************************** + * LessonManager.java + * + * Copyright (c) 2007 LAMS Foundation + * Licensed under the Educational Community License version 1.0 + * + * A copy of the Educational Community License has been included in this + * distribution and is available at: http://www.opensource.org/licenses/ecl1.php + * + *****************************************************************************/ + +/** + * LessonManager.java + * + * This file was auto-generated from WSDL + * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter. + */ + +package org.lamsfoundation.lams.webservice; + +public interface LessonManager extends java.rmi.Remote { + public java.lang.Long startLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long ldId, java.lang.String courseId, java.lang.String title, java.lang.String desc, java.lang.String countryIsoCode, java.lang.String langIsoCode) throws java.rmi.RemoteException; + public java.lang.Long scheduleLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long ldId, java.lang.String courseId, java.lang.String title, java.lang.String desc, java.lang.String startDate, java.lang.String countryIsoCode, java.lang.String langIsoCode) throws java.rmi.RemoteException; + public boolean deleteLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long lsId) throws java.rmi.RemoteException; +} Index: lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerService.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerService.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerService.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,27 @@ +/****************************************************************************** + * LessonManagerService.java + * + * Copyright (c) 2007 LAMS Foundation + * Licensed under the Educational Community License version 1.0 + * + * A copy of the Educational Community License has been included in this + * distribution and is available at: http://www.opensource.org/licenses/ecl1.php + * + *****************************************************************************/ + +/** + * LessonManagerService.java + * + * This file was auto-generated from WSDL + * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter. + */ + +package org.lamsfoundation.lams.webservice; + +public interface LessonManagerService extends javax.xml.rpc.Service { + public java.lang.String getLessonManagerServiceAddress(); + + public org.lamsfoundation.lams.webservice.LessonManager getLessonManagerService() throws javax.xml.rpc.ServiceException; + + public org.lamsfoundation.lams.webservice.LessonManager getLessonManagerService(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; +} Index: lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceLocator.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceLocator.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceLocator.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,153 @@ +/****************************************************************************** + * LessonManagerServiceLocator.java + * + * Copyright (c) 2007 LAMS Foundation + * Licensed under the Educational Community License version 1.0 + * + * A copy of the Educational Community License has been included in this + * distribution and is available at: http://www.opensource.org/licenses/ecl1.php + * + *****************************************************************************/ + +/** + * LessonManagerServiceLocator.java + * + * This file was auto-generated from WSDL + * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter. + */ + +package org.lamsfoundation.lams.webservice; + +public class LessonManagerServiceLocator extends org.apache.axis.client.Service implements org.lamsfoundation.lams.webservice.LessonManagerService { + + public LessonManagerServiceLocator() { + } + + + public LessonManagerServiceLocator(org.apache.axis.EngineConfiguration config) { + super(config); + } + + public LessonManagerServiceLocator(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException { + super(wsdlLoc, sName); + } + + // Use to get a proxy class for LessonManagerService + private java.lang.String LessonManagerService_address = "http://localhost:8080/lams/services/LessonManagerService"; + + public java.lang.String getLessonManagerServiceAddress() { + return LessonManagerService_address; + } + + // The WSDD service name defaults to the port name. + private java.lang.String LessonManagerServiceWSDDServiceName = "LessonManagerService"; + + public java.lang.String getLessonManagerServiceWSDDServiceName() { + return LessonManagerServiceWSDDServiceName; + } + + public void setLessonManagerServiceWSDDServiceName(java.lang.String name) { + LessonManagerServiceWSDDServiceName = name; + } + + public org.lamsfoundation.lams.webservice.LessonManager getLessonManagerService() throws javax.xml.rpc.ServiceException { + java.net.URL endpoint; + try { + endpoint = new java.net.URL(LessonManagerService_address); + } + catch (java.net.MalformedURLException e) { + throw new javax.xml.rpc.ServiceException(e); + } + return getLessonManagerService(endpoint); + } + + public org.lamsfoundation.lams.webservice.LessonManager getLessonManagerService(java.net.URL portAddress) throws javax.xml.rpc.ServiceException { + try { + org.lamsfoundation.lams.webservice.LessonManagerServiceSoapBindingStub _stub = new org.lamsfoundation.lams.webservice.LessonManagerServiceSoapBindingStub(portAddress, this); + _stub.setPortName(getLessonManagerServiceWSDDServiceName()); + return _stub; + } + catch (org.apache.axis.AxisFault e) { + return null; + } + } + + public void setLessonManagerServiceEndpointAddress(java.lang.String address) { + LessonManagerService_address = address; + } + + /** + * For the given interface, get the stub implementation. + * If this service has no port for the given interface, + * then ServiceException is thrown. + */ + public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException { + try { + if (org.lamsfoundation.lams.webservice.LessonManager.class.isAssignableFrom(serviceEndpointInterface)) { + org.lamsfoundation.lams.webservice.LessonManagerServiceSoapBindingStub _stub = new org.lamsfoundation.lams.webservice.LessonManagerServiceSoapBindingStub(new java.net.URL(LessonManagerService_address), this); + _stub.setPortName(getLessonManagerServiceWSDDServiceName()); + return _stub; + } + } + catch (java.lang.Throwable t) { + throw new javax.xml.rpc.ServiceException(t); + } + throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface: " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName())); + } + + /** + * For the given interface, get the stub implementation. + * If this service has no port for the given interface, + * then ServiceException is thrown. + */ + public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException { + if (portName == null) { + return getPort(serviceEndpointInterface); + } + java.lang.String inputPortName = portName.getLocalPart(); + if ("LessonManagerService".equals(inputPortName)) { + return getLessonManagerService(); + } + else { + java.rmi.Remote _stub = getPort(serviceEndpointInterface); + ((org.apache.axis.client.Stub) _stub).setPortName(portName); + return _stub; + } + } + + public javax.xml.namespace.QName getServiceName() { + return new javax.xml.namespace.QName("http://webservice.lams.lamsfoundation.org", "LessonManagerService"); + } + + private java.util.HashSet ports = null; + + public java.util.Iterator getPorts() { + if (ports == null) { + ports = new java.util.HashSet(); + ports.add(new javax.xml.namespace.QName("http://webservice.lams.lamsfoundation.org", "LessonManagerService")); + } + return ports.iterator(); + } + + /** + * Set the endpoint address for the specified port name. + */ + public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException { + +if ("LessonManagerService".equals(portName)) { + setLessonManagerServiceEndpointAddress(address); + } + else +{ // Unknown Port Name + throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName); + } + } + + /** + * Set the endpoint address for the specified port name. + */ + public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException { + setEndpointAddress(portName.getLocalPart(), address); + } + +} Index: lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceSoapBindingStub.java =================================================================== diff -u --- lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceSoapBindingStub.java (revision 0) +++ lams_bb_integration/src/org/lamsfoundation/ld/webservice/LessonManagerServiceSoapBindingStub.java (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,262 @@ +/****************************************************************************** + * LessonManagerServiceSoapBindingStub.java + * + * Copyright (c) 2007 LAMS Foundation + * Licensed under the Educational Community License version 1.0 + * + * A copy of the Educational Community License has been included in this + * distribution and is available at: http://www.opensource.org/licenses/ecl1.php + * + *****************************************************************************/ + +/** + * LessonManagerServiceSoapBindingStub.java + * + * This file was auto-generated from WSDL + * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter. + */ + +package org.lamsfoundation.lams.webservice; + +public class LessonManagerServiceSoapBindingStub extends org.apache.axis.client.Stub implements org.lamsfoundation.lams.webservice.LessonManager { + private java.util.Vector cachedSerClasses = new java.util.Vector(); + private java.util.Vector cachedSerQNames = new java.util.Vector(); + private java.util.Vector cachedSerFactories = new java.util.Vector(); + private java.util.Vector cachedDeserFactories = new java.util.Vector(); + + static org.apache.axis.description.OperationDesc [] _operations; + + static { + _operations = new org.apache.axis.description.OperationDesc[3]; + _initOperationDesc1(); + } + + private static void _initOperationDesc1(){ + org.apache.axis.description.OperationDesc oper; + org.apache.axis.description.ParameterDesc param; + oper = new org.apache.axis.description.OperationDesc(); + oper.setName("startLesson"); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "serverId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "datetime"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "hashValue"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "username"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "ldId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "long"), long.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "courseId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "title"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "desc"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "countryIsoCode"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "langIsoCode"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + oper.setReturnType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "long")); + oper.setReturnClass(java.lang.Long.class); + oper.setReturnQName(new javax.xml.namespace.QName("", "startLessonReturn")); + oper.setStyle(org.apache.axis.constants.Style.RPC); + oper.setUse(org.apache.axis.constants.Use.ENCODED); + _operations[0] = oper; + + oper = new org.apache.axis.description.OperationDesc(); + oper.setName("scheduleLesson"); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "serverId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "datetime"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "hashValue"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "username"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "ldId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "long"), long.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "courseId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "title"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "desc"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "startDate"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "countryIsoCode"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "langIsoCode"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + oper.setReturnType(new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "long")); + oper.setReturnClass(java.lang.Long.class); + oper.setReturnQName(new javax.xml.namespace.QName("", "scheduleLessonReturn")); + oper.setStyle(org.apache.axis.constants.Style.RPC); + oper.setUse(org.apache.axis.constants.Use.ENCODED); + _operations[1] = oper; + + oper = new org.apache.axis.description.OperationDesc(); + oper.setName("deleteLesson"); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "serverId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "datetime"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "hashValue"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "username"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://schemas.xmlsoap.org/soap/encoding/", "string"), java.lang.String.class, false, false); + oper.addParameter(param); + param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("", "lsId"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "long"), long.class, false, false); + oper.addParameter(param); + oper.setReturnType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "boolean")); + oper.setReturnClass(boolean.class); + oper.setReturnQName(new javax.xml.namespace.QName("", "deleteLessonReturn")); + oper.setStyle(org.apache.axis.constants.Style.RPC); + oper.setUse(org.apache.axis.constants.Use.ENCODED); + _operations[2] = oper; + + } + + public LessonManagerServiceSoapBindingStub() throws org.apache.axis.AxisFault { + this(null); + } + + public LessonManagerServiceSoapBindingStub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault { + this(service); + super.cachedEndpoint = endpointURL; + } + + public LessonManagerServiceSoapBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault { + if (service == null) { + super.service = new org.apache.axis.client.Service(); + } else { + super.service = service; + } + ((org.apache.axis.client.Service)super.service).setTypeMappingVersion("1.2"); + } + + protected org.apache.axis.client.Call createCall() throws java.rmi.RemoteException { + try { + org.apache.axis.client.Call _call = super._createCall(); + if (super.maintainSessionSet) { + _call.setMaintainSession(super.maintainSession); + } + if (super.cachedUsername != null) { + _call.setUsername(super.cachedUsername); + } + if (super.cachedPassword != null) { + _call.setPassword(super.cachedPassword); + } + if (super.cachedEndpoint != null) { + _call.setTargetEndpointAddress(super.cachedEndpoint); + } + if (super.cachedTimeout != null) { + _call.setTimeout(super.cachedTimeout); + } + if (super.cachedPortName != null) { + _call.setPortName(super.cachedPortName); + } + java.util.Enumeration keys = super.cachedProperties.keys(); + while (keys.hasMoreElements()) { + java.lang.String key = (java.lang.String) keys.nextElement(); + _call.setProperty(key, super.cachedProperties.get(key)); + } + return _call; + } + catch (java.lang.Throwable _t) { + throw new org.apache.axis.AxisFault("Failure trying to get the Call object", _t); + } + } + + public java.lang.Long startLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long ldId, java.lang.String courseId, java.lang.String title, java.lang.String desc, java.lang.String countryIsoCode, java.lang.String langIsoCode) throws java.rmi.RemoteException { + if (super.cachedEndpoint == null) { + throw new org.apache.axis.NoEndPointException(); + } + org.apache.axis.client.Call _call = createCall(); + _call.setOperation(_operations[0]); + _call.setUseSOAPAction(true); + _call.setSOAPActionURI(""); + _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); + _call.setOperationName(new javax.xml.namespace.QName("http://webservice.lams.lamsfoundation.org", "startLesson")); + + setRequestHeaders(_call); + setAttachments(_call); + try { java.lang.Object _resp = _call.invoke(new java.lang.Object[] {serverId, datetime, hashValue, username, new java.lang.Long(ldId), courseId, title, desc, countryIsoCode, langIsoCode}); + + if (_resp instanceof java.rmi.RemoteException) { + throw (java.rmi.RemoteException)_resp; + } + else { + extractAttachments(_call); + try { + return (java.lang.Long) _resp; + } catch (java.lang.Exception _exception) { + return (java.lang.Long) org.apache.axis.utils.JavaUtils.convert(_resp, java.lang.Long.class); + } + } + } catch (org.apache.axis.AxisFault axisFaultException) { + throw axisFaultException; +} + } + + public java.lang.Long scheduleLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long ldId, java.lang.String courseId, java.lang.String title, java.lang.String desc, java.lang.String startDate, java.lang.String countryIsoCode, java.lang.String langIsoCode) throws java.rmi.RemoteException { + if (super.cachedEndpoint == null) { + throw new org.apache.axis.NoEndPointException(); + } + org.apache.axis.client.Call _call = createCall(); + _call.setOperation(_operations[1]); + _call.setUseSOAPAction(true); + _call.setSOAPActionURI(""); + _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); + _call.setOperationName(new javax.xml.namespace.QName("http://webservice.lams.lamsfoundation.org", "scheduleLesson")); + + setRequestHeaders(_call); + setAttachments(_call); + try { java.lang.Object _resp = _call.invoke(new java.lang.Object[] {serverId, datetime, hashValue, username, new java.lang.Long(ldId), courseId, title, desc, startDate, countryIsoCode, langIsoCode}); + + if (_resp instanceof java.rmi.RemoteException) { + throw (java.rmi.RemoteException)_resp; + } + else { + extractAttachments(_call); + try { + return (java.lang.Long) _resp; + } catch (java.lang.Exception _exception) { + return (java.lang.Long) org.apache.axis.utils.JavaUtils.convert(_resp, java.lang.Long.class); + } + } + } catch (org.apache.axis.AxisFault axisFaultException) { + throw axisFaultException; +} + } + + public boolean deleteLesson(java.lang.String serverId, java.lang.String datetime, java.lang.String hashValue, java.lang.String username, long lsId) throws java.rmi.RemoteException { + if (super.cachedEndpoint == null) { + throw new org.apache.axis.NoEndPointException(); + } + org.apache.axis.client.Call _call = createCall(); + _call.setOperation(_operations[2]); + _call.setUseSOAPAction(true); + _call.setSOAPActionURI(""); + _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS); + _call.setOperationName(new javax.xml.namespace.QName("http://webservice.lams.lamsfoundation.org", "deleteLesson")); + + setRequestHeaders(_call); + setAttachments(_call); + try { java.lang.Object _resp = _call.invoke(new java.lang.Object[] {serverId, datetime, hashValue, username, new java.lang.Long(lsId)}); + + if (_resp instanceof java.rmi.RemoteException) { + throw (java.rmi.RemoteException)_resp; + } + else { + extractAttachments(_call); + try { + return ((java.lang.Boolean) _resp).booleanValue(); + } catch (java.lang.Exception _exception) { + return ((java.lang.Boolean) org.apache.axis.utils.JavaUtils.convert(_resp, boolean.class)).booleanValue(); + } + } + } catch (org.apache.axis.AxisFault axisFaultException) { + throw axisFaultException; +} + } + +} Index: lams_bb_integration/web/admin/config.jsp =================================================================== diff -u --- lams_bb_integration/web/admin/config.jsp (revision 0) +++ lams_bb_integration/web/admin/config.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,59 @@ +<%@page import="java.util.Properties, + blackboard.platform.BbServiceManager, + blackboard.platform.plugin.PlugInUtil, + blackboard.platform.security.AccessManagerService, + org.lamsfoundation.ld.integration.blackboard.LamsPluginUtil" + errorPage="/error.jsp" +%> + +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<bbData:context id="ctx"> + +<% + // SECURITY! + AccessManagerService accessManager = (AccessManagerService) BbServiceManager.lookupService(AccessManagerService.class); + if (!PlugInUtil.authorizeForSystemAdmin(request,response)){ + accessManager.sendAccessDeniedRedirect(request,response); + return; + } + + Properties p = LamsPluginUtil.getProperties(); + String lamsServerUrl = p.getProperty("LAMS_SERVER_URL", "http://"); + String lamsServerId = p.getProperty("LAMS_SERVER_ID", ""); + String SecretKey = p.getProperty("LAMS_SERVER_SKEY", ""); + String ReqSrc = p.getProperty("BB_REQ_SRC"); +%> + +<bbUI:docTemplate title="Configure LAMS"> +<bbUI:breadcrumbBar handle="admin_plugin_manage"> + <bbUI:breadcrumb>LAMS Configuration</bbUI:breadcrumb> +</bbUI:breadcrumbBar> +<bbUI:titleBar iconUrl="/images/ci/icons/tools_u.gif">Configure Sample Plugin.</bbUI:titleBar> +<form action="config_proc.jsp"> + <bbUI:step title="Select Plug-in" number="1"> + <bbUI:dataElement label="LAMS SERVER URL"> + <input type="text" name="lams_server_url" size="70" value="<%=lamsServerUrl%>"> + </bbUI:dataElement> + <bbUI:dataElement label="LAMS SERVER ID"> + <input type="text" name="lams_server_id" size="70" value="<%=lamsServerId%>"> + </bbUI:dataElement> + <bbUI:dataElement label="LAMS SERVER SECRET KEY"> + <input type="text" name="lams_server_skey" size="70" value="<%=SecretKey%>"> + </bbUI:dataElement> + <bbUI:dataElement label="BLACKBOARD REQUEST SRC"> + <input type="text" name="bb_req_src" size="70" value="<%=ReqSrc%>"> + </bbUI:dataElement> + </bbUI:step> + <bbUI:step title="Callback URL" number="2"> + <bbUI:instructions> + Copy and paste the user data callback URL into LAMS <BR> + <B>USER DATA CALLBACK URL</B>: http://<%=request.getServerName()%><%=request.getContextPath()%>/UserData?uid=%username%&ts=%timestamp%&hash=%hash% + </bbUI:instructions> + </bbUI:step> + <bbUI:stepSubmit title="Submit" number="3" /> + +</form> + +</bbUI:docTemplate> +</bbData:context> \ No newline at end of file Index: lams_bb_integration/web/admin/config_proc.jsp =================================================================== diff -u --- lams_bb_integration/web/admin/config_proc.jsp (revision 0) +++ lams_bb_integration/web/admin/config_proc.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,50 @@ +<%@page import="java.util.Properties, + blackboard.platform.BbServiceManager, + blackboard.platform.plugin.PlugInUtil, + blackboard.platform.security.AccessManagerService, + org.lamsfoundation.ld.integration.blackboard.LamsPluginUtil" + + errorPage="/error.jsp" +%> + +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<bbData:context id="ctx"> +<% + // SECURITY! + AccessManagerService accessManager = (AccessManagerService) BbServiceManager.lookupService(AccessManagerService.class); + if (!PlugInUtil.authorizeForSystemAdmin(request,response)){ + accessManager.sendAccessDeniedRedirect(request,response); + return; + } + Properties p = LamsPluginUtil.getProperties(); + String lamsServerUrl = request.getParameter("lams_server_url"); + String lamsServerSkey = request.getParameter("lams_server_skey"); + String lamsServerId = request.getParameter("lams_server_id"); + String bbReqSrc = request.getParameter("bb_req_src"); + + p.setProperty(LamsPluginUtil.PROP_LAMS_URL, lamsServerUrl); + p.setProperty(LamsPluginUtil.PROP_LAMS_SECRET_KEY, lamsServerSkey); + p.setProperty(LamsPluginUtil.PROP_LAMS_SERVER_ID, lamsServerId); + p.setProperty("BB_REQ_SRC", bbReqSrc); + + LamsPluginUtil.setProperties(p); //persist the properties file +%> + <bbUI:docTemplate title="Configure Sample Plug-in"> + <bbUI:breadcrumbBar handle="admin_plugin_manage"> + <bbUI:breadcrumb>LAMS Configuration</bbUI:breadcrumb> + </bbUI:breadcrumbBar> + <bbUI:receipt type="SUCCESS" + iconUrl="/images/ci/icons/tools_u.gif" + title="Configure LAMS Plugin." + recallUrl="/webapps/blackboard/admin/manage_plugins.jsp"> + <h4>Sample plugin configured</h4><p> + LAMS_SERVER_URL: <%= lamsServerUrl %><br> + LAMS_SERVER_SKEY: <%= lamsServerSkey %><br> + LAMS_SERVER_ID: <%= lamsServerId %><br> + BB_REQ_SRC: <%= bbReqSrc %> + </bbUI:receipt> + <br> + + </bbUI:docTemplate> +</bbData:context> \ No newline at end of file Index: lams_bb_integration/web/error.jsp =================================================================== diff -u --- lams_bb_integration/web/error.jsp (revision 0) +++ lams_bb_integration/web/error.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,19 @@ +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ page import="java.io.PrintWriter"%> +<%@ page isErrorPage = "true" %> +<% + String strException = exception.getMessage(); + response.setStatus(response.SC_INTERNAL_SERVER_ERROR); +%> +<bbUI:receipt type="FAIL" title="Error"> +<%=strException%> +<p> +<pre> +<% + // now display a stack trace of the exception + PrintWriter pw = new PrintWriter( out ); + exception.printStackTrace( pw ); +%> +</pre> +</bbUI:receipt><br> + Index: lams_bb_integration/web/images/Thumbs.db =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/images/logo.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/tree.js =================================================================== diff -u --- lams_bb_integration/web/lib/tigra/tree.js (revision 0) +++ lams_bb_integration/web/lib/tigra/tree.js (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,8 @@ +// Title: Tigra Tree +// Description: See the demo at url +// URL: http://www.softcomplex.com/products/tigra_menu_tree/ +// Version: 1.1 (size optimized) +// Date: 11-12-2002 (mm-dd-yyyy) +// Notes: This script is free. Visit official site for further details. + +function tree(tm0,tm1){this.tm2=tm1;this.tm3=tm0;this.tm4=this;this.tm5=[];this.tm6=null;this.tm7=-1;var tm8=new Image(),tm9=new Image();tm8.src=tm1['icon_e'];tm9.src=tm1['icon_l'];tm1['im_e']=tm8;tm1['im_l']=tm9;for(var i=0;i<64;i++)if(tm1['icon_'+i]){var tmA=new Image();tm1['im_'+i]=tmA;tmA.src=tm1['icon_'+i]}this.tmB=function(tmC){var tmD=this.tm5[tmC];tmD.tmE(tmD.tmF)};this.tmG=function(tmC){return this.tm5[tmC].tmG()};this.tmH=function(tmC){this.tm5[tmC].tmI(true)};this.tmJ=function(tmC){this.tm5[tmC].tmI()};this.tmK=[];for(var i=0;i<tm0.length;i++)new tmL(this,i);this.tmC=trees.length;trees[this.tmC]=this;for(var i=0;i<this.tmK.length;i++){document.write(this.tmK[i].tmM());this.tmK[i].tmE()}}function tmL(tmN,tmO){this.tm7=tmN.tm7+1;this.tm3=tmN.tm3[tmO+(this.tm7?2:0)];if(!this.tm3)return;this.tm4=tmN.tm4;this.tmN=tmN;this.tmO=tmO;this.tmF=!this.tm7;this.tmC=this.tm4.tm5.length;this.tm4.tm5[this.tmC]=this;tmN.tmK[tmO]=this;this.tmK=[];for(var i=0;i<this.tm3.length-2;i++)new tmL(this,i);this.tmP=tmQ;this.tmE=tmR;this.tmG=tmS;this.tmM=tmT;this.tmI=tmU;this.tmV=function(){return this.tmO==this.tmN.tmK.length-1}}function tmR(tmW){var tmX=tmY('i_div'+this.tm4.tmC+'_'+this.tmC);if(!tmX)return;if(!tmX.innerHTML){var tmK=[];for(var i=0;i<this.tmK.length;i++)tmK[i]=this.tmK[i].tmM();tmX.innerHTML=tmK.join('')}tmX.style.display=(tmW?'none':'block');this.tmF=!tmW;var tmZ=document.images['j_img'+this.tm4.tmC+'_'+this.tmC],tma=document.images['i_img'+this.tm4.tmC+'_'+this.tmC];if(tmZ)tmZ.src=this.tmP(true);if(tma)tma.src=this.tmP();this.tmI()}function tmS(tmb){if(!tmb){var tmc=this.tm4.tm6;this.tm4.tm6=this;if(tmc)tmc.tmG(true)}var tma=document.images['i_img'+this.tm4.tmC+'_'+this.tmC];if(tma)tma.src=this.tmP();tmY('i_txt'+this.tm4.tmC+'_'+this.tmC).style.fontWeight=tmb?'normal':'bold';this.tmI();return Boolean(this.tm3[1])}function tmU(tmd){window.setTimeout('window.status="'+(tmd?'':this.tm3[0]+(this.tm3[1]?' ('+this.tm3[1]+')':''))+'"',10)}function tmT(){var tme=[],tmf=this.tmN;for(var i=this.tm7;i>1;i--){tme[i]='<img src="'+this.tm4.tm2[tmf.tmV()?'icon_e':'icon_l']+'" border="0" align="absbottom">';tmf=tmf.tmN}return '<table cellpadding="0" cellspacing="0" border="0"><tr><td nowrap>'+(this.tm7?tme.join('')+(this.tmK.length?'<a href="javascript: trees['+this.tm4.tmC+'].tmB('+this.tmC+')" onmouseover="trees['+this.tm4.tmC+'].tmJ('+this.tmC+')" onmouseout="trees['+this.tm4.tmC+'].tmH('+this.tmC+')"><img src="'+this.tmP(true)+'" border="0" align="absbottom" name="j_img'+this.tm4.tmC+'_'+this.tmC+'"></a>':'<img src="'+this.tmP(true)+'" border="0" align="absbottom">'):'')+'<a href="'+this.tm3[1]+'" target="'+this.tm4.tm2['target']+'" onclick="return trees['+this.tm4.tmC+'].tmG('+this.tmC+')" ondblclick="trees['+this.tm4.tmC+'].tmB('+this.tmC+')" onmouseover="trees['+this.tm4.tmC+'].tmJ('+this.tmC+')" onmouseout="trees['+this.tm4.tmC+'].tmH('+this.tmC+')" class="t'+this.tm4.tmC+'i" id="i_txt'+this.tm4.tmC+'_'+this.tmC+'"><img src="'+this.tmP()+'" border="0" align="absbottom" name="i_img'+this.tm4.tmC+'_'+this.tmC+'" class="t'+this.tm4.tmC+'im">'+this.tm3[0]+'</a></td></tr></table>'+(this.tmK.length?'<div id="i_div'+this.tm4.tmC+'_'+this.tmC+'" style="display:none"></div>':'')}function tmQ(tmg){return this.tm4.tm2['icon_'+((this.tm7?0:32)+(this.tmK.length?16:0)+(this.tmK.length&&this.tmF?8:0)+(!tmg&&this.tm4.tm6==this?4:0)+(tmg?2:0)+(tmg&&this.tmV()?1:0))]}var trees=[];tmY=document.all?function(tmh){return document.all[tmh]}:function(tmh){return document.getElementById(tmh)}; \ No newline at end of file Index: lams_bb_integration/web/lib/tigra/tree_tpl.js =================================================================== diff -u --- lams_bb_integration/web/lib/tigra/tree_tpl.js (revision 0) +++ lams_bb_integration/web/lib/tigra/tree_tpl.js (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,36 @@ +/* + Feel free to use your custom treeicons for the tree. Make sure they are all of the same size. + User treeicons collections are welcome, we'll publish them giving all regards. +*/ + +var TREE_TPL = { + 'target' : '_self', // name of the frame links will be opened in + // other possible values are: _blank, _parent, _search, _self and _top + + 'icon_e' : '../lib/tigra/treeicons/empty.gif', // empty image + 'icon_l' : '../lib/tigra/treeicons/line.gif', // vertical line + + 'icon_32' : '../lib/tigra/treeicons/base.gif', // root leaf icon normal + 'icon_36' : '../lib/tigra/treeicons/base.gif', // root leaf icon selected + + 'icon_48' : '../lib/tigra/treeicons/base.gif', // root icon normal + 'icon_52' : '../lib/tigra/treeicons/base.gif', // root icon selected + 'icon_56' : '../lib/tigra/treeicons/base.gif', // root icon opened + 'icon_60' : '../lib/tigra/treeicons/base.gif', // root icon selected + + 'icon_16' : '../lib/tigra/treeicons/folder.gif', // node icon normal + 'icon_20' : '../lib/tigra/treeicons/folderopen.gif', // node icon selected + 'icon_24' : '../lib/tigra/treeicons/folderopen.gif', // node icon opened + 'icon_28' : '../lib/tigra/treeicons/folderopen.gif', // node icon selected opened + + 'icon_0' : '../lib/tigra/treeicons/page.gif', // leaf icon normal + 'icon_4' : '../lib/tigra/treeicons/page.gif', // leaf icon selected + + 'icon_2' : '../lib/tigra/treeicons/joinbottom.gif', // junction for leaf + 'icon_3' : '../lib/tigra/treeicons/join.gif', // junction for last leaf + 'icon_18' : '../lib/tigra/treeicons/plusbottom.gif', // junction for closed node + 'icon_19' : '../lib/tigra/treeicons/plus.gif', // junctioin for last closed node + 'icon_26' : '../lib/tigra/treeicons/minusbottom.gif',// junction for opened node + 'icon_27' : '../lib/tigra/treeicons/minus.gif' // junctioin for last opended node +}; + Index: lams_bb_integration/web/lib/tigra/treeicons/Thumbs.db =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/base.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/empty.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/folder.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/folderopen.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/join.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/joinbottom.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/line.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/minus.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/minusbottom.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/page.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/plus.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/lib/tigra/treeicons/plusbottom.gif =================================================================== diff -u Binary files differ Index: lams_bb_integration/web/modules/create.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/create.jsp (revision 0) +++ lams_bb_integration/web/modules/create.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,104 @@ +<%@ page import="blackboard.platform.plugin.PlugInUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.Constants"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsSecurityUtil"%> +<%@ page errorPage="/error.jsp"%> + +<%@ taglib uri="/bbData" prefix="bbData"%> +<%@ taglib uri="/bbUI" prefix="bbUI"%> + +<bbData:context id="ctx"> +<bbUI:docTemplate title = "Add new LAMS"> + +<% + // SECURITY! + //AccessManagerService accessManager = (AccessManagerService) BbServiceManager.lookupService(AccessManagerService.class); + if (!PlugInUtil.authorizeForCourseControlPanel(request,response)){ + //accessManager.sendAccessDeniedRedirect(request,response); + //TODO: redirect user to login page, since sendAccessDeniedRedirect is deprecated another way is needed + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + String authorUrl = LamsSecurityUtil.generateRequestURL(ctx, "author"); + String learningDesigns = LamsSecurityUtil.getLearningDesigns(ctx, 2); +%> + +<bbUI:breadcrumbBar handle="control_panel" isContent="true" > + <bbUI:breadcrumb>Add new LAMS</bbUI:breadcrumb> +</bbUI:breadcrumbBar> + +<bbUI:titleBar iconUrl ="/images/ci/icons/bookopen_u.gif">Add new LAMS</bbUI:titleBar> + + + + + +<form name="workspace_form" id="workspace_form" action="start_lesson.jsp" method="post"> + <input type="hidden" name="content_id" value="<%=request.getParameter("content_id")%>"> + <input type="hidden" name="course_id" value="<%=request.getParameter("course_id")%>"> + <input type="hidden" name="sequence_id" id="sequence_id" value="0"> + + + <bbUI:step title="Select an existing sequence from the LAMS workspace."> + <bbUI:dataElement> + <script language="JavaScript" type="text/javascript" src="../lib/tigra/tree.js"></script> + <script language="JavaScript" type="text/javascript" src="../lib/tigra/tree_tpl.js"></script> + <script language="JavaScript" type="text/javascript"> + <!-- + var TREE_ITEMS = <%=learningDesigns%>; + var tree = new tree(TREE_ITEMS, TREE_TPL); + + //--> + </script> + </bbUI:dataElement> + </bbUI:step> + <bbUI:step title="Open author, refresh or start the chosen lesson."> + <br> + <bbUI:dataElement> + <input type="button" name="author" onClick="openAuthor();" value="Open Author"> + <input type="button" name="action" onClick="refreshSeqList();" value="Refresh Workspace"> + <input id="nextButton" type="submit" name="nextButton" onClick="openNext();" value="Next" disabled="true"> + </bbUI:dataElement> + </bbUI:step> + +</form> + + +<script language="JavaScript" type="text/javascript"> +<!-- + var authorWin = null; + + function openAuthor() + { + authorUrl = '<%=authorUrl%>'; + if(authorWin && authorWin.open && !authorWin.closed){ + + authorWin.focus(); + } + else{ + authorWin = window.open(authorUrl,'aWindow','width=800,height=600,resizable'); + authorWin.focus(); + } + } + + function refreshSeqList() + { + document.getElementById("sequence_id").value="0"; + document.location.reload(); + } + + function openNext() + { + } + + function selectSequence(id) + { + document.getElementById("nextButton").disabled = false; + document.getElementById("sequence_id").value=id; + } +//--> +</script> + + + +</bbUI:docTemplate> +</bbData:context> \ No newline at end of file Index: lams_bb_integration/web/modules/create_proc.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/create_proc.jsp (revision 0) +++ lams_bb_integration/web/modules/create_proc.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,161 @@ +<%@ page import="java.util.Calendar"%> +<%@ page import="java.text.SimpleDateFormat"%> +<%@ page import="blackboard.base.FormattedText"%> +<%@ page import="blackboard.data.course.Course"%> +<%@ page import="blackboard.data.content.Content"%> +<%@ page import="blackboard.data.content.ContentFolder"%> +<%@ page import="blackboard.data.content.CourseDocument"%> + +<%@ page import="blackboard.persist.Id"%> +<%@ page import="blackboard.persist.BbPersistenceManager"%> +<%@ page import="blackboard.persist.content.ContentDbPersister"%> +<%@ page import="blackboard.persist.content.ContentDbLoader"%> +<%@ page import="blackboard.platform.session.BbSessionManagerService"%> +<%@ page import="blackboard.platform.session.BbSession"%> +<%@ page import="blackboard.platform.*"%> +<%@ page import="blackboard.platform.plugin.PlugInUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsServiceUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsPluginUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.Constants"%> + + +<%@ page errorPage="/error.jsp"%><%@ page import="org.lamsfoundation.ld.integration.Constants" %> + +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<bbData:context id="ctx"> + +<jsp:useBean id="myContent" scope="page" class="blackboard.data.content.CourseDocument"/> +<jsp:setProperty name="myContent" property="title"/> +<jsp:setProperty name="myContent" property="isAvailable"/> +<jsp:setProperty name="myContent" property="isTracked"/> + +<% + + // SECURITY! + //AccessManagerService accessManager = (AccessManagerService) BbServiceManager.lookupService(AccessManagerService.class); + if (!PlugInUtil.authorizeForCourseControlPanel(request,response)){ + //accessManager.sendAccessDeniedRedirect(request,response); + //TODO: redirect user to login page, since sendAccessDeniedRedirect is deprecated another way is needed + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + //check parameters + String p_courseId = request.getParameter("course_id"); + String p_contentId = request.getParameter("content_id"); + String p_learningDesignId = request.getParameter("sequence"); + String p_descText = request.getParameter("descriptiontext"); + String p_descType = request.getParameter("descriptiontype"); + String p_title = request.getParameter("title"); + if(p_courseId==null || p_contentId==null || p_learningDesignId==null || p_title==null || p_descText==null || p_descType==null){ + throw new ServletException("requested parameters missing"); + } + + // retrieve the Db persistence manager from the persistence service + BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager(); + ContentDbPersister contentPersister = (ContentDbPersister) bbPm.getPersister( ContentDbPersister.TYPE ); + + // internal IDs for the course and parent content item + Id courseId = bbPm.generateId(Course.DATA_TYPE,request.getParameter("course_id")); + Id folderId = bbPm.generateId(CourseDocument.DATA_TYPE,request.getParameter("content_id")); + + // learning design id + long ldId = Long.parseLong(p_learningDesignId); + + //load parent content item + ContentDbLoader courseDocumentLoader = (ContentDbLoader) bbPm.getLoader( ContentDbLoader.TYPE ); + ContentFolder courseDocParent = (ContentFolder)courseDocumentLoader.loadById( folderId ); + + //get the session object to obtain the user and course object + BbSessionManagerService sessionService = BbServiceManager.getSessionManagerService(); + BbSession bbSession = sessionService.getSession( request ); + + //get username + String username = bbSession.getUserName(); + + //set LAMS content data + myContent.setTitle(p_title); + myContent.setIsAvailable(request.getParameter("isAvailable").equals("true")?true:false); + myContent.setIsTracked(request.getParameter("isTracked").equals("true")?true:false); + + //get descriptions entered + FormattedText.Type descType = FormattedText.Type.DEFAULT; //type of description (S|H|P) + switch(p_descType.charAt(0)){ + case 'H': + descType = FormattedText.Type.HTML; break; + case 'S': + descType = FormattedText.Type.SMART_TEXT; break; + case 'P': + descType = FormattedText.Type.PLAIN_TEXT; break; + } + if(!myContent.getIsAvailable()){ + p_descText = "<i>Item is not available.</i><br>" + p_descText; + } + FormattedText description = new FormattedText(p_descText,descType); + + + //set core course data + myContent.setContentHandler( LamsPluginUtil.CONTENT_HANDLE ); + myContent.setCourseId( courseId ); + myContent.setParentId( folderId ); + + //set LAMS content data + myContent.setRenderType(Content.RenderType.URL); + myContent.setBody(description); + + String learningSessionId = null; + + //tell lams to create the learning session using webservices + try{ + long lsId = LamsServiceUtil.createLearningSession(username, ldId, courseId.toExternalString(), p_title, p_descText); + learningSessionId = Long.toString(lsId); + } catch (Exception e){ + throw new ServletException(e.getMessage(), e); + } + + + String contentUrl = request.getContextPath() + Constants.SERVLET_ACTION_REQUEST + '?' + + Constants.PARAM_METHOD + '=' + Constants.METHOD_LEARNER + '&' + + Constants.PARAM_LEARNING_SESSION_ID + '=' + learningSessionId + '&' + + Constants.PARAM_COURSE_ID + '=' + courseId.toExternalString(); + myContent.setUrl(contentUrl); + + + + + //Parse start/end Date from the <bbUI:dateAvailability> + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Calendar cstart = Calendar.getInstance(); + Calendar cend = Calendar.getInstance(); + cstart.setTime(formatter.parse(request.getParameter("startDate"))); + cend.setTime(formatter.parse(request.getParameter("endDate"))); + + // Set Availability Dates + myContent.setStartDate(cstart); + if (request.getParameter("restrict_end") != null){ + if (request.getParameter("restrict_end").equals("1")){ + myContent.setEndDate(cend); + } + } + + ContentDbPersister persister= (ContentDbPersister) bbPm.getPersister( ContentDbPersister.TYPE ); + persister.persist( myContent ); + + String strReturnUrl = PlugInUtil.getEditableContentReturnURL(myContent.getParentId()); +%> +<bbUI:docTemplate title="Learning Activity Management System"> +<bbUI:coursePage courseId="<%=PlugInUtil.getCourseId(request)%>"> + +<bbUI:breadcrumbBar environment="ctrl_panel" handle="control_panel" isContent="true" > + <bbUI:breadcrumb>LAMS</bbUI:breadcrumb> +</bbUI:breadcrumbBar> + +<bbUI:receipt type="SUCCESS" iconUrl="/images/ci/icons/tools_u.gif" title="Content Added" recallUrl="<%=strReturnUrl%>">Content successfully added.</bbUI:receipt><br> +<br> +<br> + + +</bbUI:coursePage> +</bbUI:docTemplate> +</bbData:context> Index: lams_bb_integration/web/modules/js/DynamicOptionList.js =================================================================== diff -u --- lams_bb_integration/web/modules/js/DynamicOptionList.js (revision 0) +++ lams_bb_integration/web/modules/js/DynamicOptionList.js (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,584 @@ +// =================================================================== +// Author: Matt Kruse <matt@mattkruse.com> +// WWW: http://www.mattkruse.com/ +// +// NOTICE: You may use this code for any purpose, commercial or +// private, without any further permission from the author. You may +// remove this notice from your final code if you wish, however it is +// appreciated by the author if at least my web site address is kept. +// +// You may *NOT* re-distribute this code in any way except through its +// use. That means, you can include it in your product, or your web +// site, or any other form where the code is actually being used. You +// may not put the plain javascript up on your site for download or +// include it in your javascript libraries for download. +// If you wish to share this code with others, please just point them +// to the URL instead. +// Please DO NOT link directly to my .js files from your site. Copy +// the files to your server and use them there. Thank you. +// =================================================================== + +// HISTORY +// ------------------------------------------------------------------ +// Feb 15, 2005: Documentation Fix +// March 31, 2004: First release +/* + +DESCRIPTION: This library allows you to easily create select boxes whose +contents depend on the value in a parent select box. It supports default +options, preselected options, single or multiple-select lists, multiple +form fields referencing the same list structure, form resetting, and most +importantly, it's backwards-compatible way back to Netscape 4! + +COMPATABILITY: Netscape 4+, IE, Opera >5 (O5 didn't support new Option()), +and should work on all other newer browsers. + +USAGE: + + // Create a new object, passing in the fields that make up the dynamic set + // of lists. +var dol = new DynamicOptionList("Field1","Child1","Child2"); + + // Or, you can create it empty, and pass in sets of select objects later +var dol = new DynamicOptionList(); +dol.addDependentFields("Field1","Child1","Child2"); + + // Once you have the list object defined, you can additional sets of dependent + // fields, too. These sets will act as separate groups of related fields, but + // will all use the same options and data. +dol.addDependentOptions("Field1","Child2-1","Child2-2"); + + // By default, the script will automatically find the form where your select + // objects exist. But you can explicitly set it if you wish, either by form + // name or index. +dol.setFormName("MyForm"); +dol.setFormIndex(1); + + // Now define the options that will exist in sub-lists. This is done in a + // very logical way - you say for an option in the parent, populate the child + // with specific options. When selecting which parent option you're dealing + // with, you can either select by its value or its display text. This command + // says, for an option in the parent list that has value="Value1", if it is + // selected then populate the child list with the given sub-options. +dol.forValue("Value1").addOptions("Suboption1","Suboption2","Suboption3"); + + // And you can also say, for an option in the parent list that has display + // text of "Text1", if it is selected then populate the child list with the + // given sub-options. +dol.forText("Text1").addOptions("Suboption1","Suboption2","Suboption3"); + + // For multi-level lists, you just continue the chain... + // This says, if an option with value "Value1" is selected in the first list, + // then an option with values "Value2" is selected in the second list, populate + // the third list with these options. +dol.forValue("Value1").forValue("Value2").addOptions("1","2","3"); + + // If the options you want to add should have different values and dislplay + // text, you can do that +dol.forValue("Value1").addOptionsTextValue("Text2","Value2"); + + // When an option is selected from the first list, and the options in the + // second list are populated, you may want to have one of the options in the + // child list be selected by default. +dol.forValue("Value1").setDefaultOptions("MyValue"); + + // When the page first loads, you may set the values of the dependent select + // lists to be selected by default. For example, when a user is editing an + // existing record where they've already selected from the parent/child + // relationships. This is different from the default option in that this + // value is only selected when the page LOADS. If the user changes selections, + // this will be lost. +dol.forField("Field1").setValues("MyPreselectedValue"); + + // By default, if there are is no option which should be selected in the child + // list, the code will automatically select the first option in the list. If + // you want it to instead set selectedIndex = -1 (nothing selected - works in + // most browsers but not all) than you can tell it to do that instead +dol.selectFirstOption = false; + +// MODIFYING THE HTML +// If you are supporting Netscape 4.x browsers, you will need to insert a call to +// the library to populate options. This is because Netscape4 will not expand the +// size of the select box as new options are added, so you have to "pad" the list +// with blank options in order for it to work right. +// This is the ONLY change you should need to make to your HTML. To do this, just +// add a javascript block between your <select> </select> tags like this: + +<select name="list1"><script>dol.printOptions("list1")</script></select> + +// You only need to pass it the name of the select options that it should print +// options for. + + +NOTES: + - There seems to be an issue with Netscape6, if you hit Reload on the page. It + doesn't happen every time, and I can't figure out why it happens at all. + + - If your select objects have onChange handlers in them, you'll need to manually + add a call to the DynamicOptionList code to trigger the population of the child + list. For example, + + <select onChange="yourfunction(); dol.change(this)"> + +*/ +// Global objects to keep track of DynamicOptionList objects created on the page +var dynamicOptionListCount=0; +var dynamicOptionListObjects = new Array(); + +// Init call to setup lists after page load. One call to this function sets up all lists. +function initDynamicOptionLists() { + // init each DynamicOptionList object + for (var i=0; i<dynamicOptionListObjects.length; i++) { + var dol = dynamicOptionListObjects[i]; + + // Find the form associated with this list + if (dol.formName!=null) { + dol.form = document.forms[dol.formName]; + } + else if (dol.formIndex!=null) { + dol.form = document.forms[dol.formIndex]; + } + else { + // Form wasn't set manually, so go find it! + // Search for the first form element name in the lists + var name = dol.fieldNames[0][0]; + for (var f=0; f<document.forms.length; f++) { + if (typeof(document.forms[f][name])!="undefined") { + dol.form = document.forms[f]; + break; + } + } + if (dol.form==null) { + alert("ERROR: Couldn't find form element "+name+" in any form on the page! Init aborted"); return; + } + } + + // Form is found, now set the onchange attributes of each dependent select box + for (var j=0; j<dol.fieldNames.length; j++) { + // For each set of field names... + for (var k=0; k<dol.fieldNames[j].length-1; k++) { + // For each field in the set... + var selObj = dol.form[dol.fieldNames[j][k]]; + if (typeof(selObj)=="undefined") { alert("Select box named "+dol.fieldNames[j][k]+" could not be found in the form. Init aborted"); return; } + // Map the HTML options in the first select into the options we created + if (k==0) { + if (selObj.options!=null) { + for (l=0; l<selObj.options.length; l++) { + var sopt = selObj.options[l]; + var m = dol.findMatchingOptionInArray(dol.options,sopt.text,sopt.value,false); + if (m!=null) { + var reselectForNN6 = sopt.selected; + var m2 = new Option(sopt.text, sopt.value, sopt.defaultSelected, sopt.selected); + m2.selected = sopt.selected; // For some reason I need to do this to make NN4 happy + m2.defaultSelected = sopt.defaultSelected; + m2.DOLOption = m; + selObj.options[l] = m2; + selObj.options[l].selected = reselectForNN6; // Reselect this option for NN6 to be happy. Yuck. + } + } + } + } + if (selObj.onchange==null) { + // We only modify the onChange attribute if it's empty! Otherwise do it yourself in your source! + selObj.onchange = new Function("dynamicOptionListObjects["+dol.index+"].change(this)"); + } + } + } + } + // Set the preselectd options on page load + resetDynamicOptionLists(); +} + +// This function populates lists with the preselected values. +// It's pulled out into a separate function so it can be hooked into a 'reset' button on a form +// Optionally passed a form object which should be the only form reset +function resetDynamicOptionLists(theform) { + // reset each DynamicOptionList object + for (var i=0; i<dynamicOptionListObjects.length; i++) { + var dol = dynamicOptionListObjects[i]; + if (typeof(theform)=="undefined" || theform==null || theform==dol.form) { + for (var j=0; j<dol.fieldNames.length; j++) { + dol.change(dol.form[dol.fieldNames[j][0]],true); // Second argument says to use preselected values rather than default values + } + } + } +} + +// An object to represent an Option() but just for data-holding +function DOLOption(text,value,defaultSelected,selected) { + this.text = text; + this.value = value; + this.defaultSelected = defaultSelected; + this.selected = selected; + this.options = new Array(); // To hold sub-options + return this; +} + +// DynamicOptionList CONSTRUCTOR +function DynamicOptionList() { + this.form = null;// The form this list belongs to + this.options = new Array();// Holds the options of dependent lists + this.longestString = new Array();// Longest string that is currently a potential option (for Netscape) + this.numberOfOptions = new Array();// The total number of options that might be displayed, to build dummy options (for Netscape) + this.currentNode = null;// The current node that has been selected with forValue() or forText() + this.currentField = null;// The current field that is selected to be used for setValue() + this.currentNodeDepth = 0;// How far down the tree the currentNode is + this.fieldNames = new Array();// Lists of dependent fields which use this object + this.formIndex = null;// The index of the form to associate with this list + this.formName = null;// The name of the form to associate with this list + this.fieldListIndexes = new Object();// Hold the field lists index where fields exist + this.fieldIndexes = new Object();// Hold the index within the list where fields exist + this.selectFirstOption = true;// Whether or not to select the first option by default if no options are default or preselected, otherwise set the selectedIndex = -1 + this.numberOfOptions = new Array();// Store the max number of options for a given option list + this.longestString = new Array();// Store the longest possible string + this.values = new Object(); // Will hold the preselected values for fields, by field name + + // Method mappings + this.forValue = DOL_forValue; + this.forText = DOL_forText; + this.forField = DOL_forField; + this.forX = DOL_forX; + this.addOptions = DOL_addOptions; + this.addOptionsTextValue = DOL_addOptionsTextValue; + this.setDefaultOptions = DOL_setDefaultOptions; + this.setValues = DOL_setValues; + this.setValue = DOL_setValues; + this.setFormIndex = DOL_setFormIndex; + this.setFormName = DOL_setFormName; + this.printOptions = DOL_printOptions; + this.addDependentFields = DOL_addDependentFields; + this.change = DOL_change; + this.child = DOL_child; + this.selectChildOptions = DOL_selectChildOptions; + this.populateChild = DOL_populateChild; + this.change = DOL_change; + this.addNewOptionToList = DOL_addNewOptionToList; + this.findMatchingOptionInArray = DOL_findMatchingOptionInArray; + + // Optionally pass in the dependent field names + if (arguments.length > 0) { + // Process arguments and add dependency groups + for (var i=0; i<arguments.length; i++) { + this.fieldListIndexes[arguments[i].toString()] = this.fieldNames.length; + this.fieldIndexes[arguments[i].toString()] = i; + } + this.fieldNames[this.fieldNames.length] = arguments; + } + + // Add this object to the global array of dynamicoptionlist objects + this.index = window.dynamicOptionListCount++; + window["dynamicOptionListObjects"][this.index] = this; +} + +// Given an array of Option objects, search for an existing option that matches value, text, or both +function DOL_findMatchingOptionInArray(a,text,value,exactMatchRequired) { + if (a==null || typeof(a)=="undefined") { return null; } + var value_match = null; // Whether or not a value has been matched + var text_match = null; // Whether or not a text has been matched + for (var i=0; i<a.length; i++) { + var opt = a[i]; + // If both value and text match, return it right away + if (opt.value==value && opt.text==text) { return opt; } + if (!exactMatchRequired) { + // If value matches, store it until we complete scanning the list + if (value_match==null && value!=null && opt.value==value) { + value_match = opt; + } + // If text matches, store it for later + if (text_match==null && text!=null && opt.text==text) { + text_match = opt; + } + } + } + return (value_match!=null)?value_match:text_match; +} + +// Util function used by forValue and forText +function DOL_forX(s,type) { + if (this.currentNode==null) { this.currentNodeDepth=0; } + var useNode = (this.currentNode==null)?this:this.currentNode; + var o = this.findMatchingOptionInArray(useNode["options"],(type=="text")?s:null,(type=="value")?s:null,false); + if (o==null) { + o = new DOLOption(null,null,false,false); + o[type] = s; + useNode.options[useNode.options.length] = o; + } + this.currentNode = o; + this.currentNodeDepth++; + return this; +} + +// Set the portion of the list structure that is to be used by a later operation like addOptions +function DOL_forValue(s) { return this.forX(s,"value"); } + +// Set the portion of the list structure that is to be used by a later operation like addOptions +function DOL_forText(s) { return this.forX(s,"text"); } + +// Set the field to be used for setValue() calls +function DOL_forField(f) { this.currentField = f; return this; } + +// Create and add an option to a list, avoiding duplicates +function DOL_addNewOptionToList(a, text, value, defaultSelected) { + var o = new DOLOption(text,value,defaultSelected,false); + // Add the option to the array + if (a==null) { a = new Array(); } + for (var i=0; i<a.length; i++) { + if (a[i].text==o.text && a[i].value==o.value) { + if (o.selected) { + a[i].selected=true; + } + if (o.defaultSelected) { + a[i].defaultSelected = true; + } + return a; + } + } + a[a.length] = o; +} + +// Add sub-options to the currently-selected node, with the same text and value for each option +function DOL_addOptions() { + if (this.currentNode==null) { this.currentNode = this; } + if (this.currentNode["options"] == null) { this.currentNode["options"] = new Array(); } + for (var i=0; i<arguments.length; i++) { + var text = arguments[i]; + this.addNewOptionToList(this.currentNode.options,text,text,false); + if (typeof(this.numberOfOptions[this.currentNodeDepth])=="undefined") { + this.numberOfOptions[this.currentNodeDepth]=0; + } + if (this.currentNode.options.length > this.numberOfOptions[this.currentNodeDepth]) { + this.numberOfOptions[this.currentNodeDepth] = this.currentNode.options.length; + } + if (typeof(this.longestString[this.currentNodeDepth])=="undefined" || (text.length > this.longestString[this.currentNodeDepth].length)) { + this.longestString[this.currentNodeDepth] = text; + } + } + this.currentNode = null; + this.currentNodeDepth = 0; +} + +// Add sub-options to the currently-selected node, specifying separate text and values for each option +function DOL_addOptionsTextValue() { + if (this.currentNode==null) { this.currentNode = this; } + if (this.currentNode["options"] == null) { this.currentNode["options"] = new Array(); } + for (var i=0; i<arguments.length; i++) { + var text = arguments[i++]; + var value = arguments[i]; + this.addNewOptionToList(this.currentNode.options,text,value,false); + if (typeof(this.numberOfOptions[this.currentNodeDepth])=="undefined") { + this.numberOfOptions[this.currentNodeDepth]=0; + } + if (this.currentNode.options.length > this.numberOfOptions[this.currentNodeDepth]) { + this.numberOfOptions[this.currentNodeDepth] = this.currentNode.options.length; + } + if (typeof(this.longestString[this.currentNodeDepth])=="undefined" || (text.length > this.longestString[this.currentNodeDepth].length)) { + this.longestString[this.currentNodeDepth] = text; + } + } + this.currentNode = null; + this.currentNodeDepth = 0; +} + +// Find the first dependent list of a select box +// If it's the last list in a chain, return null because there are no children +function DOL_child(obj) { + var listIndex = this.fieldListIndexes[obj.name]; + var index = this.fieldIndexes[obj.name]; + if (index < (this.fieldNames[listIndex].length-1)) { + return this.form[this.fieldNames[listIndex][index+1]]; + } + return null; +} + +// Set the options which should be selected by default for a certain value in the parent +function DOL_setDefaultOptions() { + if (this.currentNode==null) { this.currentNode = this; } + for (var i=0; i<arguments.length; i++) { + var o = this.findMatchingOptionInArray(this.currentNode.options,null,arguments[i],false); + if (o!=null) { + o.defaultSelected = true; + } + } + this.currentNode = null; +} + +// Set the options which should be selected when the page loads. This is different than the default value and ONLY applies when the page LOADS +function DOL_setValues() { + if (this.currentField==null) { + alert("Can't call setValues() without using forField() first!"); + return; + } + if (typeof(this.values[this.currentField])=="undefined") { + this.values[this.currentField] = new Object(); + } + for (var i=0; i<arguments.length; i++) { + this.values[this.currentField][arguments[i]] = true; + } + this.currentField = null; +} + +// Manually set the form for the object using an index +function DOL_setFormIndex(i) { + this.formIndex = i; +} + +// Manually set the form for the object using a form name +function DOL_setFormName(n) { + this.formName = n; +} + +// Print blank <option> objects for Netscape4, since it refuses to grow or shrink select boxes for new options +function DOL_printOptions(name) { + // Only need to write out "dummy" options for Netscape4 + if ((navigator.appName == 'Netscape') && (parseInt(navigator.appVersion) <= 4)){ + var index = this.fieldIndexes[name]; + var ret = ""; + if (typeof(this.numberOfOptions[index])!="undefined") { + for (var i=0; i<this.numberOfOptions[index]; i++) { + ret += "<OPTION>"; + } + } + ret += "<OPTION>"; + if (typeof(this.longestString[index])!="undefined") { + for (var i=0; i<this.longestString[index].length; i++) { + ret += "_"; + } + } + document.writeln(ret); + } +} + +// Add a list of field names which use this option-mapping object. +// A single mapping object may be used by multiple sets of fields +function DOL_addDependentFields() { + for (var i=0; i<arguments.length; i++) { + this.fieldListIndexes[arguments[i].toString()] = this.fieldNames.length; + this.fieldIndexes[arguments[i].toString()] = i; + } + this.fieldNames[this.fieldNames.length] = arguments; +} + +// Called when a parent select box is changed. It populates its direct child, then calls change on the child object to continue the population. +function DOL_change(obj, usePreselected) { + if (usePreselected==null || typeof(usePreselected)=="undefined") { usePreselected = false; } + var changedListIndex = this.fieldListIndexes[obj.name]; + var changedIndex = this.fieldIndexes[obj.name]; + var child = this.child(obj); + if (child == null) { return; } // No child, no need to continue + if (obj.type == "select-one") { + // Treat single-select differently so we don't have to scan the entire select list, which could potentially speed things up + if (child.options!=null) { + child.options.length=0; // Erase all the options from the child so we can re-populate + } + if (obj.options!=null && obj.options.length>0 && obj.selectedIndex>=0) { + var o = obj.options[obj.selectedIndex]; + this.populateChild(o.DOLOption,child,usePreselected); + this.selectChildOptions(child,usePreselected); + } + } + else if (obj.type == "select-multiple") { + // For each selected value in the parent, find the options to fill in for this list + // Loop through the child list and keep track of options that are currently selected + var currentlySelectedOptions = new Array(); + if (!usePreselected) { + for (var i=0; i<child.options.length; i++) { + var co = child.options[i]; + if (co.selected) { + this.addNewOptionToList(currentlySelectedOptions, co.text, co.value, co.defaultSelected); + } + } + } + child.options.length=0; + if (obj.options!=null) { + var obj_o = obj.options; + // For each selected option in the parent... + for (var i=0; i<obj_o.length; i++) { + if (obj_o[i].selected) { + // if option is selected, add its children to the list + this.populateChild(obj_o[i].DOLOption,child,usePreselected); + } + } + // Now go through and re-select any options which were selected before + var atLeastOneSelected = false; + if (!usePreselected) { + for (var i=0; i<child.options.length; i++) { + var m = this.findMatchingOptionInArray(currentlySelectedOptions,child.options[i].text,child.options[i].value,true); + if (m!=null) { + child.options[i].selected = true; + atLeastOneSelected = true; + } + } + } + if (!atLeastOneSelected) { + this.selectChildOptions(child,usePreselected); + } + } + } + // Change all the way down the chain + this.change(child,usePreselected); +} +function DOL_populateChild(dolOption,childSelectObj,usePreselected) { + // If this opton has sub-options, populate the child list with them + if (dolOption!=null && dolOption.options!=null) { + for (var j=0; j<dolOption.options.length; j++) { + var srcOpt = dolOption.options[j]; + if (childSelectObj.options==null) { childSelectObj.options = new Array(); } + // Put option into select list + var duplicate = false; + var preSelectedExists = false; + for (var k=0; k<childSelectObj.options.length; k++) { + var csi = childSelectObj.options[k]; + if (csi.text==srcOpt.text && csi.value==srcOpt.value) { + duplicate = true; + break; + } + } + if (!duplicate) { + var newopt = new Option(srcOpt.text, srcOpt.value, false, false); + newopt.selected = false; // Again, we have to do these two statements for NN4 to work + newopt.defaultSelected = false; + newopt.DOLOption = srcOpt; + childSelectObj.options[childSelectObj.options.length] = newopt; + } + } + } +} + +// Once a child select is populated, go back over it to select options which should be selected +function DOL_selectChildOptions(obj,usePreselected) { + // Look to see if any options are preselected=true. If so, then set then selected if usePreselected=true, otherwise set defaults + var values = this.values[obj.name]; + var preselectedExists = false; + if (usePreselected && values!=null && typeof(values)!="undefined") { + for (var i=0; i<obj.options.length; i++) { + var v = obj.options[i].value; + if (v!=null && values[v]!=null && typeof(values[v])!="undefined") { + preselectedExists = true; + break; + } + } + } + // Go back over all the options to do the selection + var atLeastOneSelected = false; + for (var i=0; i<obj.options.length; i++) { + var o = obj.options[i]; + if (preselectedExists && o.value!=null && values[o.value]!=null && typeof(values[o.value])!="undefined") { + o.selected = true; + atLeastOneSelected = true; + } + else if (!preselectedExists && o.DOLOption!=null && o.DOLOption.defaultSelected) { + o.selected = true; + atLeastOneSelected = true; + } + else { + o.selected = false; + } + } + // If nothing else was selected, select the first one by default + if (this.selectFirstOption && !atLeastOneSelected && obj.options.length>0) { + obj.options[0].selected = true; + } + else if (!atLeastOneSelected && obj.type=="select-one") { + obj.selectedIndex = -1; + } +} Index: lams_bb_integration/web/modules/js/seqList.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/js/seqList.jsp (revision 0) +++ lams_bb_integration/web/modules/js/seqList.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,53 @@ +<%@ page import="blackboard.platform.BbServiceManager"%> +<%@ page import="blackboard.platform.session.BbSession"%> +<%@ page import="blackboard.platform.plugin.*"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsServiceUtil"%> +<%@ page import="lamsws.SimpleLearningDesignVO"%> +<%@ page errorPage="/error.jsp"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<bbData:context id="ctx"> +<% + /*** + * this JSP page simply generate a list of all Learning Design from the LearningDesign web service + **/ + + // SECURITY! + //AccessManagerService accessManager = (AccessManagerService) BbServiceManager.lookupService(AccessManagerService.class); + if (!PlugInUtil.authorizeForCourseControlPanel(request,response)){ + //accessManager.sendAccessDeniedRedirect(request,response); + //TODO: redirect user to login page, since sendAccessDeniedRedirect is deprecated another way is needed + response.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + //use BbSession to obtain username + BbSession bbSession = BbServiceManager.getSessionManagerService().getSession( request ); + String username = bbSession.getUserName(); + + //get All Learning Designs from WebService object + SimpleLearningDesignVO[] learningDesignArray = LamsServiceUtil.getAllLearningDesign(username); + + response.setContentType("text/xml"); + + //open designs XML tag + %><designs><% + + /*this javascript uses the learningDesignArray to get a list of workspace and sequences*/ + for(int i=0; i<learningDesignArray.length; i++){ + String workspace = learningDesignArray[i].getWorkspace(); + String sequence = learningDesignArray[i].getTitle(); + String sid = learningDesignArray[i].getSid().toString(); + %> + <design> + <id><%=sid%></id> + <workspace><%=workspace%></workspace> + <sequence><%=sequence%></sequence> + </design><% + + } + + //close designs XML tag + %></designs><% +%> +</bbData:context> \ No newline at end of file Index: lams_bb_integration/web/modules/modify.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/modify.jsp (revision 0) +++ lams_bb_integration/web/modules/modify.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,91 @@ +<%@ page import="java.util.*, + java.util.Date, + java.text.SimpleDateFormat, + blackboard.data.*, + blackboard.persist.*, + blackboard.data.course.*, + blackboard.data.user.*, + blackboard.persist.course.*, + blackboard.data.content.*, + blackboard.persist.content.*, + blackboard.db.*, + blackboard.base.*, + blackboard.platform.*, + blackboard.platform.plugin.*" + errorPage="/error.jsp" +%> +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<bbData:context id="ctx"> + +<% + String NOT_AVAILABLE = "<i>Item is not available.</i><br>"; + + //check permission + if (!PlugInUtil.authorizeForCourseControlPanel(request, response)) + return; + + BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager(); + Container bbContainer = bbPm.getContainer(); + + Id contentId = new PkId( bbContainer, CourseDocument.COURSE_DOCUMENT_DATA_TYPE, request.getParameter("content_id") ); + + ContentDbLoader courseDocumentLoader = (ContentDbLoader) bbPm.getLoader( ContentDbLoader.TYPE ); + Content courseDoc = (Content)courseDocumentLoader.loadById( contentId ); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date startDate = null; + Date endDate = null; + + if(courseDoc.getStartDate() != null) + startDate = courseDoc.getStartDate().getTime(); + if(courseDoc.getEndDate() != null) + endDate = courseDoc.getStartDate().getTime(); + + FormattedText desc = courseDoc.getBody(); + String description = desc.getText().replaceFirst(NOT_AVAILABLE, ""); //remove the NOT_AVAILABLE substring +%> + +<bbUI:docTemplate title="Modify LAMS"> +<bbUI:coursePage courseId="<%=PlugInUtil.getCourseId(request)%>"> + +<bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel" isContent="true"> + <bbUI:breadcrumb>Modify HTML Block</bbUI:breadcrumb> +</bbUI:breadcrumbBar> +<bbUI:titleBar iconUrl="/images/ci/icons/tools_u.gif">Modify LAMS</bbUI:titleBar> +<form name="lams_form" action="modify_proc.jsp" method="post"> + <input type=hidden name=content_id value="<%=request.getParameter("content_id")%>"> + <input type=hidden name=course_id value="<%=request.getParameter("course_id")%>"> + + <bbUI:step title="Select an existing sequence or create a new sequence"> + <bbUI:dataElement label="Name"> + <input type="text" name="title" value="<%=courseDoc.getTitle()%>"> + </bbUI:dataElement> + + <bbUI:dataElement label="Description"> + <bbUI:textbox name="description" rows="12" cols="55" text="<%=description%>" format="<%=desc.getType().toFieldName().substring(0,1)%>"></bbUI:textbox> + </bbUI:dataElement> + </bbUI:step> + + <bbUI:step title="Options"> + <bbUI:dataElement label="Do you want to make LAMS visible?"> + <input type="Radio" name="isAvailable" value="true" <%=(courseDoc.getIsAvailable())?"checked":""%>>Yes + <input type="Radio" name="isAvailable" value="false" <%=(courseDoc.getIsAvailable())?"":"checked"%>>No + </bbUI:dataElement> + <bbUI:dataElement label="Track number of views"> + <input type="radio" name="isTracked" value="true" <%=(courseDoc.getIsTracked())?"checked":""%>>Yes + <input type="radio" name="isTracked" value="false" <%=(courseDoc.getIsTracked())?"":"checked"%>>No + </bbUI:dataElement> + <bbUI:dataElement label="Choose date restrictions"> + <bbUI:dateAvailability formName="lams_form" + startDateField="startDate" endDateField="endDate" + startDate="<%=startDate%>" endDate="<%=endDate%>"/> + </bbUI:dataElement> + </bbUI:step> + + <bbUI:stepSubmit title="Submit"/> +</form> +</bbUI:coursePage> +</bbUI:docTemplate> +</bbData:context> + Index: lams_bb_integration/web/modules/modify_proc.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/modify_proc.jsp (revision 0) +++ lams_bb_integration/web/modules/modify_proc.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,94 @@ +<%@ page import="java.util.*, + java.text.*, + java.io.*, + blackboard.data.*, + blackboard.persist.*, + blackboard.data.course.*, + blackboard.data.user.*, + blackboard.persist.course.*, + blackboard.data.content.*, + blackboard.persist.content.*, + blackboard.base.*, + blackboard.platform.*, + blackboard.platform.persistence.*, + blackboard.platform.plugin.*" + errorPage="/error.jsp" +%> +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> +<bbData:context id="ctx"> + +<% + //check permission + if (!PlugInUtil.authorizeForCourseControlPanel(request, response)) + return; + + BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager(); + Container bbContainer = bbPm.getContainer(); + + Id contentId = new PkId( bbContainer, CourseDocument.COURSE_DOCUMENT_DATA_TYPE, request.getParameter("content_id") ); + + ContentDbLoader courseDocumentLoader = (ContentDbLoader) bbPm.getLoader( ContentDbLoader.TYPE ); + Content myContent = (Content)courseDocumentLoader.loadById( contentId ); + + //set LAMS content data + myContent.setTitle(request.getParameter("title")); + myContent.setIsAvailable(request.getParameter("isAvailable").equals("true")?true:false); + myContent.setIsTracked(request.getParameter("isTracked").equals("true")?true:false); + + + //get descriptions entered + String descText = request.getParameter("descriptiontext"); + FormattedText.Type descType = FormattedText.Type.DEFAULT; //type of description (S|H|P) + switch(request.getParameter("descriptiontype").charAt(0)){ + case 'H': + descType = FormattedText.Type.HTML; break; + case 'S': + descType = FormattedText.Type.SMART_TEXT; break; + case 'P': + descType = FormattedText.Type.PLAIN_TEXT; break; + } + if(!myContent.getIsAvailable()){ + descText = "<i>Item is not available.</i><br>" + descText; + } + FormattedText description = new FormattedText(descText,descType); + + myContent.setBody(description); + + //Parse start/end Date from the <bbUI:dateAvailability> + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Calendar cstart = Calendar.getInstance(); + Calendar cend = Calendar.getInstance(); + cstart.setTime(formatter.parse(request.getParameter("startDate"))); + cend.setTime(formatter.parse(request.getParameter("endDate"))); + + // Set Availability Dates + myContent.setStartDate(cstart); + if (request.getParameter("restrict_end") != null){ + if (request.getParameter("restrict_end").equals("1")){ + myContent.setEndDate(cend); + } + } + + ContentDbPersister persister= (ContentDbPersister) bbPm.getPersister( ContentDbPersister.TYPE ); + persister.persist( myContent ); + + String strReturnUrl = PlugInUtil.getEditableContentReturnURL(myContent.getParentId()); +%> + + + <bbUI:docTemplate title="Modify LAMS"> + <bbUI:coursePage courseId="<%=PlugInUtil.getCourseId(request)%>"> + + <bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel" isContent="true" > + <bbUI:breadcrumb>Modify LAMS</bbUI:breadcrumb> + </bbUI:breadcrumbBar> + <bbUI:receipt type="SUCCESS" + iconUrl="/images/ci/icons/tools_u.gif" + title="Content Modified" + recallUrl="<%=strReturnUrl%>"> + Content successfully modified.<br> + </bbUI:receipt> + </bbUI:coursePage> + </bbUI:docTemplate> +</bbData:context> Index: lams_bb_integration/web/modules/start_lesson.jsp =================================================================== diff -u --- lams_bb_integration/web/modules/start_lesson.jsp (revision 0) +++ lams_bb_integration/web/modules/start_lesson.jsp (revision a225f60e82f4197c7a2bf6dbb7200709d1e852d7) @@ -0,0 +1,62 @@ +<%@ page import="java.util.Calendar"%> +<%@ page import="java.text.SimpleDateFormat"%> +<%@ page import="blackboard.base.FormattedText"%> +<%@ page import="blackboard.data.course.Course"%> +<%@ page import="blackboard.data.content.Content"%> +<%@ page import="blackboard.data.content.ContentFolder"%> +<%@ page import="blackboard.data.content.CourseDocument"%> +<%@ page import="blackboard.persist.Id"%> +<%@ page import="blackboard.persist.BbPersistenceManager"%> +<%@ page import="blackboard.persist.content.ContentDbPersister"%> +<%@ page import="blackboard.persist.content.ContentDbLoader"%> +<%@ page import="blackboard.platform.session.BbSessionManagerService"%> +<%@ page import="blackboard.platform.session.BbSession"%> +<%@ page import="blackboard.platform.*"%> +<%@ page import="blackboard.platform.plugin.PlugInUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsServiceUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.blackboard.LamsPluginUtil"%> +<%@ page import="org.lamsfoundation.ld.integration.Constants"%> + +<%@ page errorPage="/error.jsp"%><%@ page import="org.lamsfoundation.ld.integration.Constants" %> + +<%@ taglib uri="/bbUI" prefix="bbUI"%> +<%@ taglib uri="/bbData" prefix="bbData"%> + +<% + String courseId = request.getParameter("course_id"); + String contentId = request.getParameter("content_id"); + String designId = request.getParameter("itemSequenceId"); + String sequenceID = request.getParameter("sequence_id"); +%> + +<bbData:context id="ctx"> + <bbUI:docTemplate title = "Start a LAMS lesson." > + + <form name="lesson_form" id="lesson_form" action="start_lesson.jsp" method="post"> + <bbUI:step title="Name and describe the lesson"> + <bbUI:dataElement label="Name"> + <input id="title" type="text" name="title" value=""> + </bbUI:dataElement> + + <bbUI:dataElement label="Description"> + <bbUI:textbox name="description" rows="12" cols="55"></bbUI:textbox> + </bbUI:dataElement> + </bbUI:step> + + <bbUI:step title="Lesson options"> + <bbUI:dataElement label="Do you want to make LAMS visible?"> + <input type="Radio" name="isAvailable" value="true" checked>Yes + <input type="Radio" name="isAvailable" value="false">No + </bbUI:dataElement> + <bbUI:dataElement label="Track number of views"> + <input type="radio" name="isTracked" value="true">Yes + <input type="radio" name="isTracked" value="false" checked>No + </bbUI:dataElement> + <bbUI:dataElement label="Choose date restrictions"> + <bbUI:dateAvailability formName="lesson_form" startDateField="startDate" endDateField="endDate"/> + </bbUI:dataElement> + </bbUI:step> + <bbUI:stepSubmit title="Start lesson"/> + </form> + </bbUI:docTemplate> +</bbData:context> \ No newline at end of file