Merge branch 'master' of https://github.com/SafeExamBrowser/seb-server.git
This commit is contained in:
		
						commit
						cccbc48805
					
				
					 61 changed files with 7744 additions and 7773 deletions
				
			
		|  | @ -34,7 +34,7 @@ public class GuiInit implements ApplicationListener<ApplicationReadyEvent> { | ||||||
|         SEBServerInit.INIT_LOGGER.info("---->  **** GUI Service starting up... ****"); |         SEBServerInit.INIT_LOGGER.info("---->  **** GUI Service starting up... ****"); | ||||||
| 
 | 
 | ||||||
|         SEBServerInit.INIT_LOGGER.info("---->"); |         SEBServerInit.INIT_LOGGER.info("---->"); | ||||||
|         SEBServerInit.INIT_LOGGER.info("---->  GUI Service sucessfully successfully started up!"); |         SEBServerInit.INIT_LOGGER.info("---->  GUI Service successfully successfully started up!"); | ||||||
|         SEBServerInit.INIT_LOGGER.info("---->"); |         SEBServerInit.INIT_LOGGER.info("---->"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -73,12 +73,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati | ||||||
|         this.webserviceURIService = webserviceURIService; |         this.webserviceURIService = webserviceURIService; | ||||||
|         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; |         this.clientHttpRequestFactoryService = clientHttpRequestFactoryService; | ||||||
| 
 | 
 | ||||||
|         String _defaultLogo = null; |         String _defaultLogo; | ||||||
|         if (!Constants.NO_NAME.equals(defaultLogoFileName)) { |         if (!Constants.NO_NAME.equals(defaultLogoFileName)) { | ||||||
|             try { |             try { | ||||||
| 
 | 
 | ||||||
|                 final String extension = ImageUploadSelection.SUPPORTED_IMAGE_FILES.stream() |                 final String extension = ImageUploadSelection.SUPPORTED_IMAGE_FILES.stream() | ||||||
|                         .filter(ext -> defaultLogoFileName.endsWith(ext)) |                         .filter(defaultLogoFileName::endsWith) | ||||||
|                         .findFirst() |                         .findFirst() | ||||||
|                         .orElse(null); |                         .orElse(null); | ||||||
| 
 | 
 | ||||||
|  | @ -141,7 +141,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati | ||||||
|                                 : null); |                                 : null); | ||||||
| 
 | 
 | ||||||
|                 if (log.isDebugEnabled()) { |                 if (log.isDebugEnabled()) { | ||||||
|                     log.debug("Known and active gui entrypoint requested:", institutions); |                     log.debug("Known and active gui entrypoint requested: {}", institutions); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 final String logoImageBase64 = requestLogoImage(institutionalEndpoint); |                 final String logoImageBase64 = requestLogoImage(institutionalEndpoint); | ||||||
|  | @ -184,9 +184,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             return requestURI.substring( |             return requestURI.substring(requestURI.lastIndexOf(Constants.SLASH) + 1); | ||||||
|                     requestURI.lastIndexOf(Constants.SLASH) + 1, |  | ||||||
|                     requestURI.length()); |  | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|             log.error("Failed to extract institutional URL suffix: {}", e.getMessage()); |             log.error("Failed to extract institutional URL suffix: {}", e.getMessage()); | ||||||
|             return null; |             return null; | ||||||
|  | @ -231,12 +229,12 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati | ||||||
|             if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) { |             if (exchange.getStatusCodeValue() == HttpStatus.OK.value()) { | ||||||
|                 return exchange.getBody(); |                 return exchange.getBody(); | ||||||
|             } else { |             } else { | ||||||
|                 log.warn("Failed to verify insitution from requested entrypoint url: {}, response: {}", |                 log.warn("Failed to verify institution from requested entrypoint url: {}, response: {}", | ||||||
|                         institutionalEndpoint, |                         institutionalEndpoint, | ||||||
|                         exchange); |                         exchange); | ||||||
|             } |             } | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|             log.warn("Failed to verify insitution from requested entrypoint url: {}", |             log.warn("Failed to verify institution from requested entrypoint url: {}", | ||||||
|                     institutionalEndpoint, |                     institutionalEndpoint, | ||||||
|                     e); |                     e); | ||||||
|         } |         } | ||||||
|  | @ -245,7 +243,7 @@ public final class InstitutionalAuthenticationEntryPoint implements Authenticati | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** TODO this seems not to work as expected. Different Theme is only possible in RAP on different |     /** TODO this seems not to work as expected. Different Theme is only possible in RAP on different | ||||||
|      * entry-points and since entry-points are statically defined within the RAPConficuration |      * entry-points and since entry-points are statically defined within the RAPConfiguration | ||||||
|      * there is no possibility to apply them dynamically within an institution so far. |      * there is no possibility to apply them dynamically within an institution so far. | ||||||
|      * |      * | ||||||
|      * @param institutionalEndpoint |      * @param institutionalEndpoint | ||||||
|  |  | ||||||
|  | @ -63,7 +63,7 @@ public class RAPConfiguration implements ApplicationConfiguration { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static interface EntryPointService { |     public interface EntryPointService { | ||||||
| 
 | 
 | ||||||
|         void loadLoginPage(final Composite parent); |         void loadLoginPage(final Composite parent); | ||||||
| 
 | 
 | ||||||
|  | @ -160,5 +160,5 @@ public class RAPConfiguration implements ApplicationConfiguration { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     }; |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,10 +8,7 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui; | package ch.ethz.seb.sebserver.gui; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.ServletContext; | import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | ||||||
| import javax.servlet.ServletContextListener; |  | ||||||
| import javax.servlet.ServletException; |  | ||||||
| 
 |  | ||||||
| import org.eclipse.rap.rwt.engine.RWTServlet; | import org.eclipse.rap.rwt.engine.RWTServlet; | ||||||
| import org.eclipse.rap.rwt.engine.RWTServletContextListener; | import org.eclipse.rap.rwt.engine.RWTServletContextListener; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
|  | @ -25,7 +22,8 @@ import org.springframework.context.annotation.Bean; | ||||||
| import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||||
| import org.springframework.context.support.ReloadableResourceBundleMessageSource; | import org.springframework.context.support.ReloadableResourceBundleMessageSource; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | import javax.servlet.ServletContext; | ||||||
|  | import javax.servlet.ServletContextListener; | ||||||
| 
 | 
 | ||||||
| @Configuration | @Configuration | ||||||
| @GuiProfile | @GuiProfile | ||||||
|  | @ -73,7 +71,7 @@ public class RAPSpringConfig { | ||||||
| 
 | 
 | ||||||
|     private static class RAPServletContextInitializer implements ServletContextInitializer { |     private static class RAPServletContextInitializer implements ServletContextInitializer { | ||||||
|         @Override |         @Override | ||||||
|         public void onStartup(final ServletContext servletContext) throws ServletException { |         public void onStartup(final ServletContext servletContext) { | ||||||
|             servletContext.setInitParameter( |             servletContext.setInitParameter( | ||||||
|                     "org.eclipse.rap.applicationConfiguration", |                     "org.eclipse.rap.applicationConfiguration", | ||||||
|                     RAPConfiguration.class.getName()); |                     RAPConfiguration.class.getName()); | ||||||
|  |  | ||||||
|  | @ -82,8 +82,8 @@ public class ResourceService { | ||||||
| 
 | 
 | ||||||
|     private static final String MISSING_CLIENT_PING_NAME_KEY = "MISSING"; |     private static final String MISSING_CLIENT_PING_NAME_KEY = "MISSING"; | ||||||
| 
 | 
 | ||||||
|     public static final Comparator<Tuple<String>> RESOURCE_COMPARATOR = (t1, t2) -> t1._2.compareTo(t2._2); |     public static final Comparator<Tuple<String>> RESOURCE_COMPARATOR = Comparator.comparing(t -> t._2); | ||||||
|     public static final Comparator<Tuple3<String>> RESOURCE_COMPARATOR_TUPLE_3 = (t1, t2) -> t1._2.compareTo(t2._2); |     public static final Comparator<Tuple3<String>> RESOURCE_COMPARATOR_TUPLE_3 = Comparator.comparing(t -> t._2); | ||||||
| 
 | 
 | ||||||
|     public static final EnumSet<EntityType> ENTITY_TYPE_EXCLUDE_MAP = EnumSet.of( |     public static final EnumSet<EntityType> ENTITY_TYPE_EXCLUDE_MAP = EnumSet.of( | ||||||
|             EntityType.ADDITIONAL_ATTRIBUTES, |             EntityType.ADDITIONAL_ATTRIBUTES, | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ public class FieldValidationError { | ||||||
|     public FieldValidationError(final APIMessage apiMessage) { |     public FieldValidationError(final APIMessage apiMessage) { | ||||||
|         this( |         this( | ||||||
|                 apiMessage.messageCode, |                 apiMessage.messageCode, | ||||||
|                 apiMessage.attributes.toArray(new String[apiMessage.attributes.size()])); |                 apiMessage.attributes.toArray(new String[0])); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public FieldValidationError( |     public FieldValidationError( | ||||||
|  | @ -44,7 +44,7 @@ public class FieldValidationError { | ||||||
|             return new String[0]; |             return new String[0]; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this.attributes.toArray(new String[this.attributes.size()]); |         return this.attributes.toArray(new String[0]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,34 +27,34 @@ public interface PageContext { | ||||||
|     Logger log = LoggerFactory.getLogger(PageContext.class); |     Logger log = LoggerFactory.getLogger(PageContext.class); | ||||||
| 
 | 
 | ||||||
|     /** Defines attribute keys that can be used to store attribute values within the page context state */ |     /** Defines attribute keys that can be used to store attribute values within the page context state */ | ||||||
|     public interface AttributeKeys { |     interface AttributeKeys { | ||||||
| 
 | 
 | ||||||
|         public static final String PAGE_TEMPLATE_COMPOSER_NAME = "ATTR_PAGE_TEMPLATE_COMPOSER_NAME"; |         String PAGE_TEMPLATE_COMPOSER_NAME = "ATTR_PAGE_TEMPLATE_COMPOSER_NAME"; | ||||||
| 
 | 
 | ||||||
|         public static final String READ_ONLY = "READ_ONLY"; |         String READ_ONLY = "READ_ONLY"; | ||||||
|         public static final String READ_ONLY_FROM = "READ_ONLY_FROM"; |         String READ_ONLY_FROM = "READ_ONLY_FROM"; | ||||||
| 
 | 
 | ||||||
|         public static final String ENTITY_ID = "ENTITY_ID"; |         String ENTITY_ID = "ENTITY_ID"; | ||||||
|         public static final String PARENT_ENTITY_ID = "PARENT_ENTITY_ID"; |         String PARENT_ENTITY_ID = "PARENT_ENTITY_ID"; | ||||||
|         public static final String ENTITY_TYPE = "ENTITY_TYPE"; |         String ENTITY_TYPE = "ENTITY_TYPE"; | ||||||
|         public static final String PARENT_ENTITY_TYPE = "PARENT_ENTITY_TYPE"; |         String PARENT_ENTITY_TYPE = "PARENT_ENTITY_TYPE"; | ||||||
| 
 | 
 | ||||||
|         public static final String IMPORT_FROM_QUIZ_DATA = "IMPORT_FROM_QUIZ_DATA"; |         String IMPORT_FROM_QUIZ_DATA = "IMPORT_FROM_QUIZ_DATA"; | ||||||
| 
 | 
 | ||||||
|         public static final String COPY_AS_TEMPLATE = "COPY_AS_TEMPLATE"; |         String COPY_AS_TEMPLATE = "COPY_AS_TEMPLATE"; | ||||||
|         public static final String CREATE_FROM_TEMPLATE = "CREATE_FROM_TEMPLATE"; |         String CREATE_FROM_TEMPLATE = "CREATE_FROM_TEMPLATE"; | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** The resource-bundle key of the generic load entity error message. */ |     /** The resource-bundle key of the generic load entity error message. */ | ||||||
|     public static final String GENERIC_LOAD_ERROR_TEXT_KEY = "sebserver.error.get.entity"; |     String GENERIC_LOAD_ERROR_TEXT_KEY = "sebserver.error.get.entity"; | ||||||
|     public static final String GENERIC_REMOVE_ERROR_TEXT_KEY = "sebserver.error.remove.entity"; |     String GENERIC_REMOVE_ERROR_TEXT_KEY = "sebserver.error.remove.entity"; | ||||||
|     public static final String GENERIC_SAVE_ERROR_TEXT_KEY = "sebserver.error.save.entity"; |     String GENERIC_SAVE_ERROR_TEXT_KEY = "sebserver.error.save.entity"; | ||||||
|     public static final String GENERIC_ACTIVATE_ERROR_TEXT_KEY = "sebserver.error.activate.entity"; |     String GENERIC_ACTIVATE_ERROR_TEXT_KEY = "sebserver.error.activate.entity"; | ||||||
|     public static final String GENERIC_IMPORT_ERROR_TEXT_KEY = "sebserver.error.import"; |     String GENERIC_IMPORT_ERROR_TEXT_KEY = "sebserver.error.import"; | ||||||
|     public static final LocTextKey SUCCESS_MSG_TITLE = |     LocTextKey SUCCESS_MSG_TITLE = | ||||||
|             new LocTextKey("sebserver.page.message"); |             new LocTextKey("sebserver.page.message"); | ||||||
|     public static final LocTextKey UNEXPECTED_ERROR_KEY = |     LocTextKey UNEXPECTED_ERROR_KEY = | ||||||
|             new LocTextKey("sebserver.error.action.unexpected.message"); |             new LocTextKey("sebserver.error.action.unexpected.message"); | ||||||
| 
 | 
 | ||||||
|     /** Get the I18nSupport service |     /** Get the I18nSupport service | ||||||
|  | @ -84,11 +84,11 @@ public interface PageContext { | ||||||
| 
 | 
 | ||||||
|     /** Get a copy of this PageContext. |     /** Get a copy of this PageContext. | ||||||
|      * |      * | ||||||
|      * @return */ |      * @return a deep copy of this PageContext */ | ||||||
|     PageContext copy(); |     PageContext copy(); | ||||||
| 
 | 
 | ||||||
|     /** Create a copy of this PageContext with a new parent Composite. |     /** Create a copy of this PageContext with a new parent Composite. | ||||||
|      * The implementation should take care of the imutability of PageContext and return a copy with the new parent |      * The implementation should take care of the immutability of PageContext and return a copy with the new parent | ||||||
|      * by leave this PageContext as is. |      * by leave this PageContext as is. | ||||||
|      * |      * | ||||||
|      * @param parent the new parent Composite |      * @param parent the new parent Composite | ||||||
|  | @ -97,15 +97,15 @@ public interface PageContext { | ||||||
| 
 | 
 | ||||||
|     /** Create a copy of this PageContext with and additionally page context attributes. |     /** Create a copy of this PageContext with and additionally page context attributes. | ||||||
|      * The additionally page context attributes will get merged with them already defined |      * The additionally page context attributes will get merged with them already defined | ||||||
|      * The implementation should take care of the imutability of PageContext and return a copy with the merge |      * The implementation should take care of the immutability of PageContext and return a copy with the merge | ||||||
|      * by leave this and the given PageContext as is. |      * by leave this and the given PageContext as is. | ||||||
|      * |      * | ||||||
|      * @param attributes additionally page context attributes. |      * @param otherContext the other PageContext to copy the attributes from | ||||||
|      * @return a copy of this PageContext with with and additionally page context attributes. */ |      * @return a copy of this PageContext with with and additionally page context attributes. */ | ||||||
|     PageContext copyOfAttributes(PageContext otherContext); |     PageContext copyOfAttributes(PageContext otherContext); | ||||||
| 
 | 
 | ||||||
|     /** Adds the specified attribute to the existing page context attributes. |     /** Adds the specified attribute to the existing page context attributes. | ||||||
|      * The implementation should take care of the imutability of PageContext and return a copy |      * The implementation should take care of the immutability of PageContext and return a copy | ||||||
|      * by leave this PageContext as is. |      * by leave this PageContext as is. | ||||||
|      * |      * | ||||||
|      * @param key the key of the attribute |      * @param key the key of the attribute | ||||||
|  | @ -162,7 +162,7 @@ public interface PageContext { | ||||||
| 
 | 
 | ||||||
|     /** Create a copy of this PageContext and resets both entity keys attributes, the base and the parent EntityKey |     /** Create a copy of this PageContext and resets both entity keys attributes, the base and the parent EntityKey | ||||||
|      * |      * | ||||||
|      * @return copy of this PageContext with reseted EntityKey attributes (base and parent) */ |      * @return copy of this PageContext with reset EntityKey attributes (base and parent) */ | ||||||
|     PageContext clearEntityKeys(); |     PageContext clearEntityKeys(); | ||||||
| 
 | 
 | ||||||
|     /** Indicates if an attribute with the specified name exists within this PageContext |     /** Indicates if an attribute with the specified name exists within this PageContext | ||||||
|  | @ -181,7 +181,7 @@ public interface PageContext { | ||||||
|      * block that will be executed on users OK selection. |      * block that will be executed on users OK selection. | ||||||
|      * |      * | ||||||
|      * @param confirmMessage the localized confirm message key |      * @param confirmMessage the localized confirm message key | ||||||
|      * @param onOK callback code block that will be called on users selection */ |      * @param callback callback code block that will be called on users selection */ | ||||||
|     void applyConfirmDialog(LocTextKey confirmMessage, final Consumer<Boolean> callback); |     void applyConfirmDialog(LocTextKey confirmMessage, final Consumer<Boolean> callback); | ||||||
| 
 | 
 | ||||||
|     /** This can be used to forward to a defined page. |     /** This can be used to forward to a defined page. | ||||||
|  |  | ||||||
|  | @ -8,8 +8,12 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.page; | package ch.ethz.seb.sebserver.gui.service.page; | ||||||
| 
 | 
 | ||||||
|  | /** Defines a global SEB Server page */ | ||||||
| public interface PageDefinition { | public interface PageDefinition { | ||||||
| 
 | 
 | ||||||
|  |     /** Get the type class of the TemplateComposer that composes the page. | ||||||
|  |      * | ||||||
|  |      * @return the type class of the TemplateComposer that composes the page. */ | ||||||
|     Class<? extends TemplateComposer> composer(); |     Class<? extends TemplateComposer> composer(); | ||||||
| 
 | 
 | ||||||
|     PageContext applyPageContext(PageContext pageContext); |     PageContext applyPageContext(PageContext pageContext); | ||||||
|  |  | ||||||
|  | @ -363,7 +363,7 @@ public interface PageService { | ||||||
|         return content; |         return content; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** Used to update the crolledComposite when some if its content has dynamically changed |     /** Used to update the scrolledComposite when some if its content has dynamically changed | ||||||
|      * its dimensions. |      * its dimensions. | ||||||
|      * |      * | ||||||
|      * @param composite The Component that changed its dimensions */ |      * @param composite The Component that changed its dimensions */ | ||||||
|  |  | ||||||
|  | @ -22,9 +22,9 @@ public interface PageStateDefinition { | ||||||
| 
 | 
 | ||||||
|     Type type(); |     Type type(); | ||||||
| 
 | 
 | ||||||
|     public Class<? extends TemplateComposer> contentPaneComposer(); |     Class<? extends TemplateComposer> contentPaneComposer(); | ||||||
| 
 | 
 | ||||||
|     public Class<? extends TemplateComposer> actionPaneComposer(); |     Class<? extends TemplateComposer> actionPaneComposer(); | ||||||
| 
 | 
 | ||||||
|     Activity activityAnchor(); |     Activity activityAnchor(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,12 +8,20 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.page; | package ch.ethz.seb.sebserver.gui.service.page; | ||||||
| 
 | 
 | ||||||
|  | /** interface defining a RAP page template composer */ | ||||||
| public interface TemplateComposer { | public interface TemplateComposer { | ||||||
| 
 | 
 | ||||||
|  |     /** Validate given PageContext for completeness to compose a specific  TemplateComposer implementation | ||||||
|  |      *  Default returns always true. | ||||||
|  |      * @param pageContext The PageContext instance to check | ||||||
|  |      * @return true if the PageContext contains all mandatory data to compose this page template */ | ||||||
|     default boolean validate(final PageContext pageContext) { |     default boolean validate(final PageContext pageContext) { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** Compose a specific page template for the given PageContext | ||||||
|  |      * | ||||||
|  |      * @param pageContext The PageContext instance */ | ||||||
|     void compose(PageContext pageContext); |     void compose(PageContext pageContext); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -156,7 +156,7 @@ public class DefaultPageLayout implements TemplateComposer { | ||||||
|                 logoutSuccess.open(null); |                 logoutSuccess.open(null); | ||||||
| 
 | 
 | ||||||
|                 // TODO Try to invalidate RWT's user session. |                 // TODO Try to invalidate RWT's user session. | ||||||
|                 //      This seems to be more difficult then expected and just invalidate the HttpSession dosn't work |                 //      This seems to be more difficult then expected and just invalidate the HttpSession doesn't work | ||||||
|                 //      Try to send a redirect JSON to the client: https://bugs.eclipse.org/bugs/show_bug.cgi?id=388249 |                 //      Try to send a redirect JSON to the client: https://bugs.eclipse.org/bugs/show_bug.cgi?id=388249 | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  | @ -347,12 +347,8 @@ public class DefaultPageLayout implements TemplateComposer { | ||||||
|             final Display display = pageContext.getShell().getDisplay(); |             final Display display = pageContext.getShell().getDisplay(); | ||||||
|             final Image image = new Image(display, input); |             final Image image = new Image(display, input); | ||||||
|             final Rectangle imageBounds = image.getBounds(); |             final Rectangle imageBounds = image.getBounds(); | ||||||
|             final int width = (imageBounds.width > LOGO_IMAGE_MAX_WIDTH) |             final int width = Math.min(imageBounds.width, LOGO_IMAGE_MAX_WIDTH); | ||||||
|                     ? LOGO_IMAGE_MAX_WIDTH |             final int height = Math.min(imageBounds.height, LOGO_IMAGE_MAX_HEIGHT); | ||||||
|                     : imageBounds.width; |  | ||||||
|             final int height = (imageBounds.height > LOGO_IMAGE_MAX_HEIGHT) |  | ||||||
|                     ? LOGO_IMAGE_MAX_HEIGHT |  | ||||||
|                     : imageBounds.height; |  | ||||||
|             final ImageData imageData = image.getImageData().scaledTo(width, height); |             final ImageData imageData = image.getImageData().scaledTo(width, height); | ||||||
| 
 | 
 | ||||||
|             logo.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage"); |             logo.setData(RWT.CUSTOM_VARIANT, "bgLogoNoImage"); | ||||||
|  |  | ||||||
|  | @ -89,7 +89,7 @@ public class ModalInputDialog<T> extends Dialog { | ||||||
| 
 | 
 | ||||||
|         open( |         open( | ||||||
|                 title, |                 title, | ||||||
|                 (Predicate<T>) t -> true, |                 t -> true, | ||||||
|                 () -> { |                 () -> { | ||||||
|                 }, contentComposer); |                 }, contentComposer); | ||||||
|     } |     } | ||||||
|  | @ -130,7 +130,7 @@ public class ModalInputDialog<T> extends Dialog { | ||||||
|         gridData.widthHint = this.dialogWidth; |         gridData.widthHint = this.dialogWidth; | ||||||
|         main.setLayoutData(gridData); |         main.setLayoutData(gridData); | ||||||
| 
 | 
 | ||||||
|         final Supplier<T> valueSuppier = contentComposer.compose(main); |         final Supplier<T> valueSupplier = contentComposer.compose(main); | ||||||
|         gridData.heightHint = calcDialogHeight(main); |         gridData.heightHint = calcDialogHeight(main); | ||||||
| 
 | 
 | ||||||
|         final Button ok = this.widgetFactory.buttonLocalized(shell, OK_TEXT_KEY); |         final Button ok = this.widgetFactory.buttonLocalized(shell, OK_TEXT_KEY); | ||||||
|  | @ -138,8 +138,8 @@ public class ModalInputDialog<T> extends Dialog { | ||||||
|         data.widthHint = this.buttonWidth; |         data.widthHint = this.buttonWidth; | ||||||
|         ok.setLayoutData(data); |         ok.setLayoutData(data); | ||||||
|         ok.addListener(SWT.Selection, event -> { |         ok.addListener(SWT.Selection, event -> { | ||||||
|             if (valueSuppier != null) { |             if (valueSupplier != null) { | ||||||
|                 final T result = valueSuppier.get(); |                 final T result = valueSupplier.get(); | ||||||
|                 if (callback.test(result)) { |                 if (callback.test(result)) { | ||||||
|                     shell.close(); |                     shell.close(); | ||||||
|                 } |                 } | ||||||
|  | @ -192,9 +192,7 @@ public class ModalInputDialog<T> extends Dialog { | ||||||
|         final GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); |         final GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); | ||||||
|         data.widthHint = this.buttonWidth; |         data.widthHint = this.buttonWidth; | ||||||
|         close.setLayoutData(data); |         close.setLayoutData(data); | ||||||
|         close.addListener(SWT.Selection, event -> { |         close.addListener(SWT.Selection, event -> shell.close()); | ||||||
|             shell.close(); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         finishUp(shell); |         finishUp(shell); | ||||||
|     } |     } | ||||||
|  | @ -216,10 +214,7 @@ public class ModalInputDialog<T> extends Dialog { | ||||||
|         final int availableHeight = (displayHeight < actualHeight + 100) |         final int availableHeight = (displayHeight < actualHeight + 100) | ||||||
|                 ? displayHeight - 100 |                 ? displayHeight - 100 | ||||||
|                 : actualHeight; |                 : actualHeight; | ||||||
|         final int height = (availableHeight > this.dialogHeight) |         return Math.min(availableHeight, this.dialogHeight); | ||||||
|                 ? this.dialogHeight |  | ||||||
|                 : availableHeight; |  | ||||||
|         return height; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -118,8 +118,7 @@ public class PageContextImpl implements PageContext { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public PageContext withAttribute(final String key, final String value) { |     public PageContext withAttribute(final String key, final String value) { | ||||||
|         final Map<String, String> attrs = new HashMap<>(); |         final Map<String, String> attrs = new HashMap<>(this.attributes); | ||||||
|         attrs.putAll(this.attributes); |  | ||||||
|         attrs.put(key, value); |         attrs.put(key, value); | ||||||
|         return new PageContextImpl( |         return new PageContextImpl( | ||||||
|                 this.i18nSupport, |                 this.i18nSupport, | ||||||
|  | @ -136,11 +135,7 @@ public class PageContextImpl implements PageContext { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public String getAttribute(final String name, final String def) { |     public String getAttribute(final String name, final String def) { | ||||||
|         if (this.attributes.containsKey(name)) { |         return this.attributes.getOrDefault(name, def); | ||||||
|             return this.attributes.get(name); |  | ||||||
|         } else { |  | ||||||
|             return def; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -203,8 +198,7 @@ public class PageContextImpl implements PageContext { | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public PageContext removeAttribute(final String name) { |     public PageContext removeAttribute(final String name) { | ||||||
|         final Map<String, String> attrs = new HashMap<>(); |         final Map<String, String> attrs = new HashMap<>(this.attributes); | ||||||
|         attrs.putAll(this.attributes); |  | ||||||
|         attrs.remove(name); |         attrs.remove(name); | ||||||
|         return new PageContextImpl( |         return new PageContextImpl( | ||||||
|                 this.i18nSupport, |                 this.i18nSupport, | ||||||
|  | @ -333,7 +327,7 @@ public class PageContextImpl implements PageContext { | ||||||
|                     this.onOK.accept(true); |                     this.onOK.accept(true); | ||||||
|                 } catch (final Exception e) { |                 } catch (final Exception e) { | ||||||
|                     log.error( |                     log.error( | ||||||
|                             "Unexpected on confirm callback execution. This should not happen, plase secure the given onOK Runnable", |                             "Unexpected on confirm callback execution. This should not happen, please secure the given onOK Runnable", | ||||||
|                             e); |                             e); | ||||||
|                     this.onOK.accept(false); |                     this.onOK.accept(false); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -227,7 +227,7 @@ public class PageServiceImpl implements PageService { | ||||||
|                 final int dependencies = (int) entities.stream() |                 final int dependencies = (int) entities.stream() | ||||||
|                         .flatMap(entity -> { |                         .flatMap(entity -> { | ||||||
|                             final RestCall<Set<EntityKey>>.RestCallBuilder builder = |                             final RestCall<Set<EntityKey>>.RestCallBuilder builder = | ||||||
|                                     restService.<Set<EntityKey>>getBuilder( |                                     restService.getBuilder( | ||||||
|                                             entity.entityType(), |                                             entity.entityType(), | ||||||
|                                             CallType.GET_DEPENDENCIES); |                                             CallType.GET_DEPENDENCIES); | ||||||
| 
 | 
 | ||||||
|  | @ -366,7 +366,7 @@ public class PageServiceImpl implements PageService { | ||||||
|             final boolean logoutSuccessful = this.currentUser.logout(); |             final boolean logoutSuccessful = this.currentUser.logout(); | ||||||
| 
 | 
 | ||||||
|             if (!logoutSuccessful) { |             if (!logoutSuccessful) { | ||||||
|                 log.warn("Failed to logout. See logfiles for more information"); |                 log.warn("Failed to logout. See log-files for more information"); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|  |  | ||||||
|  | @ -78,7 +78,7 @@ public class ServerPushService { | ||||||
|                         } catch (final Exception e) { |                         } catch (final Exception e) { | ||||||
|                             log.warn( |                             log.warn( | ||||||
|                                     "Failed to update on Server Push Session {}. It seems that the UISession is not available anymore. " |                                     "Failed to update on Server Push Session {}. It seems that the UISession is not available anymore. " | ||||||
|                                             + "This may source from a connection interruption.", |                                             + "This may source from a connection interruption. cause: {}", | ||||||
|                                     Thread.currentThread().getName(), e.getMessage()); |                                     Thread.currentThread().getName(), e.getMessage()); | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|  |  | ||||||
|  | @ -8,16 +8,9 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.remote.download; | package ch.ethz.seb.sebserver.gui.service.remote.download; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import ch.ethz.seb.sebserver.gbl.Constants; | ||||||
| import java.util.Collection; | import ch.ethz.seb.sebserver.gbl.api.API; | ||||||
| import java.util.Map; | import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | ||||||
| import java.util.function.Function; |  | ||||||
| import java.util.stream.Collectors; |  | ||||||
| 
 |  | ||||||
| import javax.servlet.ServletException; |  | ||||||
| import javax.servlet.http.HttpServletRequest; |  | ||||||
| import javax.servlet.http.HttpServletResponse; |  | ||||||
| 
 |  | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.eclipse.rap.rwt.RWT; | import org.eclipse.rap.rwt.RWT; | ||||||
| import org.eclipse.rap.rwt.service.ServiceHandler; | import org.eclipse.rap.rwt.service.ServiceHandler; | ||||||
|  | @ -26,10 +19,14 @@ import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.context.annotation.Lazy; | import org.springframework.context.annotation.Lazy; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.Constants; | import javax.servlet.http.HttpServletRequest; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.API; | import javax.servlet.http.HttpServletResponse; | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | import java.util.Collection; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.function.Function; | ||||||
|  | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
|  | /** Implements a eclipse RAP ServiceHandler to handle downloads */ | ||||||
| @Lazy | @Lazy | ||||||
| @Service | @Service | ||||||
| @GuiProfile | @GuiProfile | ||||||
|  | @ -54,7 +51,7 @@ public class DownloadService implements ServiceHandler { | ||||||
|     @Override |     @Override | ||||||
|     public void service( |     public void service( | ||||||
|             final HttpServletRequest request, |             final HttpServletRequest request, | ||||||
|             final HttpServletResponse response) throws IOException, ServletException { |             final HttpServletResponse response) { | ||||||
| 
 | 
 | ||||||
|         log.debug("Received download service request: {}", request.getRequestURI()); |         log.debug("Received download service request: {}", request.getRequestURI()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,8 +11,13 @@ package ch.ethz.seb.sebserver.gui.service.remote.download; | ||||||
| import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||||
| 
 | 
 | ||||||
|  | /** Interface defining a service to handle downloads */ | ||||||
| public interface DownloadServiceHandler { | public interface DownloadServiceHandler { | ||||||
| 
 | 
 | ||||||
|  |     /** Process a requested download | ||||||
|  |      * | ||||||
|  |      * @param request The download HttpServletRequest | ||||||
|  |      * @param response the response to send the download to */ | ||||||
|     void processDownload(final HttpServletRequest request, final HttpServletResponse response); |     void processDownload(final HttpServletRequest request, final HttpServletResponse response); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ public class SebClientConfigDownload extends AbstractDownloadServiceHandler { | ||||||
|             IOUtils.copyLarge(input, downloadOut); |             IOUtils.copyLarge(input, downloadOut); | ||||||
|         } catch (final IOException e) { |         } catch (final IOException e) { | ||||||
|             log.error( |             log.error( | ||||||
|                     "Unexpected error while streaming incomming config data from web-service to output-stream of download response: ", |                     "Unexpected error while streaming incoming config data from web-service to output-stream of download response: ", | ||||||
|                     e); |                     e); | ||||||
|         } finally { |         } finally { | ||||||
|             try { |             try { | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ public class SebExamConfigDownload extends AbstractDownloadServiceHandler { | ||||||
|             IOUtils.copyLarge(input, downloadOut); |             IOUtils.copyLarge(input, downloadOut); | ||||||
|         } catch (final IOException e) { |         } catch (final IOException e) { | ||||||
|             log.error( |             log.error( | ||||||
|                     "Unexpected error while streaming incomming config data from web-service to output-stream of download response: ", |                     "Unexpected error while streaming incoming config data from web-service to output-stream of download response: ", | ||||||
|                     e); |                     e); | ||||||
|         } finally { |         } finally { | ||||||
|             try { |             try { | ||||||
|  |  | ||||||
|  | @ -48,7 +48,7 @@ public class SebExamConfigPlaintextDownload extends AbstractDownloadServiceHandl | ||||||
|             IOUtils.copyLarge(input, downloadOut); |             IOUtils.copyLarge(input, downloadOut); | ||||||
|         } catch (final IOException e) { |         } catch (final IOException e) { | ||||||
|             log.error( |             log.error( | ||||||
|                     "Unexpected error while streaming incomming config data from web-service to output-stream of download response: ", |                     "Unexpected error while streaming incoming config data from web-service to output-stream of download response: ", | ||||||
|                     e); |                     e); | ||||||
|         } finally { |         } finally { | ||||||
|             try { |             try { | ||||||
|  |  | ||||||
|  | @ -31,9 +31,7 @@ public abstract class AbstractExportCall extends RestCall<InputStream> { | ||||||
|     @Override |     @Override | ||||||
|     protected Result<InputStream> exchange(final RestCallBuilder builder) { |     protected Result<InputStream> exchange(final RestCallBuilder builder) { | ||||||
| 
 | 
 | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> builder | ||||||
| 
 |  | ||||||
|             return builder |  | ||||||
|                 .getRestTemplate() |                 .getRestTemplate() | ||||||
|                 .execute( |                 .execute( | ||||||
|                         builder.buildURI(), |                         builder.buildURI(), | ||||||
|  | @ -41,9 +39,7 @@ public abstract class AbstractExportCall extends RestCall<InputStream> { | ||||||
|                         (final ClientHttpRequest requestCallback) -> { |                         (final ClientHttpRequest requestCallback) -> { | ||||||
|                         }, |                         }, | ||||||
|                         response -> IOUtils.toBufferedInputStream(response.getBody()), |                         response -> IOUtils.toBufferedInputStream(response.getBody()), | ||||||
|                             builder.getURIVariables()); |                         builder.getURIVariables())); | ||||||
| 
 |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,10 +8,18 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; | package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; | ||||||
| 
 | 
 | ||||||
|  | /** Defines a form binding to get form parameter and values either in JSON format | ||||||
|  |  *  or as form-url-encoded string */ | ||||||
| public interface FormBinding { | public interface FormBinding { | ||||||
| 
 | 
 | ||||||
|  |     /** Get the form parameter and values in JSON format | ||||||
|  |      * | ||||||
|  |      * @return the form parameter and values in JSON format */ | ||||||
|     String getFormAsJson(); |     String getFormAsJson(); | ||||||
| 
 | 
 | ||||||
|  |     /** Get the form parameter and values in form-url-encoded string format. | ||||||
|  |      * | ||||||
|  |      * @return the form parameter and values in form-url-encoded string format.*/ | ||||||
|     String getFormUrlEncoded(); |     String getFormUrlEncoded(); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -8,14 +8,18 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; | package ch.ethz.seb.sebserver.gui.service.remote.webservice.api; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import ch.ethz.seb.sebserver.gbl.Constants; | ||||||
| import java.io.InputStream; | import ch.ethz.seb.sebserver.gbl.api.APIMessage; | ||||||
| import java.util.Arrays; | import ch.ethz.seb.sebserver.gbl.api.EntityType; | ||||||
| import java.util.HashMap; | import ch.ethz.seb.sebserver.gbl.api.JSONMapper; | ||||||
| import java.util.List; | import ch.ethz.seb.sebserver.gbl.model.Entity; | ||||||
| import java.util.Map; | import ch.ethz.seb.sebserver.gbl.model.Page; | ||||||
| import java.util.function.Function; | import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; | ||||||
| 
 | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
|  | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
|  | import com.fasterxml.jackson.core.JsonParseException; | ||||||
|  | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
|  | import com.fasterxml.jackson.core.type.TypeReference; | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | @ -32,20 +36,13 @@ import org.springframework.web.client.RestClientResponseException; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| import org.springframework.web.util.UriComponentsBuilder; | import org.springframework.web.util.UriComponentsBuilder; | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.core.JsonParseException; | import java.io.IOException; | ||||||
| import com.fasterxml.jackson.core.JsonProcessingException; | import java.io.InputStream; | ||||||
| import com.fasterxml.jackson.core.type.TypeReference; | import java.util.Arrays; | ||||||
| import com.fasterxml.jackson.databind.JsonMappingException; | import java.util.HashMap; | ||||||
| 
 | import java.util.List; | ||||||
| import ch.ethz.seb.sebserver.gbl.Constants; | import java.util.Map; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.APIMessage; | import java.util.function.Function; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.api.JSONMapper; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.Entity; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.Page; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.PageSortOrder; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; |  | ||||||
| 
 | 
 | ||||||
| public abstract class RestCall<T> { | public abstract class RestCall<T> { | ||||||
| 
 | 
 | ||||||
|  | @ -173,7 +170,7 @@ public abstract class RestCall<T> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Result<T> handleRestCallError(final ResponseEntity<String> responseEntity) |     private Result<T> handleRestCallError(final ResponseEntity<String> responseEntity) | ||||||
|             throws IOException, JsonParseException, JsonMappingException { |             throws IOException { | ||||||
| 
 | 
 | ||||||
|         final RestCallError restCallError = |         final RestCallError restCallError = | ||||||
|                 new RestCallError("Response Entity: " + responseEntity.toString()); |                 new RestCallError("Response Entity: " + responseEntity.toString()); | ||||||
|  | @ -225,6 +222,7 @@ public abstract class RestCall<T> { | ||||||
|             this.uriComponentsBuilder = builder.uriComponentsBuilder; |             this.uriComponentsBuilder = builder.uriComponentsBuilder; | ||||||
|             this.httpHeaders = builder.httpHeaders; |             this.httpHeaders = builder.httpHeaders; | ||||||
|             this.body = builder.body; |             this.body = builder.body; | ||||||
|  |             this.streamingBody = builder.streamingBody; | ||||||
|             this.queryParams = new LinkedMultiValueMap<>(builder.queryParams); |             this.queryParams = new LinkedMultiValueMap<>(builder.queryParams); | ||||||
|             this.uriVariables = new HashMap<>(builder.uriVariables); |             this.uriVariables = new HashMap<>(builder.uriVariables); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -49,9 +49,7 @@ public class RestCallError extends RuntimeException implements APIMessageError { | ||||||
|     public boolean isFieldValidationError() { |     public boolean isFieldValidationError() { | ||||||
|         return this.errors |         return this.errors | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(error -> APIMessage.ErrorMessage.FIELD_VALIDATION.isOf(error)) |                 .anyMatch(APIMessage.ErrorMessage.FIELD_VALIDATION::isOf); | ||||||
|                 .findFirst() |  | ||||||
|                 .isPresent(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ public interface RestService { | ||||||
|      * NOTE not all RestCall can be get within this method. Only the ones that have a defined CallType |      * NOTE not all RestCall can be get within this method. Only the ones that have a defined CallType | ||||||
|      * |      * | ||||||
|      * @param entityType The EntityType of the RestCall |      * @param entityType The EntityType of the RestCall | ||||||
|      * @param callType The CallType of the RestCall (not UNDEFINDED) |      * @param callType The CallType of the RestCall (not UNDEFINED) | ||||||
|      * @return RestCall instance */ |      * @return RestCall instance */ | ||||||
|     <T> RestCall<T> getRestCall(EntityType entityType, CallType callType); |     <T> RestCall<T> getRestCall(EntityType entityType, CallType callType); | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,7 @@ public interface RestService { | ||||||
|     /** Get a certain RestCallBuilder by EntityType and CallType. |     /** Get a certain RestCallBuilder by EntityType and CallType. | ||||||
|      * |      * | ||||||
|      * @param entityType The EntityType of the RestCall to get a builder for |      * @param entityType The EntityType of the RestCall to get a builder for | ||||||
|      * @param callType The CallType of the RestCall to get a builder for (not UNDEFINDED) |      * @param callType The CallType of the RestCall to get a builder for (not UNDEFINED) | ||||||
|      * @return RestCallBuilder instance to build a dedicated call and execute it */ |      * @return RestCallBuilder instance to build a dedicated call and execute it */ | ||||||
|     <T> RestCall<T>.RestCallBuilder getBuilder( |     <T> RestCall<T>.RestCallBuilder getBuilder( | ||||||
|             EntityType entityType, |             EntityType entityType, | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | ||||||
| import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; | import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| @Lazy | @Lazy | ||||||
| @Component | @Component | ||||||
| @GuiProfile | @GuiProfile | ||||||
|  |  | ||||||
|  | @ -119,17 +119,15 @@ public class CurrentUser { | ||||||
|                 return userInfo |                 return userInfo | ||||||
|                         .getRoles() |                         .getRoles() | ||||||
|                         .stream() |                         .stream() | ||||||
|                         .map(roleName -> UserRole.valueOf(roleName)) |                         .map(UserRole::valueOf) | ||||||
|                         .map(role -> new RoleTypeKey(entityType, role)) |                         .map(role -> new RoleTypeKey(entityType, role)) | ||||||
|                         .map(key -> this.privileges.get(key)) |                         .map(key -> this.privileges.get(key)) | ||||||
|                         .filter(priv -> (priv != null) && priv.hasGrant( |                         .anyMatch(privilege -> (privilege != null) && privilege.hasGrant( | ||||||
|                                 userInfo.uuid, |                                 userInfo.uuid, | ||||||
|                                 userInfo.institutionId, |                                 userInfo.institutionId, | ||||||
|                                 privilegeType, |                                 privilegeType, | ||||||
|                                 institutionId, |                                 institutionId, | ||||||
|                                 ownerId)) |                                 ownerId)); | ||||||
|                         .findFirst() |  | ||||||
|                         .isPresent(); |  | ||||||
|             } catch (final Exception e) { |             } catch (final Exception e) { | ||||||
|                 log.error("Failed to verify privilege: PrivilegeType {} EntityType {}", |                 log.error("Failed to verify privilege: PrivilegeType {} EntityType {}", | ||||||
|                         privilegeType, entityType, e); |                         privilegeType, entityType, e); | ||||||
|  | @ -149,17 +147,15 @@ public class CurrentUser { | ||||||
|                 final UserInfo userInfo = get(); |                 final UserInfo userInfo = get(); | ||||||
|                 return userInfo.getRoles() |                 return userInfo.getRoles() | ||||||
|                         .stream() |                         .stream() | ||||||
|                         .map(roleName -> UserRole.valueOf(roleName)) |                         .map(UserRole::valueOf) | ||||||
|                         .map(role -> new RoleTypeKey(entityType, role)) |                         .map(role -> new RoleTypeKey(entityType, role)) | ||||||
|                         .map(key -> this.privileges.get(key)) |                         .map(key -> this.privileges.get(key)) | ||||||
|                         .filter(priv -> (priv != null) && priv.hasGrant( |                         .anyMatch(privilege -> (privilege != null) && privilege.hasGrant( | ||||||
|                                 userInfo.uuid, |                                 userInfo.uuid, | ||||||
|                                 userInfo.institutionId, |                                 userInfo.institutionId, | ||||||
|                                 privilegeType, |                                 privilegeType, | ||||||
|                                 grantEntity.getInstitutionId(), |                                 grantEntity.getInstitutionId(), | ||||||
|                                 grantEntity.getOwnerId())) |                                 grantEntity.getOwnerId())); | ||||||
|                         .findFirst() |  | ||||||
|                         .isPresent(); |  | ||||||
|             } catch (final Exception e) { |             } catch (final Exception e) { | ||||||
|                 log.error("Failed to verify privilege: PrivilegeType {} EntityType {}", |                 log.error("Failed to verify privilege: PrivilegeType {} EntityType {}", | ||||||
|                         privilegeType, entityType, e); |                         privilegeType, entityType, e); | ||||||
|  | @ -234,9 +230,9 @@ public class CurrentUser { | ||||||
|                     if (privileges != null) { |                     if (privileges != null) { | ||||||
|                         this.privileges = privileges |                         this.privileges = privileges | ||||||
|                                 .stream() |                                 .stream() | ||||||
|                                 .reduce(new HashMap<RoleTypeKey, Privilege>(), |                                 .reduce(new HashMap<>(), | ||||||
|                                         (map, priv) -> { |                                         (map, privilege) -> { | ||||||
|                                             map.put(priv.roleTypeKey, priv); |                                             map.put(privilege.roleTypeKey, privilege); | ||||||
|                                             return map; |                                             return map; | ||||||
|                                         }, |                                         }, | ||||||
|                                         (map1, map2) -> { |                                         (map1, map2) -> { | ||||||
|  |  | ||||||
|  | @ -8,15 +8,12 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth; | package ch.ethz.seb.sebserver.gui.service.remote.webservice.auth; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; | ||||||
| import java.net.URI; | import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; | ||||||
| import java.nio.charset.Charset; | import ch.ethz.seb.sebserver.gbl.model.user.UserRole; | ||||||
| import java.util.Arrays; | import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | ||||||
| import java.util.Collections; | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
| import java.util.List; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
| 
 |  | ||||||
| import javax.servlet.http.HttpSession; |  | ||||||
| 
 |  | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
|  | @ -44,12 +41,13 @@ import org.springframework.web.client.ResponseExtractor; | ||||||
| import org.springframework.web.client.RestClientException; | import org.springframework.web.client.RestClientException; | ||||||
| import org.springframework.web.client.RestTemplate; | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.ClientHttpRequestFactoryService; | import javax.servlet.http.HttpSession; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.user.UserInfo; | import java.io.IOException; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.user.UserRole; | import java.net.URI; | ||||||
| import ch.ethz.seb.sebserver.gbl.profile.GuiProfile; | import java.nio.charset.StandardCharsets; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | import java.util.Arrays; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import java.util.Collections; | ||||||
|  | import java.util.List; | ||||||
| 
 | 
 | ||||||
| @Lazy | @Lazy | ||||||
| @Component | @Component | ||||||
|  | @ -171,7 +169,7 @@ public class OAuth2AuthorizationContextHolder implements AuthorizationContextHol | ||||||
|             this.restTemplate.setErrorHandler(new ErrorHandler(this.resource)); |             this.restTemplate.setErrorHandler(new ErrorHandler(this.resource)); | ||||||
|             this.restTemplate |             this.restTemplate | ||||||
|                     .getMessageConverters() |                     .getMessageConverters() | ||||||
|                     .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8"))); |                     .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); | ||||||
| 
 | 
 | ||||||
|             this.revokeTokenURI = webserviceURIService.getOAuthRevokeTokenURI(); |             this.revokeTokenURI = webserviceURIService.getOAuthRevokeTokenURI(); | ||||||
|             this.currentUserURI = webserviceURIService.getCurrentUserRequestURI(); |             this.currentUserURI = webserviceURIService.getCurrentUserRequestURI(); | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ public interface SEBServerAuthorizationContext { | ||||||
|      * |      * | ||||||
|      * @param username the username for login |      * @param username the username for login | ||||||
|      * @param password the password for login |      * @param password the password for login | ||||||
|      * @return */ |      * @return true if login was successful, false if no */ | ||||||
|     boolean login(String username, CharSequence password); |     boolean login(String username, CharSequence password); | ||||||
| 
 | 
 | ||||||
|     /** Requests a logout on SEB Server webservice if a user is currently logged in |     /** Requests a logout on SEB Server webservice if a user is currently logged in | ||||||
|  |  | ||||||
|  | @ -14,29 +14,29 @@ public class WebserviceConnectionData { | ||||||
| 
 | 
 | ||||||
|     final String id; |     final String id; | ||||||
|     final String webserviceProtocol; |     final String webserviceProtocol; | ||||||
|     final String webserviceServerAdress; |     final String webserviceServerAddress; | ||||||
|     final String webserviceServerPort; |     final String webserviceServerPort; | ||||||
|     final String webserviceAPIPath; |     final String webserviceAPIPath; | ||||||
|     final String webserviceServerAddress; |     final String webserviceServerURL; | ||||||
| 
 | 
 | ||||||
|     private final UriComponentsBuilder webserviceURIBuilder; |     private final UriComponentsBuilder webserviceURIBuilder; | ||||||
| 
 | 
 | ||||||
|     protected WebserviceConnectionData( |     protected WebserviceConnectionData( | ||||||
|             final String id, |             final String id, | ||||||
|             final String webserviceProtocol, |             final String webserviceProtocol, | ||||||
|             final String webserviceServerAdress, |             final String webserviceServerAddress, | ||||||
|             final String webserviceServerPort, |             final String webserviceServerPort, | ||||||
|             final String webserviceAPIPath) { |             final String webserviceAPIPath) { | ||||||
| 
 | 
 | ||||||
|         this.id = id; |         this.id = id; | ||||||
|         this.webserviceProtocol = webserviceProtocol; |         this.webserviceProtocol = webserviceProtocol; | ||||||
|         this.webserviceServerAdress = webserviceServerAdress; |         this.webserviceServerAddress = webserviceServerAddress; | ||||||
|         this.webserviceServerPort = webserviceServerPort; |         this.webserviceServerPort = webserviceServerPort; | ||||||
|         this.webserviceAPIPath = webserviceAPIPath; |         this.webserviceAPIPath = webserviceAPIPath; | ||||||
| 
 | 
 | ||||||
|         this.webserviceServerAddress = webserviceProtocol + "://" + webserviceServerAdress + ":" + webserviceServerPort; |         this.webserviceServerURL = webserviceProtocol + "://" + webserviceServerAddress + ":" + webserviceServerPort; | ||||||
|         this.webserviceURIBuilder = UriComponentsBuilder |         this.webserviceURIBuilder = UriComponentsBuilder | ||||||
|                 .fromHttpUrl(webserviceProtocol + "://" + webserviceServerAdress) |                 .fromHttpUrl(webserviceProtocol + "://" + webserviceServerAddress) | ||||||
|                 .port(webserviceServerPort) |                 .port(webserviceServerPort) | ||||||
|                 .path(webserviceAPIPath); |                 .path(webserviceAPIPath); | ||||||
|     } |     } | ||||||
|  | @ -49,8 +49,8 @@ public class WebserviceConnectionData { | ||||||
|         return this.webserviceProtocol; |         return this.webserviceProtocol; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public String getWebserviceServerAdress() { |     public String getWebserviceServerAddress() { | ||||||
|         return this.webserviceServerAdress; |         return this.webserviceServerAddress; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public String getWebserviceServerPort() { |     public String getWebserviceServerPort() { | ||||||
|  | @ -61,8 +61,8 @@ public class WebserviceConnectionData { | ||||||
|         return this.webserviceAPIPath; |         return this.webserviceAPIPath; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public String getWebserviceServerAddress() { |     public String getWebserviceServerURL() { | ||||||
|         return this.webserviceServerAddress; |         return this.webserviceServerURL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public UriComponentsBuilder getWebserviceURIBuilder() { |     public UriComponentsBuilder getWebserviceURIBuilder() { | ||||||
|  | @ -101,8 +101,8 @@ public class WebserviceConnectionData { | ||||||
|         builder.append(this.id); |         builder.append(this.id); | ||||||
|         builder.append(", webserviceProtocol="); |         builder.append(", webserviceProtocol="); | ||||||
|         builder.append(this.webserviceProtocol); |         builder.append(this.webserviceProtocol); | ||||||
|         builder.append(", webserviceServerAdress="); |         builder.append(", webserviceServerAddress="); | ||||||
|         builder.append(this.webserviceServerAdress); |         builder.append(this.webserviceServerAddress); | ||||||
|         builder.append(", webserviceServerPort="); |         builder.append(", webserviceServerPort="); | ||||||
|         builder.append(this.webserviceServerPort); |         builder.append(this.webserviceServerPort); | ||||||
|         builder.append(", webserviceAPIPath="); |         builder.append(", webserviceAPIPath="); | ||||||
|  |  | ||||||
|  | @ -25,15 +25,15 @@ public class WebserviceURIService { | ||||||
| 
 | 
 | ||||||
|     public WebserviceURIService( |     public WebserviceURIService( | ||||||
|             @Value("${sebserver.gui.webservice.protocol}") final String webserviceProtocol, |             @Value("${sebserver.gui.webservice.protocol}") final String webserviceProtocol, | ||||||
|             @Value("${sebserver.gui.webservice.address}") final String webserviceServerAdress, |             @Value("${sebserver.gui.webservice.address}") final String webserviceServerAddress, | ||||||
|             @Value("${sebserver.gui.webservice.port}") final String webserviceServerPort, |             @Value("${sebserver.gui.webservice.port}") final String webserviceServerPort, | ||||||
|             @Value("${server.servlet.context-path}") final String servletContextPath, |             @Value("${server.servlet.context-path}") final String servletContextPath, | ||||||
|             @Value("${sebserver.gui.webservice.apipath}") final String webserviceAPIPath) { |             @Value("${sebserver.gui.webservice.apipath}") final String webserviceAPIPath) { | ||||||
| 
 | 
 | ||||||
|         this.servletContextPath = servletContextPath; |         this.servletContextPath = servletContextPath; | ||||||
|         this.webserviceServerAddress = webserviceProtocol + "://" + webserviceServerAdress + ":" + webserviceServerPort; |         this.webserviceServerAddress = webserviceProtocol + "://" + webserviceServerAddress + ":" + webserviceServerPort; | ||||||
|         this.webserviceURIBuilder = UriComponentsBuilder |         this.webserviceURIBuilder = UriComponentsBuilder | ||||||
|                 .fromHttpUrl(webserviceProtocol + "://" + webserviceServerAdress) |                 .fromHttpUrl(webserviceProtocol + "://" + webserviceServerAddress) | ||||||
|                 .port(webserviceServerPort) |                 .port(webserviceServerPort) | ||||||
|                 .path(servletContextPath) |                 .path(servletContextPath) | ||||||
|                 .path(webserviceAPIPath); |                 .path(webserviceAPIPath); | ||||||
|  |  | ||||||
|  | @ -49,12 +49,10 @@ public class ClientConnectionDetails { | ||||||
| 
 | 
 | ||||||
|     private static final int NUMBER_OF_NONE_INDICATOR_ROWS = 3; |     private static final int NUMBER_OF_NONE_INDICATOR_ROWS = 3; | ||||||
| 
 | 
 | ||||||
|     private final PageService pageService; |  | ||||||
|     private final ResourceService resourceService; |     private final ResourceService resourceService; | ||||||
|     private final Exam exam; |  | ||||||
|     private final EnumMap<IndicatorType, IndicatorData> indicatorMapping; |     private final EnumMap<IndicatorType, IndicatorData> indicatorMapping; | ||||||
|     private final RestCall<ClientConnectionData>.RestCallBuilder restCallBuilder; |     private final RestCall<ClientConnectionData>.RestCallBuilder restCallBuilder; | ||||||
|     private final FormHandle<?> formhandle; |     private final FormHandle<?> formHandle; | ||||||
|     private final ColorData colorData; |     private final ColorData colorData; | ||||||
| 
 | 
 | ||||||
|     private ClientConnectionData connectionData = null; |     private ClientConnectionData connectionData = null; | ||||||
|  | @ -69,9 +67,7 @@ public class ClientConnectionDetails { | ||||||
| 
 | 
 | ||||||
|         final Display display = pageContext.getRoot().getDisplay(); |         final Display display = pageContext.getRoot().getDisplay(); | ||||||
| 
 | 
 | ||||||
|         this.pageService = pageService; |  | ||||||
|         this.resourceService = pageService.getResourceService(); |         this.resourceService = pageService.getResourceService(); | ||||||
|         this.exam = exam; |  | ||||||
|         this.restCallBuilder = restCallBuilder; |         this.restCallBuilder = restCallBuilder; | ||||||
|         this.colorData = new ColorData(display); |         this.colorData = new ColorData(display); | ||||||
|         this.indicatorMapping = IndicatorData.createFormIndicators( |         this.indicatorMapping = IndicatorData.createFormIndicators( | ||||||
|  | @ -80,12 +76,12 @@ public class ClientConnectionDetails { | ||||||
|                 this.colorData, |                 this.colorData, | ||||||
|                 NUMBER_OF_NONE_INDICATOR_ROWS); |                 NUMBER_OF_NONE_INDICATOR_ROWS); | ||||||
| 
 | 
 | ||||||
|         final FormBuilder formBuilder = this.pageService.formBuilder(pageContext) |         final FormBuilder formBuilder = pageService.formBuilder(pageContext) | ||||||
|                 .readonly(true) |                 .readonly(true) | ||||||
|                 .addField(FormBuilder.text( |                 .addField(FormBuilder.text( | ||||||
|                         QuizData.QUIZ_ATTR_NAME, |                         QuizData.QUIZ_ATTR_NAME, | ||||||
|                         EXAM_NAME_TEXT_KEY, |                         EXAM_NAME_TEXT_KEY, | ||||||
|                         this.exam.getName())) |                         exam.getName())) | ||||||
|                 .addField(FormBuilder.text( |                 .addField(FormBuilder.text( | ||||||
|                         Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, |                         Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, | ||||||
|                         CONNECTION_ID_TEXT_KEY, |                         CONNECTION_ID_TEXT_KEY, | ||||||
|  | @ -112,7 +108,7 @@ public class ClientConnectionDetails { | ||||||
|                         .withDefaultLabel(indData.indicator.name)) |                         .withDefaultLabel(indData.indicator.name)) | ||||||
|                         .addEmptyCell()); |                         .addEmptyCell()); | ||||||
| 
 | 
 | ||||||
|         this.formhandle = formBuilder.build(); |         this.formHandle = formBuilder.build(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void updateData() { |     public void updateData() { | ||||||
|  | @ -136,7 +132,7 @@ public class ClientConnectionDetails { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         final Form form = this.formhandle.getForm(); |         final Form form = this.formHandle.getForm(); | ||||||
|         form.setFieldValue( |         form.setFieldValue( | ||||||
|                 Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, |                 Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID, | ||||||
|                 this.connectionData.clientConnection.userSessionId); |                 this.connectionData.clientConnection.userSessionId); | ||||||
|  |  | ||||||
|  | @ -371,7 +371,7 @@ public final class ClientConnectionTable { | ||||||
|     private void sortTable() { |     private void sortTable() { | ||||||
|         this.tableMapping = this.tableMapping.entrySet() |         this.tableMapping = this.tableMapping.entrySet() | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .sorted((e1, e2) -> e1.getValue().compareTo(e2.getValue())) |                 .sorted(Entry.comparingByValue()) | ||||||
|                 .collect(Collectors.toMap( |                 .collect(Collectors.toMap( | ||||||
|                         Entry::getKey, |                         Entry::getKey, | ||||||
|                         Entry::getValue, |                         Entry::getValue, | ||||||
|  | @ -398,13 +398,12 @@ public final class ClientConnectionTable { | ||||||
|             final String attribute = this.resourceService |             final String attribute = this.resourceService | ||||||
|                     .getCurrentUser() |                     .getCurrentUser() | ||||||
|                     .getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE); |                     .getAttribute(USER_SESSION_STATUS_FILTER_ATTRIBUTE); | ||||||
|             if (attribute != null) { |  | ||||||
|             this.statusFilter.clear(); |             this.statusFilter.clear(); | ||||||
|  |             if (attribute != null) { | ||||||
|                 Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR)) |                 Arrays.asList(StringUtils.split(attribute, Constants.LIST_SEPARATOR)) | ||||||
|                         .forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name))); |                         .forEach(name -> this.statusFilter.add(ConnectionStatus.valueOf(name))); | ||||||
| 
 | 
 | ||||||
|             } else { |             } else { | ||||||
|                 this.statusFilter.clear(); |  | ||||||
|                 this.statusFilter.add(ConnectionStatus.DISABLED); |                 this.statusFilter.add(ConnectionStatus.DISABLED); | ||||||
|             } |             } | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|  | @ -460,7 +459,7 @@ public final class ClientConnectionTable { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void updateData(final TableItem tableItem) { |         void updateData(final TableItem tableItem) { | ||||||
|             tableItem.setText(0, getConnectionIdentifer()); |             tableItem.setText(0, getConnectionIdentifier()); | ||||||
|             tableItem.setText(1, getConnectionAddress()); |             tableItem.setText(1, getConnectionAddress()); | ||||||
|             tableItem.setText(2, getStatusName()); |             tableItem.setText(2, getStatusName()); | ||||||
|         } |         } | ||||||
|  | @ -533,7 +532,7 @@ public final class ClientConnectionTable { | ||||||
|         public int compareTo(final UpdatableTableItem other) { |         public int compareTo(final UpdatableTableItem other) { | ||||||
|             return Comparator.comparingInt(UpdatableTableItem::statusWeight) |             return Comparator.comparingInt(UpdatableTableItem::statusWeight) | ||||||
|                     .thenComparingInt(UpdatableTableItem::thresholdsWeight) |                     .thenComparingInt(UpdatableTableItem::thresholdsWeight) | ||||||
|                     .thenComparing(UpdatableTableItem::getConnectionIdentifer) |                     .thenComparing(UpdatableTableItem::getConnectionIdentifier) | ||||||
|                     .compare(this, other); |                     .compare(this, other); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -580,7 +579,7 @@ public final class ClientConnectionTable { | ||||||
|             return Constants.EMPTY_NOTE; |             return Constants.EMPTY_NOTE; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         String getConnectionIdentifer() { |         String getConnectionIdentifier() { | ||||||
|             if (this.connectionData != null && this.connectionData.clientConnection.userSessionId != null) { |             if (this.connectionData != null && this.connectionData.clientConnection.userSessionId != null) { | ||||||
|                 return this.connectionData.clientConnection.userSessionId; |                 return this.connectionData.clientConnection.userSessionId; | ||||||
|             } |             } | ||||||
|  | @ -608,10 +607,7 @@ public final class ClientConnectionTable { | ||||||
|                 final IndicatorData indicatorData = |                 final IndicatorData indicatorData = | ||||||
|                         ClientConnectionTable.this.indicatorMapping.get(indicatorValue.getType()); |                         ClientConnectionTable.this.indicatorMapping.get(indicatorValue.getType()); | ||||||
| 
 | 
 | ||||||
|                 if (indicatorData == null) { |                 if (indicatorData != null) { | ||||||
|                     log.error("No IndicatorData of type: {} found", indicatorValue.getType()); |  | ||||||
|                 } else { |  | ||||||
| 
 |  | ||||||
|                     final double value = indicatorValue.getValue(); |                     final double value = indicatorValue.getValue(); | ||||||
|                     final int indicatorWeight = IndicatorData.getWeight(indicatorData, value); |                     final int indicatorWeight = IndicatorData.getWeight(indicatorData, value); | ||||||
|                     if (this.indicatorWeights[indicatorData.index] != indicatorWeight) { |                     if (this.indicatorWeights[indicatorData.index] != indicatorWeight) { | ||||||
|  |  | ||||||
|  | @ -8,18 +8,17 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.service.session; | package ch.ethz.seb.sebserver.gui.service.session; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Collection; |  | ||||||
| import java.util.Collections; |  | ||||||
| import java.util.EnumMap; |  | ||||||
| 
 |  | ||||||
| import org.eclipse.swt.graphics.Color; |  | ||||||
| import org.eclipse.swt.widgets.Display; |  | ||||||
| 
 |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; | import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; | import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; | import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.Threshold; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
|  | import org.eclipse.swt.graphics.Color; | ||||||
|  | import org.eclipse.swt.widgets.Display; | ||||||
|  | 
 | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.Comparator; | ||||||
|  | import java.util.EnumMap; | ||||||
| 
 | 
 | ||||||
| final class IndicatorData { | final class IndicatorData { | ||||||
| 
 | 
 | ||||||
|  | @ -47,13 +46,13 @@ final class IndicatorData { | ||||||
| 
 | 
 | ||||||
|         this.thresholdColor = new ThresholdColor[indicator.thresholds.size()]; |         this.thresholdColor = new ThresholdColor[indicator.thresholds.size()]; | ||||||
|         final ArrayList<Threshold> sortedThresholds = new ArrayList<>(indicator.thresholds); |         final ArrayList<Threshold> sortedThresholds = new ArrayList<>(indicator.thresholds); | ||||||
|         Collections.sort(sortedThresholds, (t1, t2) -> t1.value.compareTo(t2.value)); |         sortedThresholds.sort(Comparator.comparing(t -> t.value)); | ||||||
|         for (int i = 0; i < indicator.thresholds.size(); i++) { |         for (int i = 0; i < indicator.thresholds.size(); i++) { | ||||||
|             this.thresholdColor[i] = new ThresholdColor(sortedThresholds.get(i), display, colorData); |             this.thresholdColor[i] = new ThresholdColor(sortedThresholds.get(i), display, colorData); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static final EnumMap<IndicatorType, IndicatorData> createFormIndicators( |     static EnumMap<IndicatorType, IndicatorData> createFormIndicators( | ||||||
|             final Collection<Indicator> indicators, |             final Collection<Indicator> indicators, | ||||||
|             final Display display, |             final Display display, | ||||||
|             final ColorData colorData, |             final ColorData colorData, | ||||||
|  | @ -73,7 +72,7 @@ final class IndicatorData { | ||||||
|         return indicatorMapping; |         return indicatorMapping; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static final int getWeight(final IndicatorData indicatorData, final double value) { |     static int getWeight(final IndicatorData indicatorData, final double value) { | ||||||
|         for (int j = 0; j < indicatorData.thresholdColor.length; j++) { |         for (int j = 0; j < indicatorData.thresholdColor.length; j++) { | ||||||
|             if (value < indicatorData.thresholdColor[j].value) { |             if (value < indicatorData.thresholdColor[j].value) { | ||||||
|                 return (j == 0) ? -1 : j - 1; |                 return (j == 0) ? -1 : j - 1; | ||||||
|  |  | ||||||
|  | @ -92,13 +92,11 @@ public class InstructionProcessor { | ||||||
|                 StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR), |                 StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR), | ||||||
|                 null); |                 null); | ||||||
| 
 | 
 | ||||||
|         processInstruction(() -> { |         processInstruction(() -> this.restService.getBuilder(PropagateInstruction.class) | ||||||
|             return this.restService.getBuilder(PropagateInstruction.class) |  | ||||||
|                 .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) |                 .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) | ||||||
|                 .withBody(clientInstruction) |                 .withBody(clientInstruction) | ||||||
|                 .call() |                 .call() | ||||||
|                     .getOrThrow(); |                 .getOrThrow(), | ||||||
|         }, |  | ||||||
|                 pageContext); |                 pageContext); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | @ -116,7 +114,6 @@ public class InstructionProcessor { | ||||||
|                         ConnectionStatus.AUTHENTICATED)); |                         ConnectionStatus.AUTHENTICATED)); | ||||||
| 
 | 
 | ||||||
|         if (connectionTokens.isEmpty()) { |         if (connectionTokens.isEmpty()) { | ||||||
|             // TOOD message |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -126,15 +123,13 @@ public class InstructionProcessor { | ||||||
|                     connectionTokens); |                     connectionTokens); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         processInstruction(() -> { |         processInstruction(() -> this.restService.getBuilder(DisableClientConnection.class) | ||||||
|             return this.restService.getBuilder(DisableClientConnection.class) |  | ||||||
|                 .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) |                 .withURIVariable(API.PARAM_MODEL_ID, String.valueOf(examId)) | ||||||
|                 .withFormParam( |                 .withFormParam( | ||||||
|                         Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN, |                         Domain.CLIENT_CONNECTION.ATTR_CONNECTION_TOKEN, | ||||||
|                         StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR)) |                         StringUtils.join(connectionTokens, Constants.LIST_SEPARATOR)) | ||||||
|                 .call() |                 .call() | ||||||
|                     .getOrThrow(); |                 .getOrThrow(), | ||||||
|         }, |  | ||||||
|                 pageContext); |                 pageContext); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -96,12 +96,12 @@ public class EntityTable<ROW extends Entity> { | ||||||
|     private final BiConsumer<TableItem, ROW> rowDecorator; |     private final BiConsumer<TableItem, ROW> rowDecorator; | ||||||
|     private final Consumer<Set<ROW>> selectionListener; |     private final Consumer<Set<ROW>> selectionListener; | ||||||
| 
 | 
 | ||||||
|     int pageNumber = 1; |     int pageNumber; | ||||||
|     int pageSize; |     int pageSize; | ||||||
|     String sortColumn = null; |     String sortColumn = null; | ||||||
|     PageSortOrder sortOrder = PageSortOrder.ASCENDING; |     PageSortOrder sortOrder = PageSortOrder.ASCENDING; | ||||||
|     boolean columnsWithSameWidth = true; |     boolean columnsWithSameWidth = true; | ||||||
|     boolean hideNavigation = false; |     boolean hideNavigation; | ||||||
| 
 | 
 | ||||||
|     EntityTable( |     EntityTable( | ||||||
|             final String name, |             final String name, | ||||||
|  | @ -149,13 +149,10 @@ public class EntityTable<ROW extends Entity> { | ||||||
|         this.rowDecorator = rowDecorator; |         this.rowDecorator = rowDecorator; | ||||||
|         this.selectionListener = selectionListener; |         this.selectionListener = selectionListener; | ||||||
|         this.pageSize = pageSize; |         this.pageSize = pageSize; | ||||||
|         this.filter = |         this.filter = columns | ||||||
|                 columns |  | ||||||
|                 .stream() |                 .stream() | ||||||
|                         .map(column -> column.getFilterAttribute()) |                 .map(ColumnDefinition::getFilterAttribute) | ||||||
|                         .filter(Objects::nonNull) |                 .anyMatch(Objects::nonNull) ? new TableFilter<>(this) : null; | ||||||
|                         .findFirst() |  | ||||||
|                         .isPresent() ? new TableFilter<>(this) : null; |  | ||||||
| 
 | 
 | ||||||
|         this.table = this.widgetFactory.tableLocalized(this.composite); |         this.table = this.widgetFactory.tableLocalized(this.composite); | ||||||
|         final GridLayout gridLayout = new GridLayout(columns.size(), true); |         final GridLayout gridLayout = new GridLayout(columns.size(), true); | ||||||
|  | @ -207,17 +204,15 @@ public class EntityTable<ROW extends Entity> { | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (int i = 0; i < columns.size(); i++) { |             for (int i = 0; i < columns.size(); i++) { | ||||||
|                 final Rectangle itemBoundes = item.getBounds(i); |                 final Rectangle itemBounds = item.getBounds(i); | ||||||
|                 if (itemBoundes.contains(point)) { |                 if (itemBounds.contains(point)) { | ||||||
|                     handleCellSelection(item, i); |                     handleCellSelection(item, i); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         this.table.addListener(SWT.Selection, event -> { |         this.table.addListener(SWT.Selection, event -> this.notifySelectionChange()); | ||||||
|             this.notifySelectionChange(); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         this.navigator = new TableNavigator(this); |         this.navigator = new TableNavigator(this); | ||||||
| 
 | 
 | ||||||
|  | @ -375,8 +370,7 @@ public class EntityTable<ROW extends Entity> { | ||||||
|             return Collections.emptySet(); |             return Collections.emptySet(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return Arrays.asList(selection) |         return Arrays.stream(selection) | ||||||
|                 .stream() |  | ||||||
|                 .map(this::getRowData) |                 .map(this::getRowData) | ||||||
|                 .collect(Collectors.toSet()); |                 .collect(Collectors.toSet()); | ||||||
|     } |     } | ||||||
|  | @ -391,8 +385,7 @@ public class EntityTable<ROW extends Entity> { | ||||||
|             return Collections.emptySet(); |             return Collections.emptySet(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return Arrays.asList(selection) |         return Arrays.stream(selection) | ||||||
|                 .stream() |  | ||||||
|                 .filter(item -> grantCheck == null || grantCheck.test(getRowData(item))) |                 .filter(item -> grantCheck == null || grantCheck.test(getRowData(item))) | ||||||
|                 .map(this::getRowDataId) |                 .map(this::getRowDataId) | ||||||
|                 .collect(Collectors.toSet()); |                 .collect(Collectors.toSet()); | ||||||
|  | @ -415,8 +408,7 @@ public class EntityTable<ROW extends Entity> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private TableColumn getTableColumn(final String name) { |     private TableColumn getTableColumn(final String name) { | ||||||
|         return Arrays.asList(this.table.getColumns()) |         return Arrays.stream(this.table.getColumns()) | ||||||
|                 .stream() |  | ||||||
|                 .filter(col -> { |                 .filter(col -> { | ||||||
|                     @SuppressWarnings("unchecked") |                     @SuppressWarnings("unchecked") | ||||||
|                     final ColumnDefinition<ROW> def = (ColumnDefinition<ROW>) col.getData(COLUMN_DEFINITION); |                     final ColumnDefinition<ROW> def = (ColumnDefinition<ROW>) col.getData(COLUMN_DEFINITION); | ||||||
|  | @ -541,7 +533,7 @@ public class EntityTable<ROW extends Entity> { | ||||||
|                     .filter(c -> c.getWidthProportion() > 0) |                     .filter(c -> c.getWidthProportion() > 0) | ||||||
|                     .reduce(0, |                     .reduce(0, | ||||||
|                             (acc, c) -> acc + c.getWidthProportion(), |                             (acc, c) -> acc + c.getWidthProportion(), | ||||||
|                             (acc1, acc2) -> acc1 + acc2); |                             Integer::sum); | ||||||
| 
 | 
 | ||||||
|             // The unit size either with proportion or for a entire column if all columns are equal in size |             // The unit size either with proportion or for a entire column if all columns are equal in size | ||||||
|             final int columnUnitSize = (pSize > 0) |             final int columnUnitSize = (pSize > 0) | ||||||
|  |  | ||||||
|  | @ -100,7 +100,7 @@ public class TableBuilder<ROW extends Entity> { | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public TableBuilder<ROW> withMultiselection() { |     public TableBuilder<ROW> withMultiSelection() { | ||||||
|         this.type |= SWT.MULTI; |         this.type |= SWT.MULTI; | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
|     private static final LocTextKey DATE_TO_TEXT = new LocTextKey("sebserver.overall.date.to"); |     private static final LocTextKey DATE_TO_TEXT = new LocTextKey("sebserver.overall.date.to"); | ||||||
|     private static final LocTextKey ALL_TEXT = new LocTextKey("sebserver.overall.status.all"); |     private static final LocTextKey ALL_TEXT = new LocTextKey("sebserver.overall.status.all"); | ||||||
| 
 | 
 | ||||||
|     public static enum CriteriaType { |     public enum CriteriaType { | ||||||
|         TEXT, |         TEXT, | ||||||
|         SINGLE_SELECTION, |         SINGLE_SELECTION, | ||||||
|         DATE, |         DATE, | ||||||
|  | @ -82,7 +82,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
|     public MultiValueMap<String, String> getFilterParameter() { |     public MultiValueMap<String, String> getFilterParameter() { | ||||||
|         return this.components |         return this.components | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .reduce(new LinkedMultiValueMap<String, String>(), |                 .reduce(new LinkedMultiValueMap<>(), | ||||||
|                         (map, comp) -> comp.putFilterParameter(map), |                         (map, comp) -> comp.putFilterParameter(map), | ||||||
|                         (map1, map2) -> { |                         (map1, map2) -> { | ||||||
|                             map1.putAll(map2); |                             map1.putAll(map2); | ||||||
|  | @ -92,8 +92,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
| 
 | 
 | ||||||
|     public void reset() { |     public void reset() { | ||||||
|         this.components |         this.components | ||||||
|                 .stream() |                 .forEach(FilterComponent::reset); | ||||||
|                 .forEach(comp -> comp.reset()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void buildComponents() { |     private void buildComponents() { | ||||||
|  | @ -158,7 +157,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
|                                 .append(Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR) |                                 .append(Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR) | ||||||
|                                 .append(filter.getValue()) |                                 .append(filter.getValue()) | ||||||
|                                 .append(Constants.LIST_SEPARATOR), |                                 .append(Constants.LIST_SEPARATOR), | ||||||
|                         (sb1, sb2) -> sb1.append(sb2)); |                         StringBuilder::append); | ||||||
|         if (builder.length() > 0) { |         if (builder.length() > 0) { | ||||||
|             builder.deleteCharAt(builder.length() - 1); |             builder.deleteCharAt(builder.length() - 1); | ||||||
|         } |         } | ||||||
|  | @ -171,22 +170,19 @@ public class TableFilter<ROW extends Entity> { | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             Arrays.asList(StringUtils.split( |             Arrays.stream(StringUtils.split( | ||||||
|                     attribute, |                     attribute, | ||||||
|                     Constants.LIST_SEPARATOR_CHAR)) |                     Constants.LIST_SEPARATOR_CHAR)) | ||||||
|                     .stream() |  | ||||||
|                     .map(nameValue -> StringUtils.split( |                     .map(nameValue -> StringUtils.split( | ||||||
|                             nameValue, |                             nameValue, | ||||||
|                             Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR)) |                             Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR)) | ||||||
|                     .forEach(nameValue -> { |                     .forEach(nameValue -> this.components | ||||||
|                         this.components |  | ||||||
|                             .stream() |                             .stream() | ||||||
|                             .filter(filter -> nameValue[0].equals(filter.attribute.columnName)) |                             .filter(filter -> nameValue[0].equals(filter.attribute.columnName)) | ||||||
|                             .findFirst() |                             .findFirst() | ||||||
|                             .ifPresent(filter -> filter.setValue((nameValue.length > 1) |                             .ifPresent(filter -> filter.setValue((nameValue.length > 1) | ||||||
|                                     ? nameValue[1] |                                     ? nameValue[1] | ||||||
|                                         : StringUtils.EMPTY)); |                                     : StringUtils.EMPTY))); | ||||||
|                     }); |  | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|             log.error("Failed to set filter attributes: ", e); |             log.error("Failed to set filter attributes: ", e); | ||||||
|         } |         } | ||||||
|  | @ -208,9 +204,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
|                 ImageIcon.SEARCH, |                 ImageIcon.SEARCH, | ||||||
|                 inner, |                 inner, | ||||||
|                 new LocTextKey("sebserver.overall.action.filter"), |                 new LocTextKey("sebserver.overall.action.filter"), | ||||||
|                 event -> { |                 event -> this.entityTable.applyFilter()); | ||||||
|                     this.entityTable.applyFilter(); |  | ||||||
|                 }); |  | ||||||
|         imageButton.setLayoutData(gridData); |         imageButton.setLayoutData(gridData); | ||||||
|         final Label imageButton2 = this.entityTable.widgetFactory.imageButton( |         final Label imageButton2 = this.entityTable.widgetFactory.imageButton( | ||||||
|                 ImageIcon.CANCEL, |                 ImageIcon.CANCEL, | ||||||
|  | @ -276,7 +270,7 @@ public class TableFilter<ROW extends Entity> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private class NullFilter extends FilterComponent { |     private static class NullFilter extends FilterComponent { | ||||||
| 
 | 
 | ||||||
|         private Label label; |         private Label label; | ||||||
| 
 | 
 | ||||||
|  | @ -493,7 +487,6 @@ public class TableFilter<ROW extends Entity> { | ||||||
|     private class DateRange extends FilterComponent { |     private class DateRange extends FilterComponent { | ||||||
| 
 | 
 | ||||||
|         private Composite innerComposite; |         private Composite innerComposite; | ||||||
|         //private final GridData rw1 = new GridData(SWT.FILL, SWT.FILL, true, true); |  | ||||||
|         private DateTime fromDateSelector; |         private DateTime fromDateSelector; | ||||||
|         private DateTime toDateSelector; |         private DateTime toDateSelector; | ||||||
|         private DateTime fromTimeSelector; |         private DateTime fromTimeSelector; | ||||||
|  |  | ||||||
|  | @ -68,7 +68,7 @@ public class TableNavigator { | ||||||
| 
 | 
 | ||||||
|         if (numberOfPages > 1) { |         if (numberOfPages > 1) { | ||||||
|             createBackwardLabel(pageNumber > 1, pageNumber, numNav); |             createBackwardLabel(pageNumber > 1, pageNumber, numNav); | ||||||
|             final int pageNavSize = (numberOfPages > PAGE_NAV_SIZE) ? PAGE_NAV_SIZE : numberOfPages; |             final int pageNavSize = Math.min(numberOfPages, PAGE_NAV_SIZE); | ||||||
|             final int half = pageNavSize / 2; |             final int half = pageNavSize / 2; | ||||||
|             int start = pageNumber - half; |             int start = pageNumber - half; | ||||||
|             if (start < 1) { |             if (start < 1) { | ||||||
|  | @ -107,14 +107,12 @@ public class TableNavigator { | ||||||
| 
 | 
 | ||||||
|         final GridData rowData = new GridData(22, 16); |         final GridData rowData = new GridData(22, 16); | ||||||
|         final Label pageLabel = new Label(parent, SWT.NONE); |         final Label pageLabel = new Label(parent, SWT.NONE); | ||||||
|         pageLabel.setText(" " + String.valueOf(page) + " "); |         pageLabel.setText(" " + page + " "); | ||||||
|         pageLabel.setLayoutData(rowData); |         pageLabel.setLayoutData(rowData); | ||||||
|         pageLabel.setAlignment(SWT.CENTER); |         pageLabel.setAlignment(SWT.CENTER); | ||||||
|         if (selectable) { |         if (selectable) { | ||||||
|             pageLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); |             pageLabel.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); | ||||||
|             pageLabel.addListener(SWT.MouseDown, event -> { |             pageLabel.addListener(SWT.MouseDown, event -> this.entityTable.selectPage(page)); | ||||||
|                 this.entityTable.selectPage(page); |  | ||||||
|             }); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -131,9 +129,7 @@ public class TableNavigator { | ||||||
|         forward.setLayoutData(rowData); |         forward.setLayoutData(rowData); | ||||||
|         forward.setAlignment(SWT.CENTER); |         forward.setAlignment(SWT.CENTER); | ||||||
|         if (visible) { |         if (visible) { | ||||||
|             forward.addListener(SWT.MouseDown, event -> { |             forward.addListener(SWT.MouseDown, event -> this.entityTable.selectPage(pageNumber + 1)); | ||||||
|                 this.entityTable.selectPage(pageNumber + 1); |  | ||||||
|             }); |  | ||||||
|         } else { |         } else { | ||||||
|             forward.setVisible(false); |             forward.setVisible(false); | ||||||
|         } |         } | ||||||
|  | @ -144,9 +140,7 @@ public class TableNavigator { | ||||||
|         end.setLayoutData(rowData); |         end.setLayoutData(rowData); | ||||||
|         end.setAlignment(SWT.CENTER); |         end.setAlignment(SWT.CENTER); | ||||||
|         if (visible) { |         if (visible) { | ||||||
|             end.addListener(SWT.MouseDown, event -> { |             end.addListener(SWT.MouseDown, event -> this.entityTable.selectPage(numberOfPages)); | ||||||
|                 this.entityTable.selectPage(numberOfPages); |  | ||||||
|             }); |  | ||||||
|         } else { |         } else { | ||||||
|             end.setVisible(false); |             end.setVisible(false); | ||||||
|         } |         } | ||||||
|  | @ -164,9 +158,7 @@ public class TableNavigator { | ||||||
|         start.setAlignment(SWT.CENTER); |         start.setAlignment(SWT.CENTER); | ||||||
|         start.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); |         start.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); | ||||||
|         if (visible) { |         if (visible) { | ||||||
|             start.addListener(SWT.MouseDown, event -> { |             start.addListener(SWT.MouseDown, event -> this.entityTable.selectPage(1)); | ||||||
|                 this.entityTable.selectPage(1); |  | ||||||
|             }); |  | ||||||
|         } else { |         } else { | ||||||
|             start.setVisible(false); |             start.setVisible(false); | ||||||
|         } |         } | ||||||
|  | @ -177,9 +169,7 @@ public class TableNavigator { | ||||||
|         backward.setAlignment(SWT.CENTER); |         backward.setAlignment(SWT.CENTER); | ||||||
|         backward.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); |         backward.setData(RWT.CUSTOM_VARIANT, CustomVariant.LIST_NAVIGATION.key); | ||||||
|         if (visible) { |         if (visible) { | ||||||
|             backward.addListener(SWT.MouseDown, event -> { |             backward.addListener(SWT.MouseDown, event -> this.entityTable.selectPage(pageNumber - 1)); | ||||||
|                 this.entityTable.selectPage(pageNumber - 1); |  | ||||||
|             }); |  | ||||||
|         } else { |         } else { | ||||||
|             backward.setVisible(false); |             backward.setVisible(false); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -166,10 +166,8 @@ public class FileUploadSelection extends Composite { | ||||||
|     private boolean fileSupported(final String fileName) { |     private boolean fileSupported(final String fileName) { | ||||||
|         return this.supportedFileExtensions |         return this.supportedFileExtensions | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(fileType -> fileName.toUpperCase(Locale.ROOT) |                 .anyMatch(fileType -> fileName.toUpperCase(Locale.ROOT) | ||||||
|                         .endsWith(fileType.toUpperCase(Locale.ROOT))) |                         .endsWith(fileType.toUpperCase(Locale.ROOT))); | ||||||
|                 .findFirst() |  | ||||||
|                 .isPresent(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private final class InputReceiver extends FileUploadReceiver { |     private final class InputReceiver extends FileUploadReceiver { | ||||||
|  |  | ||||||
|  | @ -157,7 +157,7 @@ public class GridTable extends Composite { | ||||||
|         return StringUtils.join( |         return StringUtils.join( | ||||||
|                 this.rows |                 this.rows | ||||||
|                         .stream() |                         .stream() | ||||||
|                         .map(row -> row.getValue()) |                         .map(Row::getValue) | ||||||
|                         .collect(Collectors.toList()), |                         .collect(Collectors.toList()), | ||||||
|                 Constants.LIST_SEPARATOR); |                 Constants.LIST_SEPARATOR); | ||||||
|     } |     } | ||||||
|  | @ -209,10 +209,9 @@ public class GridTable extends Composite { | ||||||
|                     .stream() |                     .stream() | ||||||
|                     .reduce(0, |                     .reduce(0, | ||||||
|                             (i, c2) -> i + c2.columnDef.widthFactor, |                             (i, c2) -> i + c2.columnDef.widthFactor, | ||||||
|                             (i1, i2) -> i1 + i2); |                             Integer::sum); | ||||||
| 
 | 
 | ||||||
|             this.columns |             this.columns | ||||||
|                     .stream() |  | ||||||
|                     .forEach(c -> c.header.widthHint = c.columnDef.widthFactor * widthUnit); |                     .forEach(c -> c.header.widthHint = c.columnDef.widthFactor * widthUnit); | ||||||
| 
 | 
 | ||||||
|             super.layout(true, true); |             super.layout(true, true); | ||||||
|  | @ -273,7 +272,7 @@ public class GridTable extends Composite { | ||||||
|             this.defaultValue = defaultValue; |             this.defaultValue = defaultValue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static final ColumnDef fromString( |         public static ColumnDef fromString( | ||||||
|                 final String string, |                 final String string, | ||||||
|                 final Map<String, String> defaultValueMap) { |                 final Map<String, String> defaultValueMap) { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -48,10 +48,7 @@ public final class ImageUploadSelection extends Composite { | ||||||
|     private static final long serialVersionUID = 368264811155804533L; |     private static final long serialVersionUID = 368264811155804533L; | ||||||
|     private static final Logger log = LoggerFactory.getLogger(ImageUploadSelection.class); |     private static final Logger log = LoggerFactory.getLogger(ImageUploadSelection.class); | ||||||
| 
 | 
 | ||||||
|     public static final Set<String> SUPPORTED_IMAGE_FILES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( |     public static final Set<String> SUPPORTED_IMAGE_FILES = Set.of(".png", ".jpg", ".jpeg"); | ||||||
|             ".png", |  | ||||||
|             ".jpg", |  | ||||||
|             ".jpeg"))); |  | ||||||
| 
 | 
 | ||||||
|     private final ServerPushService serverPushService; |     private final ServerPushService serverPushService; | ||||||
| 
 | 
 | ||||||
|  | @ -152,12 +149,12 @@ public final class ImageUploadSelection extends Composite { | ||||||
|         setImage(this, input); |         setImage(this, input); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static final boolean uploadInProgress(final ServerPushContext context) { |     private static boolean uploadInProgress(final ServerPushContext context) { | ||||||
|         final ImageUploadSelection imageUpload = (ImageUploadSelection) context.getAnchor(); |         final ImageUploadSelection imageUpload = (ImageUploadSelection) context.getAnchor(); | ||||||
|         return imageUpload.loadNewImage && !imageUpload.imageLoaded; |         return imageUpload.loadNewImage && !imageUpload.imageLoaded; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static final void update(final ServerPushContext context) { |     private static void update(final ServerPushContext context) { | ||||||
|         final ImageUploadSelection imageUpload = (ImageUploadSelection) context.getAnchor(); |         final ImageUploadSelection imageUpload = (ImageUploadSelection) context.getAnchor(); | ||||||
|         if (imageUpload.imageBase64 != null |         if (imageUpload.imageBase64 != null | ||||||
|                 && imageUpload.loadNewImage |                 && imageUpload.loadNewImage | ||||||
|  | @ -181,12 +178,8 @@ public final class ImageUploadSelection extends Composite { | ||||||
| 
 | 
 | ||||||
|         final Image image = new Image(imageUpload.imageCanvas.getDisplay(), input); |         final Image image = new Image(imageUpload.imageCanvas.getDisplay(), input); | ||||||
|         final Rectangle imageBounds = image.getBounds(); |         final Rectangle imageBounds = image.getBounds(); | ||||||
|         final int width = (imageBounds.width > imageUpload.maxWidth) |         final int width = Math.min(imageBounds.width, imageUpload.maxWidth); | ||||||
|                 ? imageUpload.maxWidth |         final int height = Math.min(imageBounds.height, imageUpload.maxHeight); | ||||||
|                 : imageBounds.width; |  | ||||||
|         final int height = (imageBounds.height > imageUpload.maxHeight) |  | ||||||
|                 ? imageUpload.maxHeight |  | ||||||
|                 : imageBounds.height; |  | ||||||
|         final ImageData imageData = image.getImageData().scaledTo(width, height); |         final ImageData imageData = image.getImageData().scaledTo(width, height); | ||||||
|         imageUpload.imageCanvas.setBackgroundImage(new Image(imageUpload.imageCanvas.getDisplay(), imageData)); |         imageUpload.imageCanvas.setBackgroundImage(new Image(imageUpload.imageCanvas.getDisplay(), imageData)); | ||||||
|     } |     } | ||||||
|  | @ -194,10 +187,8 @@ public final class ImageUploadSelection extends Composite { | ||||||
|     private static boolean fileSupported(final String fileName) { |     private static boolean fileSupported(final String fileName) { | ||||||
|         return SUPPORTED_IMAGE_FILES |         return SUPPORTED_IMAGE_FILES | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(fileType -> fileName.toUpperCase(Locale.ROOT) |                 .anyMatch(fileType -> fileName.toUpperCase(Locale.ROOT) | ||||||
|                         .endsWith(fileType.toUpperCase(Locale.ROOT))) |                         .endsWith(fileType.toUpperCase(Locale.ROOT))); | ||||||
|                 .findFirst() |  | ||||||
|                 .isPresent(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private final class ImageReceiver extends FileUploadReceiver { |     private final class ImageReceiver extends FileUploadReceiver { | ||||||
|  |  | ||||||
|  | @ -8,12 +8,11 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.widget; | package ch.ethz.seb.sebserver.gui.widget; | ||||||
| 
 | 
 | ||||||
| import java.util.Arrays; | import ch.ethz.seb.sebserver.gbl.Constants; | ||||||
| import java.util.LinkedHashMap; | import ch.ethz.seb.sebserver.gbl.util.Tuple; | ||||||
| import java.util.List; | import ch.ethz.seb.sebserver.gbl.util.Tuple3; | ||||||
| import java.util.Map; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
| import java.util.stream.Collectors; | import ch.ethz.seb.sebserver.gui.service.page.PageService; | ||||||
| 
 |  | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.eclipse.swt.SWT; | import org.eclipse.swt.SWT; | ||||||
| import org.eclipse.swt.layout.GridData; | import org.eclipse.swt.layout.GridData; | ||||||
|  | @ -22,11 +21,10 @@ import org.eclipse.swt.widgets.Button; | ||||||
| import org.eclipse.swt.widgets.Composite; | import org.eclipse.swt.widgets.Composite; | ||||||
| import org.eclipse.swt.widgets.Listener; | import org.eclipse.swt.widgets.Listener; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.Constants; | import java.util.Arrays; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Tuple; | import java.util.LinkedHashMap; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Tuple3; | import java.util.List; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import java.util.Map; | ||||||
| import ch.ethz.seb.sebserver.gui.service.page.PageService; |  | ||||||
| 
 | 
 | ||||||
| public final class MultiSelectionCheckbox extends Composite implements Selection { | public final class MultiSelectionCheckbox extends Composite implements Selection { | ||||||
| 
 | 
 | ||||||
|  | @ -121,7 +119,7 @@ public final class MultiSelectionCheckbox extends Composite implements Selection | ||||||
|                         .stream() |                         .stream() | ||||||
|                         .filter(Button::getSelection) |                         .filter(Button::getSelection) | ||||||
|                         .map(button -> (String) button.getData(OPTION_VALUE)) |                         .map(button -> (String) button.getData(OPTION_VALUE)) | ||||||
|                         .collect(Collectors.toList()).toArray()); |                         .toArray()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -8,13 +8,9 @@ | ||||||
| 
 | 
 | ||||||
| package ch.ethz.seb.sebserver.gui.widget; | package ch.ethz.seb.sebserver.gui.widget; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import ch.ethz.seb.sebserver.gbl.Constants; | ||||||
| import java.util.Arrays; | import ch.ethz.seb.sebserver.gbl.util.Tuple; | ||||||
| import java.util.Collection; | import ch.ethz.seb.sebserver.gui.service.page.PageService; | ||||||
| import java.util.List; |  | ||||||
| import java.util.Optional; |  | ||||||
| import java.util.stream.Collectors; |  | ||||||
| 
 |  | ||||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||||
| import org.eclipse.rap.rwt.widgets.DropDown; | import org.eclipse.rap.rwt.widgets.DropDown; | ||||||
| import org.eclipse.swt.SWT; | import org.eclipse.swt.SWT; | ||||||
|  | @ -29,9 +25,10 @@ import org.eclipse.swt.widgets.Text; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.gbl.Constants; | import java.util.ArrayList; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Tuple; | import java.util.Arrays; | ||||||
| import ch.ethz.seb.sebserver.gui.service.page.PageService; | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
| 
 | 
 | ||||||
| public final class MultiSelectionCombo extends Composite implements Selection { | public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
| 
 | 
 | ||||||
|  | @ -75,12 +72,8 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|         this.textCell = new GridData(SWT.LEFT, SWT.CENTER, true, true); |         this.textCell = new GridData(SWT.LEFT, SWT.CENTER, true, true); | ||||||
|         this.textInput.setLayoutData(this.textCell); |         this.textInput.setLayoutData(this.textCell); | ||||||
|         this.dropDown = new DropDown(this.textInput, SWT.NONE); |         this.dropDown = new DropDown(this.textInput, SWT.NONE); | ||||||
|         this.textInput.addListener(SWT.FocusIn, event -> { |         this.textInput.addListener(SWT.FocusIn, event -> openDropDown()); | ||||||
|             openDropDown(); |         this.textInput.addListener(SWT.Modify, event -> openDropDown()); | ||||||
|         }); |  | ||||||
|         this.textInput.addListener(SWT.Modify, event -> { |  | ||||||
|             openDropDown(); |  | ||||||
|         }); |  | ||||||
|         this.dropDown.addListener(SWT.Selection, event -> { |         this.dropDown.addListener(SWT.Selection, event -> { | ||||||
|             final int selectionIndex = this.dropDown.getSelectionIndex(); |             final int selectionIndex = this.dropDown.getSelectionIndex(); | ||||||
|             if (selectionIndex >= 0) { |             if (selectionIndex >= 0) { | ||||||
|  | @ -98,12 +91,10 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|             this.dropDown.setVisible(false); |             this.dropDown.setVisible(false); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         final Collection<String> items = this.availableValues |         this.dropDown.setItems(this.availableValues | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(it -> it._2 != null && it._2.startsWith(text)) |                 .filter(it -> it._2 != null && it._2.startsWith(text)) | ||||||
|                 .map(t -> t._2) |                 .map(t -> t._2).toArray(String[]::new)); | ||||||
|                 .collect(Collectors.toList()); |  | ||||||
|         this.dropDown.setItems(items.toArray(new String[items.size()])); |  | ||||||
|         this.dropDown.setSelectionIndex(0); |         this.dropDown.setSelectionIndex(0); | ||||||
|         this.dropDown.setVisible(true); |         this.dropDown.setVisible(true); | ||||||
|     } |     } | ||||||
|  | @ -132,8 +123,7 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Arrays.asList(StringUtils.split(keys, Constants.LIST_SEPARATOR)) |         Arrays.stream(StringUtils.split(keys, Constants.LIST_SEPARATOR)) | ||||||
|                 .stream() |  | ||||||
|                 .map(this::itemForId) |                 .map(this::itemForId) | ||||||
|                 .forEach(this::addSelection); |                 .forEach(this::addSelection); | ||||||
|     } |     } | ||||||
|  | @ -159,7 +149,6 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|     public void clear() { |     public void clear() { | ||||||
|         this.selectedValues.clear(); |         this.selectedValues.clear(); | ||||||
|         this.selectionControls |         this.selectionControls | ||||||
|                 .stream() |  | ||||||
|                 .forEach(Control::dispose); |                 .forEach(Control::dispose); | ||||||
|         this.selectionControls.clear(); |         this.selectionControls.clear(); | ||||||
|         this.availableValues.clear(); |         this.availableValues.clear(); | ||||||
|  | @ -176,9 +165,7 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|         label.setData(OPTION_VALUE, item._2); |         label.setData(OPTION_VALUE, item._2); | ||||||
|         final GridData textCell = new GridData(SWT.LEFT, SWT.CENTER, true, true); |         final GridData textCell = new GridData(SWT.LEFT, SWT.CENTER, true, true); | ||||||
|         label.setLayoutData(textCell); |         label.setLayoutData(textCell); | ||||||
|         label.addListener(SWT.MouseDoubleClick, event -> { |         label.addListener(SWT.MouseDoubleClick, this::removeComboSelection); | ||||||
|             removeComboSelection(event); |  | ||||||
|         }); |  | ||||||
|         this.selectionControls.add(label); |         this.selectionControls.add(label); | ||||||
| 
 | 
 | ||||||
|         this.availableValues.remove(item); |         this.availableValues.remove(item); | ||||||
|  | @ -217,8 +204,7 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
| 
 | 
 | ||||||
|     private void adaptColumnWidth(final Event event) { |     private void adaptColumnWidth(final Event event) { | ||||||
|         try { |         try { | ||||||
|             final int currentTableWidth = this.getClientArea().width; |             this.textCell.widthHint = this.getClientArea().width; | ||||||
|             this.textCell.widthHint = currentTableWidth; |  | ||||||
|             this.layout(); |             this.layout(); | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|             log.warn("Failed to adaptColumnWidth: ", e); |             log.warn("Failed to adaptColumnWidth: ", e); | ||||||
|  | @ -230,11 +216,7 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(it -> it._2 != null && it._2.equals(name)) |                 .filter(it -> it._2 != null && it._2.equals(name)) | ||||||
|                 .findFirst(); |                 .findFirst(); | ||||||
|         if (findFirst.isPresent()) { |         return findFirst.orElse(null); | ||||||
|             return findFirst.get(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return null; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Tuple<String> itemForId(final String id) { |     private Tuple<String> itemForId(final String id) { | ||||||
|  | @ -242,11 +224,7 @@ public final class MultiSelectionCombo extends Composite implements Selection { | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(it -> it._1 != null && it._1.equals(id)) |                 .filter(it -> it._1 != null && it._1.equals(id)) | ||||||
|                 .findFirst(); |                 .findFirst(); | ||||||
|         if (findFirst.isPresent()) { |         return findFirst.orElse(null); | ||||||
|             return findFirst.get(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return null; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -99,7 +99,7 @@ public final class RadioSelection extends Composite implements Selection { | ||||||
|         return this.radioButtons |         return this.radioButtons | ||||||
|                 .values() |                 .values() | ||||||
|                 .stream() |                 .stream() | ||||||
|                 .filter(button -> button.getSelection()) |                 .filter(Button::getSelection) | ||||||
|                 .findFirst() |                 .findFirst() | ||||||
|                 .map(button -> (String) button.getData(OPTION_VALUE)) |                 .map(button -> (String) button.getData(OPTION_VALUE)) | ||||||
|                 .orElse(null); |                 .orElse(null); | ||||||
|  | @ -109,7 +109,6 @@ public final class RadioSelection extends Composite implements Selection { | ||||||
|     public void clear() { |     public void clear() { | ||||||
|         this.radioButtons |         this.radioButtons | ||||||
|                 .values() |                 .values() | ||||||
|                 .stream() |  | ||||||
|                 .forEach(button -> button.setSelection(false)); |                 .forEach(button -> button.setSelection(false)); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ import ch.ethz.seb.sebserver.gbl.util.Tuple; | ||||||
| 
 | 
 | ||||||
| public interface Selection { | public interface Selection { | ||||||
| 
 | 
 | ||||||
|     static final String OPTION_VALUE = "OPTION_VALUE"; |     String OPTION_VALUE = "OPTION_VALUE"; | ||||||
| 
 | 
 | ||||||
|     enum Type { |     enum Type { | ||||||
|         SINGLE, |         SINGLE, | ||||||
|  |  | ||||||
|  | @ -87,7 +87,7 @@ public final class SingleSelection extends Combo implements Selection { | ||||||
|     @Override |     @Override | ||||||
|     public void clear() { |     public void clear() { | ||||||
|         super.clearSelection(); |         super.clearSelection(); | ||||||
|         super.setItems(this.valueMapping.toArray(new String[this.valueMapping.size()])); |         super.setItems(this.valueMapping.toArray(new String[0])); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -123,7 +123,7 @@ public class WidgetFactory { | ||||||
|         private ImageData image = null; |         private ImageData image = null; | ||||||
|         private ImageData greyedImage = null; |         private ImageData greyedImage = null; | ||||||
| 
 | 
 | ||||||
|         private ImageIcon(final String fileName) { |         ImageIcon(final String fileName) { | ||||||
|             this.fileName = fileName; |             this.fileName = fileName; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -199,7 +199,7 @@ public class WidgetFactory { | ||||||
| 
 | 
 | ||||||
|         public final String key; |         public final String key; | ||||||
| 
 | 
 | ||||||
|         private CustomVariant(final String key) { |         CustomVariant(final String key) { | ||||||
|             this.key = key; |             this.key = key; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -268,7 +268,7 @@ public class WidgetFactory { | ||||||
|      * @param parent The parent Composite |      * @param parent The parent Composite | ||||||
|      * @return the scrolled Composite to add the form content */ |      * @return the scrolled Composite to add the form content */ | ||||||
|     public Composite createPopupScrollComposite(final Composite parent) { |     public Composite createPopupScrollComposite(final Composite parent) { | ||||||
|         final Composite grid = PageService.createManagedVScrolledComposite( |         return PageService.createManagedVScrolledComposite( | ||||||
|                 parent, |                 parent, | ||||||
|                 scrolledComposite -> { |                 scrolledComposite -> { | ||||||
|                     final Composite g = new Composite(scrolledComposite, SWT.NONE); |                     final Composite g = new Composite(scrolledComposite, SWT.NONE); | ||||||
|  | @ -277,7 +277,6 @@ public class WidgetFactory { | ||||||
|                     return g; |                     return g; | ||||||
|                 }, |                 }, | ||||||
|                 false); |                 false); | ||||||
|         return grid; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Composite createWarningPanel(final Composite parent) { |     public Composite createWarningPanel(final Composite parent) { | ||||||
|  | @ -733,7 +732,7 @@ public class WidgetFactory { | ||||||
|                 new FileUploadSelection(parent, this.i18nSupport, readonly); |                 new FileUploadSelection(parent, this.i18nSupport, readonly); | ||||||
| 
 | 
 | ||||||
|         if (supportedFiles != null) { |         if (supportedFiles != null) { | ||||||
|             supportedFiles.forEach(ext -> fileUploadSelection.withSupportFor(ext)); |             supportedFiles.forEach(fileUploadSelection::withSupportFor); | ||||||
|         } |         } | ||||||
|         return fileUploadSelection; |         return fileUploadSelection; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -57,13 +57,6 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent | ||||||
| 
 | 
 | ||||||
|         SEBServerInit.INIT_LOGGER.info("---->  **** Webservice starting up... ****"); |         SEBServerInit.INIT_LOGGER.info("---->  **** Webservice starting up... ****"); | ||||||
| 
 | 
 | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> "); |  | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> Init Database with flyway..."); |  | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> TODO "); |  | ||||||
| 
 |  | ||||||
|         // TODO integration of Flyway for database initialization and migration:  https://flywaydb.org |  | ||||||
|         //      see also https://flywaydb.org/getstarted/firststeps/api |  | ||||||
| 
 |  | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> "); |         SEBServerInit.INIT_LOGGER.info("----> "); | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> Intitialize Services..."); |         SEBServerInit.INIT_LOGGER.info("----> Intitialize Services..."); | ||||||
|         SEBServerInit.INIT_LOGGER.info("----> "); |         SEBServerInit.INIT_LOGGER.info("----> "); | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; | import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | ||||||
|  | import org.joda.time.DateTimeZone; | ||||||
| 
 | 
 | ||||||
| /** Defines the LMS API access service interface with all functionality needed to access | /** Defines the LMS API access service interface with all functionality needed to access | ||||||
|  * a LMS API within a given LmsSetup configuration. |  * a LMS API within a given LmsSetup configuration. | ||||||
|  | @ -101,12 +102,12 @@ public interface LmsAPIService { | ||||||
|     static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) { |     static Predicate<QuizData> quizFilterPredicate(final FilterMap filterMap) { | ||||||
|         final String name = filterMap.getQuizName(); |         final String name = filterMap.getQuizName(); | ||||||
|         final DateTime from = filterMap.getQuizFromTime(); |         final DateTime from = filterMap.getQuizFromTime(); | ||||||
|         //final DateTime now = DateTime.now(DateTimeZone.UTC); |  | ||||||
|         return q -> { |         return q -> { | ||||||
|             final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name)); |             final boolean nameFilter = StringUtils.isBlank(name) || (q.name != null && q.name.contains(name)); | ||||||
|             final boolean startTimeFilter = |             final boolean startTimeFilter = | ||||||
|                     (from == null) || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from))); |                     (from == null) || (q.startTime != null && (q.startTime.isEqual(from) || q.startTime.isAfter(from))); | ||||||
|             return nameFilter && startTimeFilter /* && endTimeFilter */; |             final boolean currentlyRunning = DateTime.now(DateTimeZone.UTC).isBefore(q.endTime); | ||||||
|  |             return nameFilter && (startTimeFilter || currentlyRunning) ; | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -60,10 +60,10 @@ public interface ClientConfigService { | ||||||
|             unless = "#result.hasError()") |             unless = "#result.hasError()") | ||||||
|     Result<ClientDetails> getClientConfigDetails(String clientName); |     Result<ClientDetails> getClientConfigDetails(String clientName); | ||||||
| 
 | 
 | ||||||
|     @CacheEvict( |     /** Internally used to check OAuth2 access for a active SebClientConfig. | ||||||
|             cacheNames = EXAM_CLIENT_DETAILS_CACHE, |      * | ||||||
|             allEntries = true) |      * @param config the SebClientConfig to check access | ||||||
|     @EventListener(BulkActionEvent.class) |      * @return true if the system was able to gain an access token for the client. False otherwise | ||||||
|     void flushClientConfigData(BulkActionEvent event); |      */ | ||||||
| 
 |     boolean checkAccess(SebClientConfig config); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -10,8 +10,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl; | ||||||
| 
 | 
 | ||||||
| import ch.ethz.seb.sebserver.WebSecurityConfig; | import ch.ethz.seb.sebserver.WebSecurityConfig; | ||||||
| import ch.ethz.seb.sebserver.gbl.Constants; | import ch.ethz.seb.sebserver.gbl.Constants; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType; | import ch.ethz.seb.sebserver.gbl.api.API; | ||||||
| import ch.ethz.seb.sebserver.gbl.api.EntityType; |  | ||||||
| import ch.ethz.seb.sebserver.gbl.model.EntityKey; | import ch.ethz.seb.sebserver.gbl.model.EntityKey; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.institution.Institution; | import ch.ethz.seb.sebserver.gbl.model.institution.Institution; | ||||||
| import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; | import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig; | ||||||
|  | @ -19,8 +18,6 @@ import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Result; | import ch.ethz.seb.sebserver.gbl.util.Result; | ||||||
| import ch.ethz.seb.sebserver.gbl.util.Utils; | import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
| import ch.ethz.seb.sebserver.webservice.WebserviceInfo; | import ch.ethz.seb.sebserver.webservice.WebserviceInfo; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkAction; |  | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.impl.BulkActionEvent; |  | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; | import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentialService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials; | import ch.ethz.seb.sebserver.webservice.servicelayer.client.ClientCredentials; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.InstitutionDAO; | ||||||
|  | @ -38,12 +35,21 @@ import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.beans.factory.annotation.Qualifier; | import org.springframework.beans.factory.annotation.Qualifier; | ||||||
| import org.springframework.context.annotation.Lazy; | import org.springframework.context.annotation.Lazy; | ||||||
|  | import org.springframework.http.HttpEntity; | ||||||
|  | import org.springframework.http.HttpHeaders; | ||||||
|  | import org.springframework.http.HttpMethod; | ||||||
|  | import org.springframework.http.HttpStatus; | ||||||
|  | import org.springframework.http.MediaType; | ||||||
|  | import org.springframework.http.ResponseEntity; | ||||||
| import org.springframework.security.crypto.password.PasswordEncoder; | import org.springframework.security.crypto.password.PasswordEncoder; | ||||||
| import org.springframework.security.oauth2.common.OAuth2AccessToken; | import org.springframework.security.oauth2.common.OAuth2AccessToken; | ||||||
| import org.springframework.security.oauth2.provider.ClientDetails; | import org.springframework.security.oauth2.provider.ClientDetails; | ||||||
| import org.springframework.security.oauth2.provider.client.BaseClientDetails; | import org.springframework.security.oauth2.provider.client.BaseClientDetails; | ||||||
| import org.springframework.security.oauth2.provider.token.TokenStore; | import org.springframework.security.oauth2.provider.token.TokenStore; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.util.LinkedMultiValueMap; | ||||||
|  | import org.springframework.util.MultiValueMap; | ||||||
|  | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
|  | @ -51,6 +57,7 @@ import java.io.OutputStream; | ||||||
| import java.io.PipedInputStream; | import java.io.PipedInputStream; | ||||||
| import java.io.PipedOutputStream; | import java.io.PipedOutputStream; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.util.Base64; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  | @ -316,19 +323,48 @@ public class ClientConfigServiceImpl implements ClientConfigService { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void flushClientConfigData(final BulkActionEvent event) { |     public boolean checkAccess(SebClientConfig config) { | ||||||
|         try { |         if(!config.isActive()) { | ||||||
|             final BulkAction bulkAction = event.getBulkAction(); |             return false; | ||||||
| 
 |  | ||||||
|             if (bulkAction.type == BulkActionType.DEACTIVATE || |  | ||||||
|                     bulkAction.type == BulkActionType.HARD_DELETE) { |  | ||||||
| 
 |  | ||||||
|                 bulkAction.extractKeys(EntityType.SEB_CLIENT_CONFIGURATION) |  | ||||||
|                         .forEach(this::flushClientConfigData); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         } catch (final Exception e) { |         try { | ||||||
|             log.error("Unexpected error while trying to flush ClientConfig data ", e); |             RestTemplate restTemplate = new RestTemplate(); | ||||||
|  |             String externalServerURL = webserviceInfo.getExternalServerURL() + | ||||||
|  |                     API.OAUTH_TOKEN_ENDPOINT; | ||||||
|  | 
 | ||||||
|  |             MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); | ||||||
|  |             headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); | ||||||
|  |             ClientCredentials credentials = sebClientConfigDAO | ||||||
|  |                     .getSebClientCredentials(config.getModelId()) | ||||||
|  |                     .getOrThrow(); | ||||||
|  |             CharSequence plainClientSecret = clientCredentialService.getPlainClientSecret(credentials); | ||||||
|  |             String basicAuth = credentials.clientId + | ||||||
|  |                     String.valueOf(Constants.COLON) + | ||||||
|  |                     plainClientSecret; | ||||||
|  |             String encoded = Base64.getEncoder() | ||||||
|  |                     .encodeToString(basicAuth.getBytes()); | ||||||
|  | 
 | ||||||
|  |             headers.add(HttpHeaders.AUTHORIZATION, "Basic " + encoded); | ||||||
|  |             HttpEntity<String> entity = new HttpEntity<>( | ||||||
|  |                     "grant_type=client_credentials&scope=read write", | ||||||
|  |                     headers); | ||||||
|  | 
 | ||||||
|  |             ResponseEntity<String> exchange = restTemplate.exchange( | ||||||
|  |                     externalServerURL, | ||||||
|  |                     HttpMethod.POST, | ||||||
|  |                     entity, | ||||||
|  |                     String.class); | ||||||
|  | 
 | ||||||
|  |             if (exchange.getStatusCode().value() == HttpStatus.OK.value()) { | ||||||
|  |                 return true; | ||||||
|  |             } else { | ||||||
|  |                 log.warn("Failed to check access SebClientConfig {} response: {}", config, exchange.getStatusCode()); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             log.warn("Failed to check access for SebClientConfig: {} cause: {}", config, e.getMessage()); | ||||||
|  |             return false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl; | package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | @ -93,6 +94,17 @@ public class ClientIndicatorFactory { | ||||||
|                 final PingIntervalClientIndicator pingIndicator = this.applicationContext |                 final PingIntervalClientIndicator pingIndicator = this.applicationContext | ||||||
|                         .getBean(PingIntervalClientIndicator.class); |                         .getBean(PingIntervalClientIndicator.class); | ||||||
|                 pingIndicator.hidden = true; |                 pingIndicator.hidden = true; | ||||||
|  |                 final Indicator indicator = new Indicator( | ||||||
|  |                         null, | ||||||
|  |                         clientConnection.examId, | ||||||
|  |                         "hidden_ping_indicator", | ||||||
|  |                         IndicatorType.LAST_PING, | ||||||
|  |                         "", | ||||||
|  |                         Arrays.asList(new Indicator.Threshold(5000d, ""))); | ||||||
|  |                 pingIndicator.init( | ||||||
|  |                         indicator, | ||||||
|  |                         clientConnection.id, | ||||||
|  |                         this.enableCaching); | ||||||
|                 result.add(pingIndicator); |                 result.add(pingIndicator); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,7 +38,6 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator { | ||||||
| 
 | 
 | ||||||
|     long pingErrorThreshold; |     long pingErrorThreshold; | ||||||
|     boolean missingPing = false; |     boolean missingPing = false; | ||||||
| 
 |  | ||||||
|     boolean hidden = false; |     boolean hidden = false; | ||||||
| 
 | 
 | ||||||
|     public PingIntervalClientIndicator(final ClientEventExtensionMapper clientEventExtensionMapper) { |     public PingIntervalClientIndicator(final ClientEventExtensionMapper clientEventExtensionMapper) { | ||||||
|  |  | ||||||
|  | @ -95,6 +95,8 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent, | ||||||
|             filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); |             filterMap.putIfAbsent(API.PARAM_INSTITUTION_ID, String.valueOf(institutionId)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         try { | ||||||
|  | 
 | ||||||
|             return this.paginationService.getPage( |             return this.paginationService.getPage( | ||||||
|                     pageNumber, |                     pageNumber, | ||||||
|                     pageSize, |                     pageSize, | ||||||
|  | @ -102,6 +104,10 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent, | ||||||
|                     getSQLTableOfEntity().name(), |                     getSQLTableOfEntity().name(), | ||||||
|                     () -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess)) |                     () -> this.clientEventDAO.allMatchingExtended(filterMap, this::hasReadAccess)) | ||||||
|                     .getOrThrow(); |                     .getOrThrow(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |             throw e; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | @ -118,7 +124,7 @@ public class ClientEventController extends ReadonlyEntityController<ClientEvent, | ||||||
|     protected GrantEntity toGrantEntity(final ClientEvent entity) { |     protected GrantEntity toGrantEntity(final ClientEvent entity) { | ||||||
|         return this.examDAO |         return this.examDAO | ||||||
|                 .byClientConnection(entity.connectionId) |                 .byClientConnection(entity.connectionId) | ||||||
|                 .getOrThrow(); |                 .get(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ import org.springframework.web.bind.annotation.PathVariable; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
| import org.springframework.web.bind.annotation.RequestMethod; | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
|  | import org.springframework.web.client.RestTemplate; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.ServletOutputStream; | import javax.servlet.ServletOutputStream; | ||||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||||
|  | @ -144,6 +145,15 @@ public class SebClientConfigController extends ActivatableEntityController<SebCl | ||||||
|                 .map(this::checkPasswordMatch); |                 .map(this::checkPasswordMatch); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Override | ||||||
|  |     protected Result<SebClientConfig> notifySaved(SebClientConfig entity) { | ||||||
|  |         if (entity.isActive()) { | ||||||
|  |             // try to get access token for SEB client | ||||||
|  |             sebClientConfigService.checkAccess(entity); | ||||||
|  |         } | ||||||
|  |         return super.notifySaved(entity); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private SebClientConfig checkPasswordMatch(final SebClientConfig entity) { |     private SebClientConfig checkPasswordMatch(final SebClientConfig entity) { | ||||||
|         Collection<APIMessage> errors = new ArrayList<>(); |         Collection<APIMessage> errors = new ArrayList<>(); | ||||||
|         if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.encryptSecretConfirm)) { |         if (entity.hasEncryptionSecret() && !entity.encryptSecret.equals(entity.encryptSecretConfirm)) { | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; | ||||||
| import org.springframework.security.oauth2.provider.OAuth2Authentication; | import org.springframework.security.oauth2.provider.OAuth2Authentication; | ||||||
| import org.springframework.security.oauth2.provider.token.DefaultTokenServices; | import org.springframework.security.oauth2.provider.token.DefaultTokenServices; | ||||||
| 
 | 
 | ||||||
|  | // TODO check if we can apply some caching here to get better performance for SEB client connection attempts | ||||||
| public class DefaultTokenServicesFallback extends DefaultTokenServices { | public class DefaultTokenServicesFallback extends DefaultTokenServices { | ||||||
| 
 | 
 | ||||||
|     private static final Logger log = LoggerFactory.getLogger(DefaultTokenServicesFallback.class); |     private static final Logger log = LoggerFactory.getLogger(DefaultTokenServicesFallback.class); | ||||||
|  | @ -29,22 +30,22 @@ public class DefaultTokenServicesFallback extends DefaultTokenServices { | ||||||
|             return super.createAccessToken(authentication); |             return super.createAccessToken(authentication); | ||||||
|         } catch (final DuplicateKeyException e) { |         } catch (final DuplicateKeyException e) { | ||||||
| 
 | 
 | ||||||
|             log.info( |             log.warn( | ||||||
|                     "Catched DuplicateKeyException, try to handle it by trying to get the already stored access token after waited some time"); |                     "Caught DuplicateKeyException, try to handle it by trying to get the already stored access token after waited some time"); | ||||||
| 
 | 
 | ||||||
|             final String clientName = authentication.getName(); |             final String clientName = authentication.getName(); | ||||||
|             if (StringUtils.isNotBlank(clientName)) { |             if (StringUtils.isNotBlank(clientName)) { | ||||||
| 
 | 
 | ||||||
|                 // wait a second... |                 // wait some time... | ||||||
|                 try { |                 try { | ||||||
|                     Thread.sleep(1000); |                     Thread.sleep(500); | ||||||
|                 } catch (final InterruptedException e1) { |                 } catch (final InterruptedException e1) { | ||||||
|                     log.warn("Failed to sleep: {}", e1.getMessage()); |                     log.warn("Failed to sleep: {}", e1.getMessage()); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 final OAuth2AccessToken accessToken = this.getAccessToken(authentication); |                 final OAuth2AccessToken accessToken = this.getAccessToken(authentication); | ||||||
|                 if (accessToken != null) { |                 if (accessToken != null) { | ||||||
|                     log.info("Found original accees token for client: {} token: {}", clientName, accessToken); |                     log.debug("Found original access token for client: {} ", clientName); | ||||||
|                     return accessToken; |                     return accessToken; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ sebserver.init.adminaccount.gen-on-init=false | ||||||
| sebserver.webservice.distributed=false | sebserver.webservice.distributed=false | ||||||
| sebserver.webservice.http.scheme=http | sebserver.webservice.http.scheme=http | ||||||
| sebserver.webservice.http.external.servername= | sebserver.webservice.http.external.servername= | ||||||
| sebserver.webservice.http.external.port= | sebserver.webservice.http.external.port=${server.port} | ||||||
| sebserver.webservice.http.redirect.gui=/gui | sebserver.webservice.http.redirect.gui=/gui | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -175,7 +175,7 @@ INSERT INTO configuration_attribute VALUES | ||||||
|     (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), |     (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), |     (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), |     (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), | ||||||
|     (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, 'NSTemporaryDirectory'), |     (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, 'F'), | ||||||
|     (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), |     (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), | ||||||
|     (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), |     (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'), |     (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|  | @ -263,7 +263,7 @@ INSERT INTO configuration_attribute VALUES | ||||||
|     (927, 'mobileStatusBarAppearanceExtended', 'SINGLE_SELECTION', null, '0,1,2,3,4', null, null, '1'), |     (927, 'mobileStatusBarAppearanceExtended', 'SINGLE_SELECTION', null, '0,1,2,3,4', null, null, '1'), | ||||||
|     (928, 'newBrowserWindowShowURL', 'SINGLE_SELECTION', null, '0,1,2,3', null, null, '1'), |     (928, 'newBrowserWindowShowURL', 'SINGLE_SELECTION', null, '0,1,2,3', null, null, '1'), | ||||||
|     (929, 'pinEmbeddedCertificates', 'CHECKBOX', null, null, null, null, 'false'), |     (929, 'pinEmbeddedCertificates', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (930, 'sendBrowserExamKey', 'CHECKBOX', null, null, null, null, 'false'), |     (930, 'sendBrowserExamKey', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (931, 'showNavigationButtons', 'CHECKBOX', null, null, null, null, 'false'), |     (931, 'showNavigationButtons', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (932, 'showScanQRCodeButton', 'CHECKBOX', null, null, null, null, 'false'), |     (932, 'showScanQRCodeButton', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (933, 'startResource', 'TEXT_FIELD', null, null, null, null, ''), |     (933, 'startResource', 'TEXT_FIELD', null, null, null, null, ''), | ||||||
|  |  | ||||||
|  | @ -198,7 +198,7 @@ INSERT IGNORE INTO configuration_attribute VALUES | ||||||
|     (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), |     (304, 'enablePrivateClipboard', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), |     (305, 'enableLogging', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), |     (306, 'logDirectoryWin', 'TEXT_FIELD', null, null, null, null, ''), | ||||||
|     (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, 'NSTemporaryDirectory'), |     (307, 'logDirectoryOSX', 'TEXT_FIELD', null, null, null, null, ''), | ||||||
|     (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), |     (308, 'minMacOSVersion', 'SINGLE_SELECTION', null, '0,1,2,3,4,5,6,7', null, null, '0'), | ||||||
|     (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), |     (309, 'enableAppSwitcherCheck', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'), |     (310, 'forceAppFolderInstall', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|  | @ -286,7 +286,7 @@ INSERT IGNORE INTO configuration_attribute VALUES | ||||||
|     (927, 'mobileStatusBarAppearanceExtended', 'SINGLE_SELECTION', null, '0,1,2,3,4', null, null, '1'), |     (927, 'mobileStatusBarAppearanceExtended', 'SINGLE_SELECTION', null, '0,1,2,3,4', null, null, '1'), | ||||||
|     (928, 'newBrowserWindowShowURL', 'SINGLE_SELECTION', null, '0,1,2,3', null, null, '1'), |     (928, 'newBrowserWindowShowURL', 'SINGLE_SELECTION', null, '0,1,2,3', null, null, '1'), | ||||||
|     (929, 'pinEmbeddedCertificates', 'CHECKBOX', null, null, null, null, 'false'), |     (929, 'pinEmbeddedCertificates', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (930, 'sendBrowserExamKey', 'CHECKBOX', null, null, null, null, 'false'), |     (930, 'sendBrowserExamKey', 'CHECKBOX', null, null, null, null, 'true'), | ||||||
|     (931, 'showNavigationButtons', 'CHECKBOX', null, null, null, null, 'false'), |     (931, 'showNavigationButtons', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (932, 'showScanQRCodeButton', 'CHECKBOX', null, null, null, null, 'false'), |     (932, 'showScanQRCodeButton', 'CHECKBOX', null, null, null, null, 'false'), | ||||||
|     (933, 'startResource', 'TEXT_FIELD', null, null, null, null, ''), |     (933, 'startResource', 'TEXT_FIELD', null, null, null, null, ''), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti