From dade1b2da3ad162eb9853409bf4c5a201b9eca88 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 17 Mar 2021 12:54:17 +0100 Subject: [PATCH] Prepare LMS Setups --- .../ch/ethz/seb/sebserver/gbl/util/Utils.java | 20 ++++++++ .../servicelayer/lms/LmsAPITemplate.java | 46 +++++++------------ .../servicelayer/lms/impl/CourseAccess.java | 2 +- .../impl/edx/OpenEdxRestTemplateFactory.java | 4 +- .../moodle/MoodleRestTemplateFactory.java | 3 +- 5 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java index a76655f9..a50a1025 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Utils.java @@ -8,7 +8,11 @@ package ch.ethz.seb.sebserver.gbl.util; +import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.ByteBuffer; @@ -686,4 +690,20 @@ public final class Utils { public static String valueOrEmptyNote(final String value) { return StringUtils.isBlank(value) ? Constants.EMPTY_NOTE : value; } + + /** This is used to verify if a given URL is available (valid) + * Uses java.net.Socket to try to connect to the given URL + * + * @param urlString the URL string + * @return true if SEB Server was able to ping the address. */ + public static boolean pingHost(final String urlString) { + try (Socket socket = new Socket()) { + final URL url = new URL(urlString); + final int port = (url.getPort() >= 0) ? url.getPort() : 80; + socket.connect(new InetSocketAddress(url.getHost(), port), (int) Constants.SECOND_IN_MILLIS * 5); + return true; + } catch (final IOException e) { + return false; // Either timeout or unreachable or failed DNS lookup. + } + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java index 855fde5b..42d8df8c 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPITemplate.java @@ -8,10 +8,6 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.lms; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -20,7 +16,6 @@ import java.util.Set; import org.apache.commons.lang3.StringUtils; -import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Exam; @@ -77,18 +72,12 @@ public interface LmsAPITemplate { * @return Collection of all QuizData from the given id set */ Collection> getQuizzes(Set ids); - /** Get all QuizData for the set of QuizData identifiers from LMS API in a collection - * of Result. If particular Quiz cannot be loaded because of errors or deletion, - * the Result will have an error reference. + /** Get the quiz data with specified identifier. * - * NOTE: This method looks first in the cache for all given ids. - * If all quizzes are cached, returns all from cache. - * If one quiz is not in the cache, requests all quizzes from the API and refreshes the cache + * Default implementation: Uses getQuizzes(Set ids) and returns the first matching or an error. * - * @param ids the Set of Quiz identifiers to get the QuizData for - * @return Collection of all QuizData from the given id set */ - Collection> getQuizzesFromCache(Set ids); - + * @param id the quiz data identifier + * @return Result refer to the quiz data or to an error when happened */ default Result getQuiz(final String id) { if (StringUtils.isBlank(id)) { return Result.ofError(new RuntimeException("missing model id")); @@ -100,6 +89,18 @@ public interface LmsAPITemplate { .orElse(Result.ofError(new ResourceNotFoundException(EntityType.EXAM, id))); } + /** Get all QuizData for the set of QuizData identifiers from LMS API in a collection + * of Result. If particular Quiz cannot be loaded because of errors or deletion, + * the Result will have an error reference. + * + * NOTE: This method looks first in the cache if existing for all given ids. + * If all quizzes are cached, returns all from cache. + * If one quiz is not in the cache, requests all quizzes from the API and refreshes the cache + * + * @param ids the Set of Quiz identifiers to get the QuizData for + * @return Collection of all QuizData from the given id set */ + Collection> getQuizzesFromCache(Set ids); + /** Convert a an anonymous or temporary user session identifier from SEB Client into a user * account details. * @@ -152,19 +153,4 @@ public interface LmsAPITemplate { * @return Result refer to the given Exam if successful or to an error if not */ Result releaseSEBClientRestriction(Exam exam); - /** This is used to verify if a given LMS Setup URL is available (valid) - * - * @param urlString the URL string given by the LMS Setup attribute - * @return true if SEB Server was able to ping the address. */ - static boolean pingHost(final String urlString) { - try (Socket socket = new Socket()) { - final URL url = new URL(urlString); - final int port = (url.getPort() >= 0) ? url.getPort() : 80; - socket.connect(new InetSocketAddress(url.getHost(), port), (int) Constants.SECOND_IN_MILLIS * 5); - return true; - } catch (final IOException e) { - return false; // Either timeout or unreachable or failed DNS lookup. - } - } - } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java index edc58243..9d12a54b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/CourseAccess.java @@ -97,7 +97,7 @@ public abstract class CourseAccess { final List cached = allQuizzesSupplier().getAllCached(); final List available = (cached != null) ? cached - : quizzesSupplier(ids).get(); + : Collections.emptyList(); final Map quizMapping = available .stream() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxRestTemplateFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxRestTemplateFactory.java index 04612273..1e18d39a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxRestTemplateFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxRestTemplateFactory.java @@ -42,7 +42,7 @@ import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; import ch.ethz.seb.sebserver.gbl.util.Result; -import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; +import ch.ethz.seb.sebserver.gbl.util.Utils; final class OpenEdxRestTemplateFactory { @@ -84,7 +84,7 @@ final class OpenEdxRestTemplateFactory { "lmsSetup:lmsUrl:notNull")); } else { // try to connect to the url - if (!LmsAPITemplate.pingHost(this.lmsSetup.lmsApiUrl)) { + if (!Utils.pingHost(this.lmsSetup.lmsApiUrl)) { missingAttrs.add(APIMessage.fieldValidationError( LMS_SETUP.ATTR_LMS_URL, "lmsSetup:lmsUrl:url.invalid")); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java index 522452d9..322141d7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java @@ -50,7 +50,6 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; -import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; class MoodleRestTemplateFactory { @@ -95,7 +94,7 @@ class MoodleRestTemplateFactory { "lmsSetup:lmsUrl:notNull")); } else { // try to connect to the url - if (!LmsAPITemplate.pingHost(this.lmsSetup.lmsApiUrl)) { + if (!Utils.pingHost(this.lmsSetup.lmsApiUrl)) { missingAttrs.add(APIMessage.fieldValidationError( LMS_SETUP.ATTR_LMS_URL, "lmsSetup:lmsUrl:url.invalid"));