Index: lams_tool_zoom/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r54a14306d3b36e6da9aedbaa6700c91048ebc53a -rde735f1c077e7c8ca07eddc6894b06e5beef5331 --- lams_tool_zoom/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 54a14306d3b36e6da9aedbaa6700c91048ebc53a) +++ lams_tool_zoom/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision de735f1c077e7c8ca07eddc6894b06e5beef5331) @@ -62,7 +62,7 @@ label.api.up =Up label.api.down =Down label.api.remove =Remove API keys -label.api.saved =API keys were saved +label.api.saved =API keys were saved. API works only with paid Zoom plans. error.api.ping =API keys for email {0} do not seem to work correctly error.api.none.configured =There are no Zoom API keys configured by the administrator. You are not able to create a Zoom meeting. error.api.reuse =All configured API keys are in use at the moment. If you decide to start your meeting, another teacher's meeting will be stopped. Index: lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/service/ZoomService.java =================================================================== diff -u -r20aa6cbca9fc96d341080e6ad39f82593443f792 -rde735f1c077e7c8ca07eddc6894b06e5beef5331 --- lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/service/ZoomService.java (.../ZoomService.java) (revision 20aa6cbca9fc96d341080e6ad39f82593443f792) +++ lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/service/ZoomService.java (.../ZoomService.java) (revision de735f1c077e7c8ca07eddc6894b06e5beef5331) @@ -24,11 +24,13 @@ package org.lamsfoundation.lams.tool.zoom.service; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.lang.reflect.Field; import java.net.HttpURLConnection; +import java.nio.charset.Charset; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -44,6 +46,7 @@ import javax.net.ssl.HttpsURLConnection; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; import org.lamsfoundation.lams.contentrepository.client.IToolContentHandler; @@ -147,7 +150,7 @@ @Override public SortedMap getToolOutput(List names, Long toolSessionId, Long learnerId) { - return new TreeMap(); + return new TreeMap<>(); } @Override @@ -157,14 +160,14 @@ @Override public List getToolOutputs(String name, Long toolContentId) { - return new ArrayList(); + return new ArrayList<>(); } @Override public List getConfidenceLevels(Long toolSessionId) { return null; } - + @Override public boolean isUserGroupLeader(Long userId, Long toolSessionId) { return false; @@ -334,7 +337,7 @@ @Override public SortedMap getToolOutputDefinitions(Long toolContentId, int definitionType) throws ToolException { - return new TreeMap(); + return new TreeMap<>(); } @Override @@ -450,7 +453,7 @@ public void auditLogStartEditingActivityInMonitor(long toolContentID) { toolService.auditLogStartEditingActivityInMonitor(toolContentID); } - + @Override public boolean isLastActivity(Long toolSessionId) { return toolService.isLastActivity(toolSessionId); @@ -470,7 +473,7 @@ @Override @SuppressWarnings("unchecked") public ZoomUser getUserByUserIdAndSessionId(Integer userId, Long toolSessionId) { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("userId", userId); map.put("zoomSession.sessionId", toolSessionId); List list = zoomDAO.findByProperties(ZoomUser.class, map); @@ -602,7 +605,7 @@ return null; } ZoomApi chosenApi = null; - TreeMap liveApis = new TreeMap(); + TreeMap liveApis = new TreeMap<>(); for (ZoomApi api : apis) { String meetingListURL = "users/" + api.getEmail() + "/meetings?type=live"; HttpURLConnection connection = ZoomService.getZoomConnection(meetingListURL, "GET", null, api); @@ -678,7 +681,14 @@ if (user.getMeetingJoinUrl() != null) { return user.getMeetingJoinUrl(); } + Zoom zoom = (Zoom) zoomDAO.find(Zoom.class, zoomUid); + if (zoom.getApi() == null) { + Boolean apiOK = chooseApi(zoomUid); + if (apiOK == null || !apiOK) { + throw new ZoomException("Can not join the meeting. Problem with Zoom API."); + } + } ObjectNode bodyJSON = JsonNodeFactory.instance.objectNode(); String lastName = user.getLastName(); @@ -707,8 +717,8 @@ @Override public void saveApis(List apis) { List existingApis = getApis(); - Set delete = new HashSet(); - Set saved = new HashSet(); + Set delete = new HashSet<>(); + Set saved = new HashSet<>(); for (ZoomApi existingApi : existingApis) { boolean found = false; for (ZoomApi api : apis) { @@ -744,7 +754,7 @@ HttpURLConnection connection = ZoomService.getZoomConnection("users/email?email=" + api.getEmail(), "GET", null, api); ObjectNode resultJSON = ZoomService.getReponse(connection); - return resultJSON != null && JsonUtil.optBoolean(resultJSON, "existed_email"); + return resultJSON != null && JsonUtil.optBoolean(resultJSON, "existed_email", false); } private static String generateJWT(ZoomApi api) { @@ -836,19 +846,29 @@ try { connection.connect(); int code = connection.getResponseCode(); + String responseMessage = connection.getResponseMessage(); String response = null; + InputStream responseStream = code < 300 ? connection.getInputStream() : connection.getErrorStream(); - if (code < 300) { + if (responseStream != null) { StringWriter writer = new StringWriter(); - IOUtils.copy(connection.getInputStream(), writer); + IOUtils.copy(responseStream, writer, Charset.defaultCharset()); response = writer.toString(); if (response != null && response.startsWith("{")) { responseJSON = JsonUtil.readObject(response); + if (code >= 300) { + String errorCode = JsonUtil.optString(responseJSON, "code"); + if (StringUtils.isNotBlank(errorCode) && errorCode.equals("200")) { + throw new ZoomException("API can only be used with a paid account"); + } + } } } if (logger.isDebugEnabled()) { - logger.debug("Server response: " + code + " " + connection.getResponseMessage() + " " + response); + logger.debug("Server response: " + code + + (responseMessage == null ? "" : " " + connection.getResponseMessage()) + + (response == null ? "" : " " + response)); } } finally { connection.disconnect(); Index: lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/web/controller/LearningController.java =================================================================== diff -u -r3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db -rde735f1c077e7c8ca07eddc6894b06e5beef5331 --- lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/web/controller/LearningController.java (.../LearningController.java) (revision 3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db) +++ lams_tool_zoom/src/java/org/lamsfoundation/lams/tool/zoom/web/controller/LearningController.java (.../LearningController.java) (revision de735f1c077e7c8ca07eddc6894b06e5beef5331) @@ -51,6 +51,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @@ -213,23 +214,34 @@ // set toolSessionID in request request.setAttribute(ZoomConstants.ATTR_TOOL_SESSION_ID, session.getSessionId()); - if (mode.isAuthor() || !zoom.isStartInMonitor()) { - // start a meeting just like a monitor would - MultiValueMap errorMap = ZoomUtil.startMeeting(zoomService, messageService, zoom, request); - if (!errorMap.isEmpty()) { - request.setAttribute("errorMap", errorMap); + MultiValueMap errorMap = null; + try { + if (mode.isAuthor() || !zoom.isStartInMonitor()) { + // start a meeting just like a monitor would + errorMap = ZoomUtil.startMeeting(zoomService, messageService, zoom, request); + if (!errorMap.isEmpty()) { + request.setAttribute("errorMap", errorMap); + } } - } - if (!mode.isAuthor()) { - // register a learner for the meeting - String meetingURL = user.getMeetingJoinUrl(); - if (meetingURL == null && zoom.getMeetingId() != null) { - meetingURL = zoomService.registerUser(zoom.getUid(), user.getUid(), session.getSessionName()); + if (!mode.isAuthor() && (errorMap == null || errorMap.isEmpty())) { + // register a learner for the meeting + String meetingURL = user.getMeetingJoinUrl(); + if (meetingURL == null && zoom.getMeetingId() != null) { + meetingURL = zoomService.registerUser(zoom.getUid(), user.getUid(), session.getSessionName()); + } + // if start in monitor is not set, this overwrites the URL set in ZoomUtil.startMeeting() above + request.setAttribute(ZoomConstants.ATTR_MEETING_URL, meetingURL); } - // if start in monitor is not set, this overwrites the URL set in ZoomUtil.startMeeting() above - request.setAttribute(ZoomConstants.ATTR_MEETING_URL, meetingURL); - } + } catch (Exception e) { + logger.error("Exception while entering a Zoom meeting", e); + if (errorMap == null) { + errorMap = new LinkedMultiValueMap<>(); + request.setAttribute("errorMap", errorMap); + } + errorMap.add("GLOBAL", e.getMessage()); + request.setAttribute("skipContent", true); + } return "pages/learning/learning"; } }