diff --git a/findbugs-excludes.xml b/findbugs-excludes.xml index 39d597dd..98e78911 100644 --- a/findbugs-excludes.xml +++ b/findbugs-excludes.xml @@ -19,16 +19,12 @@ - - - - - + diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java index 2a90386c..8f0e7385 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/Constants.java @@ -14,7 +14,9 @@ import org.joda.time.format.DateTimeFormatter; /** Global Constants used in SEB Server web-service as well as in web-gui component */ public final class Constants { + public static final int SEB_FILE_HEADER_SIZE = 4; public static final int JN_CRYPTOR_ITERATIONS = 10000; + public static final int JN_CRYPTOR_VERSION_HEADER_SIZE = 1; public static final String TRUE_STRING = Boolean.TRUE.toString(); public static final String FALSE_STRING = Boolean.FALSE.toString(); @@ -73,6 +75,7 @@ public final class Constants { public static final String XML_PLIST_INTEGER = "integer"; public static final String OAUTH2_GRANT_TYPE_PASSWORD = "password"; + public static final String OAUTH2_CLIENT_SECRET = "client_secret"; public static final String OAUTH2_GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; public static final String OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials"; public static final String OAUTH2_SCOPE_READ = "read"; @@ -82,7 +85,7 @@ public final class Constants { public static final int RWT_MOUSE_BUTTON_2 = 2; public static final int RWT_MOUSE_BUTTON_3 = 3; - public static final int GZIP_HEADER_LENGTH = 10; + public static final int GZIP_HEADER_LENGTH = 4; public static final int GZIP_ID1 = 0x1F; public static final int GZIP_ID2 = 0x8B; public static final int GZIP_CM = 8; diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java index 91a9d4dd..67a6f028 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java @@ -87,10 +87,14 @@ public class APIMessage implements Serializable { Utils.asImmutableList(attributes)); } - public APIMessage of(final Throwable error) { + public APIMessage of(final Exception error) { return new APIMessage(this.messageCode, this.systemMessage, error.getMessage()); } + public APIMessage of(final Exception error, final String... attributes) { + return new APIMessage(this.messageCode, this.systemMessage, error.getMessage(), Arrays.asList(attributes)); + } + public ResponseEntity> createErrorResponse() { final APIMessage message = of(); return new ResponseEntity<>( diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Result.java b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Result.java index 5ffa2bf1..f453b4ee 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/util/Result.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/util/Result.java @@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; * try { * ... do some computation * return Result.of(result); - * } catch (Throwable t) { + * } catch (Exception error) { * return Result.ofError(t); * } * } @@ -57,14 +57,14 @@ public final class Result { /** The resulting value. May be null if an error occurred */ private final T value; /** The error when happened otherwise null */ - private final Throwable error; + private final Exception error; private Result(final T value) { this.value = value; this.error = null; } - private Result(final Throwable error) { + private Result(final Exception error) { this.value = null; this.error = error; } @@ -80,7 +80,7 @@ public final class Result { * * @param errorHandler the error handling function * @return */ - public T get(final Function errorHandler) { + public T get(final Function errorHandler) { return this.error != null ? errorHandler.apply(this.error) : this.value; } @@ -90,7 +90,7 @@ public final class Result { * @param errorHandler the error handler to handle an error if happened * @param supplier supplies an alternative result element on error case * @return returns the referenced result element or the alternative element given by the supplier on error */ - public T get(final Consumer errorHandler, final Supplier supplier) { + public T get(final Consumer errorHandler, final Supplier supplier) { if (this.error != null) { errorHandler.accept(this.error); return supplier.get(); @@ -102,7 +102,7 @@ public final class Result { /** Apply a given error handler that consumes the error if there is one. * * @param errorHandler the error handler */ - public void handleError(final Consumer errorHandler) { + public void handleError(final Consumer errorHandler) { if (this.error != null) { errorHandler.accept(this.error); } @@ -153,7 +153,7 @@ public final class Result { } /** @return the error if some was reporter or null if there was no error */ - public Throwable getError() { + public Exception getError() { return this.error; } @@ -243,7 +243,7 @@ public final class Result { * * @param errorHandler the error handler * @return self reference */ - public Result onError(final Consumer errorHandler) { + public Result onError(final Consumer errorHandler) { if (this.error != null) { errorHandler.accept(this.error); } @@ -265,7 +265,7 @@ public final class Result { * * @param error the error that is wrapped within the created Result * @return Result of specified error */ - public static Result ofError(final Throwable error) { + public static Result ofError(final Exception error) { assert error != null : "error has null reference"; return new Result<>(error); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java index d3ed1d03..f737ec2e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/InstitutionalAuthenticationEntryPoint.java @@ -84,7 +84,6 @@ final class InstitutionalAuthenticationEntryPoint implements AuthenticationEntry Charsets.UTF_8); _defaultLogo = FileCopyUtils.copyToString(reader); - } catch (final IOException e) { log.warn("Failed to load default logo image from filesystem: {}", defaultLogoFileName); _defaultLogo = null; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java index 052f9eb9..4db1dcb0 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/ExamForm.java @@ -585,7 +585,7 @@ public class ExamForm implements TemplateComposer { private PageAction setSebRestriction( final PageAction action, final boolean sebRestriction, - final Consumer errorHandler) { + final Consumer errorHandler) { this.restService.getBuilder(SetExamSebRestriction.class) .withURIVariable( diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java index a4fa9d18..35e142bb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/LmsSetupForm.java @@ -324,7 +324,7 @@ public class LmsSetupForm implements TemplateComposer { // ... and handle the response if (result.hasError()) { if (formHandle.handleError(result.getError())) { - final Throwable error = result.getError(); + final Exception error = result.getError(); if (error instanceof RestCallError) { throw (RestCallError) error; } else { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java index c45d75a5..b8ec3924 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigImportPopup.java @@ -163,16 +163,23 @@ final class SebExamConfigImportPopup { } return true; } else { - final Throwable error = configuration.getError(); + final Exception error = configuration.getError(); if (error instanceof RestCallError) { ((RestCallError) error) .getErrorMessages() .stream() - .filter(APIMessage.ErrorMessage.MISSING_PASSWORD::isOf) .findFirst() - .ifPresent(message -> formHandle - .getContext() - .publishPageMessage(MISSING_PASSWORD)); + .ifPresent(message -> { + if (APIMessage.ErrorMessage.MISSING_PASSWORD.isOf(message)) { + formHandle + .getContext() + .publishPageMessage(MISSING_PASSWORD); + } else { + formHandle + .getContext() + .notifyError(error); + } + }); return true; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java index 29157ccc..78dcbdaf 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/SebExamConfigSettingsForm.java @@ -203,7 +203,7 @@ public class SebExamConfigSettingsForm implements TemplateComposer { } } - private void notifyErrorOnSave(final Throwable error, final PageContext context) { + private void notifyErrorOnSave(final Exception error, final PageContext context) { if (error instanceof APIMessageError) { try { final List errorMessages = ((APIMessageError) error).getErrorMessages(); @@ -215,7 +215,7 @@ public class SebExamConfigSettingsForm implements TemplateComposer { } } catch (final PageMessageException e) { throw e; - } catch (final Throwable e) { + } catch (final Exception e) { throw new RuntimeException(error); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java index 7bdbdc17..7603a1e5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/activity/ActivitiesPane.java @@ -301,7 +301,7 @@ public class ActivitiesPane implements TemplateComposer { // SEB Client Logs if (viewSebClientLogs) { - final TreeItem sebLogs = (monitoring != null) + final TreeItem sebLogs = (!isSupporter) ? this.widgetFactory.treeItemLocalized( monitoring, ActivityDefinition.SEB_CLIENT_LOGS.displayName) @@ -315,12 +315,10 @@ public class ActivitiesPane implements TemplateComposer { .create()); } - if (monitoring != null) { - monitoring.setExpanded( - this.currentUser - .get() - .hasAnyRole(UserRole.EXAM_SUPPORTER)); - } + monitoring.setExpanded( + this.currentUser + .get() + .hasAnyRole(UserRole.EXAM_SUPPORTER)); } // ---- MONITORING --------------------------------------------------------------------- diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java index c606754e..05388028 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/form/FormHandle.java @@ -121,7 +121,7 @@ public class FormHandle { .getOrThrow(); } - public boolean handleError(final Throwable error) { + public boolean handleError(final Exception error) { if (error instanceof RestCallError) { ((RestCallError) error) .getErrorMessages() diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java index f0ab6973..d4fefefc 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/examconfig/impl/ExamConfigurationServiceImpl.java @@ -384,7 +384,7 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService { .call(); } - private String verifyErrorMessage(final Throwable error) { + private String verifyErrorMessage(final Exception error) { if (error instanceof RestCallError) { final List errorMessages = ((RestCallError) error).getErrorMessages(); if (errorMessages.isEmpty()) { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java index e13745a2..0b5f2ed3 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageContext.java @@ -186,15 +186,15 @@ public interface PageContext { * optional exception instance * * @param errorMessage the error message to display - * @param error the error as Throwable */ - void notifyError(String errorMessage, Throwable error); + * @param error the error as Exception */ + void notifyError(String errorMessage, Exception error); - /** Shows an error message to the user with the message of the given Throwable. + /** Shows an error message to the user with the message of the given Exception. * This mainly is used for debugging so far * - * @param error the Throwable to display + * @param error the Exception to display * @return adaption to be used with functional approaches */ - T notifyError(Throwable error); + T notifyError(Exception error); /** Publish and shows a message to the user with the given localized title and * localized message. The message text can also be HTML text as far as RWT supports it. diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java index 662f4be5..6f687954 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/PageService.java @@ -156,7 +156,7 @@ public interface PageService { * and forward to the login page with showing a successful logout message to the user. */ void logout(PageContext pageContext); - default T logoutOnError(final Throwable t, final PageContext pageContext) { + default T logoutOnError(final Exception t, final PageContext pageContext) { log.error("Unexpected, Current User related error.Automatically logout and cleanup current user session. ", t); logout(pageContext); return null; diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java index 91c55dc0..f94f741d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/page/impl/PageContextImpl.java @@ -280,7 +280,7 @@ public class PageContextImpl implements PageContext { } @Override - public void notifyError(final String errorMessage, final Throwable error) { + public void notifyError(final String errorMessage, final Exception error) { if (error instanceof APIMessageError) { final List errorMessages = ((APIMessageError) error).getErrorMessages(); final MessageBox messageBox = new Message( @@ -302,7 +302,7 @@ public class PageContextImpl implements PageContext { } @Override - public T notifyError(final Throwable error) { + public T notifyError(final Exception error) { notifyError(error.getMessage(), error); return null; } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java index 291c6375..e4d3d518 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/api/RestCall.java @@ -116,32 +116,32 @@ public abstract class RestCall { } else { return handleRestCallError(responseEntity); } + } catch (final RestClientResponseException responseError) { - } catch (final Exception e) { - final RestCallError restCallError = new RestCallError("Unexpected error while rest call", e); + final RestCallError restCallError = new RestCallError("Unexpected error while rest call", responseError); try { - final String responseBody = ((RestClientResponseException) e).getResponseBodyAsString(); - + final String responseBody = responseError.getResponseBodyAsString(); restCallError.errors.addAll(RestCall.this.jsonMapper.readValue( responseBody, new TypeReference>() { })); - } catch (final ClassCastException cce) { - log.error("Unexpected error-response while webservice API call for: {}", builder, e); - restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of(e)); - } catch (final RuntimeException re) { - log.error("Unexpected runtime error while webservice API call for: {}", builder, re); - log.error("Unexpected runtime error cause: ", e); - restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of(re)); - } catch (final Exception ee) { - log.error("Unexpected error while webservice API call for: {}", builder, ee); - log.error("Unexpected error cause: ", e); - restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of(ee)); + } catch (final IOException e) { + restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of( + responseError, + "NO RESPONSE AVAILABLE" + " cause: " + e.getMessage(), + String.valueOf(builder))); } return Result.ofError(restCallError); + } catch (final Exception e) { + final RestCallError restCallError = new RestCallError("Unexpected error while rest call", e); + restCallError.errors.add(APIMessage.ErrorMessage.UNEXPECTED.of( + e, + "NO RESPONSE AVAILABLE", + String.valueOf(builder))); + return Result.ofError(e); } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/CurrentUser.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/CurrentUser.java index 61bc8c8f..22786d58 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/CurrentUser.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/CurrentUser.java @@ -62,7 +62,7 @@ public class CurrentUser { return null; } - public UserInfo getOrHandleError(final Function errorHandler) { + public UserInfo getOrHandleError(final Function errorHandler) { if (isAvailable()) { return this.authContext .getLoggedInUser() @@ -188,16 +188,23 @@ public class CurrentUser { }); if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) { - this.privileges = exchange.getBody().stream() - .reduce(new HashMap(), - (map, priv) -> { - map.put(priv.roleTypeKey, priv); - return map; - }, - (map1, map2) -> { - map1.putAll(map2); - return map1; - }); + final Collection privileges = exchange.getBody(); + if (privileges != null) { + this.privileges = privileges + .stream() + .reduce(new HashMap(), + (map, priv) -> { + map.put(priv.roleTypeKey, priv); + return map; + }, + (map1, map2) -> { + map1.putAll(map2); + return map1; + }); + } else { + log.error("Failed to get Privileges from webservice API: {}", exchange); + return false; + } return true; } else { diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java index 463d1261..a0552dc7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/remote/webservice/auth/OAuth2AuthorizationContextHolder.java @@ -298,7 +298,7 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol .contains(role.name()); } - private final class ErrorHandler extends OAuth2ErrorHandler { + private static final class ErrorHandler extends OAuth2ErrorHandler { private ErrorHandler(final OAuth2ProtectedResourceDetails resource) { super(resource); } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java index 6a704ee8..4f30f52b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/service/session/ClientConnectionTable.java @@ -261,7 +261,6 @@ public final class ClientConnectionTable { private boolean changed = false; private ClientConnectionData connectionData; private int indicatorWeight; - //private int[] thresholdColorIndices; private boolean duplicateChecked = false; UpdatableTableItem(final Long connectionId) { @@ -349,6 +348,29 @@ public final class ClientConnectionTable { .compare(this, other); } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + ((this.connectionId == null) ? 0 : this.connectionId.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final UpdatableTableItem other = (UpdatableTableItem) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + return compareTo(other) == 0; + } + int statusWeight() { return ClientConnectionTable.this.statusData.statusWeight(this.connectionData); } @@ -412,6 +434,10 @@ public final class ClientConnectionTable { } } + private ClientConnectionTable getOuterType() { + return ClientConnectionTable.this; + } + } } diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableFilter.java b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableFilter.java index 1c74230a..5d832035 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/table/TableFilter.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/table/TableFilter.java @@ -356,7 +356,7 @@ public class TableFilter { try { final org.joda.time.DateTime parse = org.joda.time.DateTime.parse(this.attribute.initValue); this.selector.setDate(parse.getYear(), parse.getMonthOfYear() - 1, parse.getDayOfMonth()); - } catch (final Exception e) { + } catch (final RuntimeException e) { final org.joda.time.DateTime now = org.joda.time.DateTime.now(DateTimeZone.UTC); this.selector.setDate(now.getYear(), now.getMonthOfYear() - 1, now.getDayOfMonth()); } @@ -436,7 +436,7 @@ public class TableFilter { parse.getMonthOfYear() - 1, parse.getDayOfMonth()); - } catch (final Exception e) { + } catch (final RuntimeException e) { this.fromSelector.setDate( now.getYear(), now.getMonthOfYear() - 1, diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/widget/GridTable.java b/src/main/java/ch/ethz/seb/sebserver/gui/widget/GridTable.java index 1190511b..3b6a182f 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/widget/GridTable.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/widget/GridTable.java @@ -203,9 +203,19 @@ public class GridTable extends Composite { private void adaptColumnWidth(final Event event) { try { - this.columns.get(0).header.widthHint = 50; - this.columns.get(1).header.widthHint = 200; + final int currentTableWidth = super.getClientArea().width - ACTION_COLUMN_WIDTH; + final int widthUnit = currentTableWidth / this.columns + .stream() + .reduce(0, + (i, c2) -> i + c2.columnDef.widthFactor, + (i1, i2) -> i1 + i2); + + this.columns + .stream() + .forEach(c -> c.header.widthHint = c.columnDef.widthFactor * widthUnit); + + super.layout(true, true); } catch (final Exception e) { log.warn("Failed to adaptColumnWidth: ", e); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java index b3248559..77122779 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/bulkaction/BulkActionSupportDAO.java @@ -95,7 +95,7 @@ public interface BulkActionSupportDAO { * @param error the error that shall be referred by created Result's * @param all all entity keys to create error Result for * @return List of Result refer to a given error for all given EntityKey instances */ - static List> handleBulkActionError(final Throwable error, final Set all) { + static List> handleBulkActionError(final Exception error, final Set all) { return all.stream() .map(key -> Result. ofError(new BulkActionEntityException(key))) .collect(Collectors.toList()); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceImpl.java index c6c143c2..0b9549d4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/client/ClientCredentialServiceImpl.java @@ -168,8 +168,8 @@ public class ClientCredentialServiceImpl implements ClientCredentialService { } } - private final static char[] possibleCharacters = (new String( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?")) + private final static char[] possibleCharacters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^*()-_=+[{]}?" .toCharArray(); private CharSequence generateClientId() { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/TransactionHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/TransactionHandler.java index 37812a36..cefcad97 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/TransactionHandler.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/TransactionHandler.java @@ -45,7 +45,7 @@ public interface TransactionHandler { * * @see org.springframework.transaction.support.TransactionCallback#doInTransaction * @see org.springframework.transaction.interceptor.TransactionAttribute#rollbackOn */ - static void rollback(final Throwable t) { + static void rollback(final Exception t) { TransactionInterceptor.currentTransactionStatus().setRollbackOnly(); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java index fe85eff9..1689bd86 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/LmsAPIService.java @@ -75,7 +75,7 @@ public interface LmsAPIService { * * @param filterMap the FilterMap containing the filter criteria * @return true if the given QuizzData passes the filter */ - public static Predicate quizFilterFunction(final FilterMap filterMap) { + public static Predicate quizFilterPredicate(final FilterMap filterMap) { final String name = filterMap.getQuizName(); final DateTime from = filterMap.getQuizFromTime(); //final DateTime now = DateTime.now(DateTimeZone.UTC); @@ -92,10 +92,9 @@ public interface LmsAPIService { * @param filterMap the FilterMap containing the filter criteria * @return filtered list of QuizData */ public static Function, List> quizzesFilterFunction(final FilterMap filterMap) { - filterMap.getName(); return quizzes -> quizzes .stream() - .filter(quizFilterFunction(filterMap)) + .filter(quizFilterPredicate(filterMap)) .collect(Collectors.toList()); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java index 87542447..97d38449 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/MockupLmsAPITemplate.java @@ -149,7 +149,7 @@ final class MockupLmsAPITemplate implements LmsAPITemplate { final List quizzes = this.mockups .stream() .map(this::getExternalAddressAlias) - .filter(LmsAPIService.quizFilterFunction(filterMap)) + .filter(LmsAPIService.quizFilterPredicate(filterMap)) .collect(Collectors.toList()); return quizzes; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseAccess.java index 025a1722..c55bf4f7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/edx/OpenEdxCourseAccess.java @@ -229,7 +229,7 @@ final class OpenEdxCourseAccess { public String end; } - private class EdxOAuth2RequestAuthenticator implements OAuth2RequestAuthenticator { + private static final class EdxOAuth2RequestAuthenticator implements OAuth2RequestAuthenticator { @Override public void authenticate( 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 22fdfd2f..6b5c8b45 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 @@ -28,10 +28,12 @@ import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; @@ -151,7 +153,7 @@ final class OpenEdxRestTemplateFactory { /** A custom ClientCredentialsAccessTokenProvider that adapts the access token request to Open edX * access token request protocol using a form-URL-encoded POST request according to: * https://course-catalog-api-guide.readthedocs.io/en/latest/authentication/index.html#getting-an-access-token */ - private class EdxClientCredentialsAccessTokenProvider extends ClientCredentialsAccessTokenProvider { + private static final class EdxClientCredentialsAccessTokenProvider extends ClientCredentialsAccessTokenProvider { @Override public OAuth2AccessToken obtainAccessToken( @@ -167,9 +169,9 @@ final class OpenEdxRestTemplateFactory { headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); final MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("grant_type", "client_credentials"); - params.add("client_id", resource.getClientId()); - params.add("client_secret", resource.getClientSecret()); + params.add(OAuth2Utils.GRANT_TYPE, Constants.OAUTH2_GRANT_TYPE_CLIENT_CREDENTIALS); + params.add(OAuth2Utils.CLIENT_ID, resource.getClientId()); + params.add(Constants.OAUTH2_CLIENT_SECRET, resource.getClientSecret()); final OAuth2AccessToken retrieveToken = retrieveToken(request, resource, params, headers); return retrieveToken; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ZipService.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ZipService.java index d11a46fe..033ef6cb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ZipService.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/ZipService.java @@ -21,7 +21,7 @@ public interface ZipService { /** Use this to read uncompressed data from a given input-stream, * compress this data with gzip and write the compressed data to * a given output stream. - * + * * @param out the OutputStream to write the compressed data to * @param in the InputStream to read the uncompressed data from */ @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) @@ -30,7 +30,7 @@ public interface ZipService { /** Use this to read gzip-compressed data from a given input-stream, * uncompress this data and write the uncompressed data to * a given output stream. - * + * * @param out the OutputStream to write the uncompressed data to * @param in the InputStream to read the compressed data from */ @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java index b168c5a7..62b001b4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ClientConfigServiceImpl.java @@ -235,8 +235,8 @@ public class ClientConfigServiceImpl implements ClientConfigService { ? "true" : "false", (StringUtils.isNotBlank(config.fallbackStartURL)) - ? " startURL\r\n" + - " " + config.fallbackStartURL + "\r\n" + ? " startURL%n" + + " " + config.fallbackStartURL + "%n" : "", this.webserviceInfo.getExternalServerURL(), String.valueOf(config.institutionId), diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java index cc0c3efc..feaa5c0d 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigIO.java @@ -216,15 +216,18 @@ public class ExamConfigIO { InputStream unzip(final InputStream input) throws Exception { - final byte[] zipHeader = new byte[4]; - input.read(zipHeader); + final byte[] zipHeader = new byte[Constants.GZIP_HEADER_LENGTH]; + final int read = input.read(zipHeader); + if (read < Constants.GZIP_HEADER_LENGTH) { + throw new IllegalArgumentException("Failed to verify Zip type from input stream. Header size mismatch."); + } final boolean isZipped = Byte.toUnsignedInt(zipHeader[0]) == Constants.GZIP_ID1 && Byte.toUnsignedInt(zipHeader[1]) == Constants.GZIP_ID2 && Byte.toUnsignedInt(zipHeader[2]) == Constants.GZIP_CM; final InputStream sequencedInput = new SequenceInputStream( - new ByteArrayInputStream(zipHeader, 0, 4), + new ByteArrayInputStream(zipHeader, 0, Constants.GZIP_HEADER_LENGTH), input); if (isZipped) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java index 448230d9..36bcf565 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigServiceImpl.java @@ -38,13 +38,12 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO; -import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamConfigurationMapDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationFormat; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ConfigurationValueValidator; +import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigEncryptionService.Strategy; -import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ZipService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.SebConfigEncryptionServiceImpl.EncryptionContext; @@ -57,7 +56,6 @@ public class ExamConfigServiceImpl implements ExamConfigService { private final ExamConfigIO examConfigIO; private final ConfigurationAttributeDAO configurationAttributeDAO; - private final ConfigurationDAO configurationDAO; private final ExamConfigurationMapDAO examConfigurationMapDAO; private final Collection validators; private final ClientCredentialService clientCredentialService; @@ -67,7 +65,6 @@ public class ExamConfigServiceImpl implements ExamConfigService { protected ExamConfigServiceImpl( final ExamConfigIO examConfigIO, final ConfigurationAttributeDAO configurationAttributeDAO, - final ConfigurationDAO configurationDAO, final ExamConfigurationMapDAO examConfigurationMapDAO, final Collection validators, final ClientCredentialService clientCredentialService, @@ -76,7 +73,6 @@ public class ExamConfigServiceImpl implements ExamConfigService { this.examConfigIO = examConfigIO; this.configurationAttributeDAO = configurationAttributeDAO; - this.configurationDAO = configurationDAO; this.examConfigurationMapDAO = examConfigurationMapDAO; this.validators = validators; this.clientCredentialService = clientCredentialService; @@ -366,14 +362,10 @@ public class ExamConfigServiceImpl implements ExamConfigService { } catch (final Exception e) { log.error("Unexpected error while trying to import SEB Exam Configuration: ", e); - log.debug("Make an undo on the ConfigurationNode to rollback the changes"); - this.configurationDAO - .undo(config.configurationNodeId) - .getOrThrow(); if (streamDecrypted != null) { final Exception exception = streamDecrypted.get(); - if (exception != null) { + if (exception != null && exception instanceof APIMessageException) { throw exception; } } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigXMLParser.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigXMLParser.java index 4119abb9..ad776b42 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigXMLParser.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/ExamConfigXMLParser.java @@ -281,8 +281,8 @@ public class ExamConfigXMLParser extends DefaultHandler { } // check if we have a simple values array - if (attribute.type == AttributeType.MULTI_CHECKBOX_SELECTION - || attribute.type == AttributeType.MULTI_SELECTION) { + if (attribute != null && (attribute.type == AttributeType.MULTI_CHECKBOX_SELECTION + || attribute.type == AttributeType.MULTI_SELECTION)) { saveValue(attrName, attribute, top.listIndex, (top.value == null) ? "" : top.value); } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java index 9ccb8af3..7f540dbb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/PasswordEncryptor.java @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.SebConfigCryptor; @@ -64,7 +65,7 @@ public class PasswordEncryptor implements SebConfigCryptor { encryptOutput = new AES256JNCryptorOutputStream( output, Utils.toCharArray(context.getPassword()), - 10000); + Constants.JN_CRYPTOR_ITERATIONS); IOUtils.copyLarge(input, encryptOutput); @@ -98,8 +99,11 @@ public class PasswordEncryptor implements SebConfigCryptor { final CharSequence password = context.getPassword(); try { - final byte[] version = new byte[4]; - input.read(version); + final byte[] version = new byte[Constants.JN_CRYPTOR_VERSION_HEADER_SIZE]; + final int read = input.read(version); + if (read != Constants.JN_CRYPTOR_VERSION_HEADER_SIZE) { + throw new IllegalArgumentException("Failed to verify RNCrypt version from input stream file header."); + } final SequenceInputStream sequenceInputStream = new SequenceInputStream( new ByteArrayInputStream(version), @@ -136,7 +140,7 @@ public class PasswordEncryptor implements SebConfigCryptor { IOUtils.copy(sequenceInputStream, out); final byte[] ciphertext = out.toByteArray(); final AES256JNCryptor cryptor = new AES256JNCryptor(); - cryptor.setPBKDFIterations(10000); + cryptor.setPBKDFIterations(Constants.JN_CRYPTOR_ITERATIONS); final byte[] decryptData = cryptor.decryptData(ciphertext, Utils.toCharArray(password)); final ByteArrayInputStream decryptedIn = new ByteArrayInputStream(decryptData); IOUtils.copyLarge(decryptedIn, output); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImpl.java index 40b2fc7d..6e15b6b9 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/sebconfig/impl/SebConfigEncryptionServiceImpl.java @@ -32,6 +32,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.util.Result; @@ -46,8 +47,6 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption private static final Logger log = LoggerFactory.getLogger(SebConfigEncryptionServiceImpl.class); - public static final int HEADER_SIZE = 4; - private final Map encryptors; public SebConfigEncryptionServiceImpl( @@ -118,8 +117,12 @@ public final class SebConfigEncryptionServiceImpl implements SebConfigEncryption pin = new PipedInputStream(pout); Strategy strategy = null; - final byte[] header = new byte[HEADER_SIZE]; - input.read(header); + final byte[] header = new byte[Constants.SEB_FILE_HEADER_SIZE]; + final int read = input.read(header); + if (read != Constants.SEB_FILE_HEADER_SIZE) { + throw new IllegalArgumentException("Failed to read seb file header."); + } + for (final Strategy s : Strategy.values()) { if (Arrays.equals(s.header, header)) { strategy = s;